Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] input: pxa27x-keypad: bug fix of getting scan code
From: Chao Xie @ 2014-01-27  4:41 UTC (permalink / raw)
  To: linux-arm-kernel

From: Chao Xie <chao.xie@marvell.com>

The rows of pxa27x-keypad used by each boards are not fixed.
So in the driver, it will get the rows from DT and register
the keymap as:
matrix_keypad_build_keymap(keymap_data, NULL,
                           pdata->matrix_key_rows,
                           pdata->matrix_key_cols,
                           keypad->keycodes, input_dev);

But the scan code is gotten as
MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
It is not correct. Fix it as
MATRIX_SCAN_CODE(row, col, keypad->row_shift);

row_shift is calculated from pdata->matrix_key_rows.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/input/keyboard/pxa27x_keypad.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index d8241ba..8da3eb0 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -113,6 +113,7 @@ struct pxa27x_keypad {
 
 	/* state row bits of each column scan */
 	uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
+	uint32_t row_shift;
 	uint32_t direct_key_state;
 
 	unsigned int direct_key_mask;
@@ -139,6 +140,7 @@ static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad,
 	pdata->matrix_key_rows = rows;
 	pdata->matrix_key_cols = cols;
 
+	keypad->row_shift = get_count_order(pdata->matrix_key_cols);
 	error = matrix_keypad_build_keymap(NULL, NULL,
 					   pdata->matrix_key_rows,
 					   pdata->matrix_key_cols,
@@ -359,6 +361,7 @@ static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
 	if (error)
 		return error;
 
+	keypad->row_shift = get_count_order(pdata->matrix_key_cols);
 	/*
 	 * The keycodes may not only include matrix keys but also the direct
 	 * or rotary keys.
@@ -467,7 +470,8 @@ scan:
 			if ((bits_changed & (1 << row)) == 0)
 				continue;
 
-			code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
+			code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+
 			input_event(input_dev, EV_MSC, MSC_SCAN, code);
 			input_report_key(input_dev, keypad->keycodes[code],
 					 new_state[col] & (1 << row));
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH] dma: mmp_pdma: add IRQF_SHARED when request irq
From: Chao Xie @ 2014-01-27  1:44 UTC (permalink / raw)
  To: linux-arm-kernel

From: Chao Xie <chao.xie@marvell.com>

For some SOCes use mmp_pdma, they have several dma controllers
sharing same irq.
So add IRQF_SHARED to flag when request irq. It can make multiple
controllers share the same irq.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
---
 drivers/dma/mmp_pdma.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 32e58ee..b86415b 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -866,8 +866,8 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq)
 	phy->base = pdev->base;
 
 	if (irq) {
-		ret = devm_request_irq(pdev->dev, irq, mmp_pdma_chan_handler, 0,
-				       "pdma", phy);
+		ret = devm_request_irq(pdev->dev, irq, mmp_pdma_chan_handler,
+				       IRQF_SHARED, "pdma", phy);
 		if (ret) {
 			dev_err(pdev->dev, "channel request irq fail!\n");
 			return ret;
@@ -964,8 +964,8 @@ static int mmp_pdma_probe(struct platform_device *op)
 	if (irq_num != dma_channels) {
 		/* all chan share one irq, demux inside */
 		irq = platform_get_irq(op, 0);
-		ret = devm_request_irq(pdev->dev, irq, mmp_pdma_int_handler, 0,
-				       "pdma", pdev);
+		ret = devm_request_irq(pdev->dev, irq, mmp_pdma_int_handler,
+				       IRQF_SHARED, "pdma", pdev);
 		if (ret)
 			return ret;
 	}
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 4/4] ARM: OMAP2+: Add pdata quirk for sys_clkout2 for omap3 DBB056
From: Christoph Fritz @ 2014-01-27  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390782797-24105-1-git-send-email-chf.fritz@googlemail.com>

Full device tree support for clock control, especially to set frequencies,
is not yet accomplished. Until then, configure the 24Mhz of sys_clkout2 to
feed an USB-Hub here.

Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
---
 arch/arm/mach-omap2/pdata-quirks.c |   37 ++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 435a823..e36ac3f 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -172,6 +172,43 @@ static void __init am3517_evm_legacy_init(void)
 
 static void __init omap3_dbb056_legacy_init(void)
 {
+	struct clk *clkout2;
+	struct clk *cm96fck;
+
+	/* Reparent clkout2 to 96M_FCK */
+	pr_info("%s: Late Reparent clkout2 to 96M_FCK\n", __func__);
+	clkout2 = clk_get(NULL, "clkout2_src_ck");
+	if (clkout2 < 0) {
+		pr_err("a83x-quirk: couldn't get clkout2_src_ck\n");
+		return;
+	}
+	cm96fck = clk_get(NULL, "cm_96m_fck");
+	if (cm96fck < 0) {
+		pr_err("a83x-quirk: couldn't get cm_96m_fck\n");
+		return;
+	}
+	if (clk_set_parent(clkout2, cm96fck) < 0) {
+		pr_err("a83x-quirk: couldn't reparent clkout2_src_ck\n");
+		return;
+	}
+
+	/* Set clkout2 to 24MHz for internal usb hub*/
+	pr_info("%s: Set clkout2 to 24MHz for internal usb hub\n", __func__);
+	clkout2 = clk_get(NULL, "sys_clkout2");
+	if (clkout2 < 0) {
+		pr_err("%s: couldn't get sys_clkout2\n", __func__);
+		return;
+	}
+	if (clk_set_rate(clkout2, 24000000) < 0) {
+		pr_err("%s: couldn't set sys_clkout2 rate\n", __func__);
+		return;
+	}
+	if (clk_prepare_enable(clkout2) < 0) {
+		pr_err("%s: couldn't enable sys_clkout2\n", __func__);
+		return;
+	}
+
+	/* Initialize display */
 	omap3_dbb056_display_init_of();
 }
 #endif /* CONFIG_ARCH_OMAP3 */
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 3/4] ARM: OMAP2+: add legacy display for omap3 DBB056
From: Christoph Fritz @ 2014-01-27  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390782797-24105-1-git-send-email-chf.fritz@googlemail.com>

Full device tree support for omapdss is not yet accomplished. Until
then, init display by legacy platform code.

Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
---
 arch/arm/mach-omap2/dss-common.c   |   49 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/dss-common.h   |    1 +
 arch/arm/mach-omap2/pdata-quirks.c |    8 +++++-
 3 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c
index dadccc9..b8b4e39 100644
--- a/arch/arm/mach-omap2/dss-common.c
+++ b/arch/arm/mach-omap2/dss-common.c
@@ -257,3 +257,52 @@ void __init omap3_igep2_display_init_of(void)
 	platform_device_register(&omap3_igep2_tfp410_device);
 	platform_device_register(&omap3_igep2_dvi_connector_device);
 }
+
+/* OMAP3 dbb056 data */
+
+#define DBB056_DISPLAY_ENABLE_GPIO 156
+
+static const struct display_timing dbb056_lcd_videomode = {
+	.pixelclock = { 0, 19200000, 0 },
+
+	.hactive = { 0, 640, 0 },
+	.hfront_porch = { 0, 104, 0 },
+	.hback_porch = { 0, 8, 0 },
+	.hsync_len = { 0, 8, 0 },
+
+	.vactive = { 0, 480, 0 },
+	.vfront_porch = { 0, 104, 0 },
+	.vback_porch = { 0, 8, 0 },
+	.vsync_len = { 0, 8, 0 },
+
+	.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+		DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+};
+
+static struct panel_dpi_platform_data dbb056_lcd_pdata = {
+	.name                   = "lcd",
+	.source                 = "dpi.0",
+
+	.data_lines             = 18,
+
+	.display_timing         = &dbb056_lcd_videomode,
+
+	.enable_gpio            = DBB056_DISPLAY_ENABLE_GPIO,
+	.backlight_gpio         = -1,
+};
+
+static struct platform_device dbb056_lcd_device = {
+	.name                   = "panel-dpi",
+	.id                     = 0,
+	.dev.platform_data      = &dbb056_lcd_pdata,
+};
+
+static struct omap_dss_board_info omap_dbb056_dss_data = {
+	.default_display_name = "lcd",
+};
+
+void __init omap3_dbb056_display_init_of(void)
+{
+	platform_device_register(&dbb056_lcd_device);
+	omap_display_init(&omap_dbb056_dss_data);
+}
diff --git a/arch/arm/mach-omap2/dss-common.h b/arch/arm/mach-omap2/dss-common.h
index a9becf0..a125b55 100644
--- a/arch/arm/mach-omap2/dss-common.h
+++ b/arch/arm/mach-omap2/dss-common.h
@@ -9,5 +9,6 @@
 void __init omap4_panda_display_init_of(void);
 void __init omap_4430sdp_display_init_of(void);
 void __init omap3_igep2_display_init_of(void);
+void __init omap3_dbb056_display_init_of(void);
 
 #endif
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 3d5b24d..435a823 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -169,6 +169,11 @@ static void __init am3517_evm_legacy_init(void)
 	omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET);
 	omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */
 }
+
+static void __init omap3_dbb056_legacy_init(void)
+{
+	omap3_dbb056_display_init_of();
+}
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #ifdef CONFIG_ARCH_OMAP4
@@ -259,10 +264,11 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 static struct pdata_init pdata_quirks[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP3
 	{ "compulab,omap3-sbc-t3730", omap3_sbc_t3730_legacy_init, },
+	{ "incostartec,omap3-lilly-dbb056", omap3_dbb056_legacy_init, },
+	{ "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
 	{ "nokia,omap3-n900", hsmmc2_internal_input_clk, },
 	{ "nokia,omap3-n9", hsmmc2_internal_input_clk, },
 	{ "nokia,omap3-n950", hsmmc2_internal_input_clk, },
-	{ "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
 	{ "ti,omap3-evm-37xx", omap3_evm_legacy_init, },
 	{ "ti,omap3-zoom3", omap3_zoom_legacy_init, },
 	{ "ti,am3517-evm", am3517_evm_legacy_init, },
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/4] ARM: dts: omap3: Add support for INCOstartec DBB056 baseboard
From: Christoph Fritz @ 2014-01-27  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390782797-24105-1-git-send-email-chf.fritz@googlemail.com>

INCOstartec LILLY-DBB056 is a carrier board (baseboard) for
computer-on-module LILLY-A83X.

This patch adds device-tree support for most of its features.

Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
---
 arch/arm/boot/dts/Makefile               |    1 +
 arch/arm/boot/dts/omap3-lilly-dbb056.dts |  165 ++++++++++++++++++++++++++++++
 2 files changed, 166 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap3-lilly-dbb056.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index cfd364d..b449161 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -215,6 +215,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	omap3-gta04.dtb \
 	omap3-igep0020.dtb \
 	omap3-igep0030.dtb \
+	omap3-lilly-dbb056.dtb \
 	omap3-zoom3.dtb \
 	omap4-panda.dtb \
 	omap4-panda-a4.dtb \
diff --git a/arch/arm/boot/dts/omap3-lilly-dbb056.dts b/arch/arm/boot/dts/omap3-lilly-dbb056.dts
new file mode 100644
index 0000000..89e2b68
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-lilly-dbb056.dts
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 Christoph Fritz <chf.fritzc@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+/dts-v1/;
+
+#include "omap3-lilly-a83x.dtsi"
+
+/ {
+	model = "INCOstartec LILLY-DBB056 (DM3730)";
+	compatible = "incostartec,omap3-lilly-dbb056", "incostartec,omap3-lilly-a83x", "ti,omap36xx", "ti,omap3";
+};
+
+&twl {
+	vaux2: regulator-vaux2 {
+		compatible = "ti,twl4030-vaux2";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		regulator-always-on;
+	};
+};
+
+&vpll2 {
+        /* Needed for DSS */
+        regulator-name = "vdds_dsi";
+};
+
+&omap3_pmx_core {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_pins>;
+
+	lan9117_pins: pinmux_lan9117_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2114, PIN_INPUT | MUX_MODE4)   /* cam_fld.gpio_98 */
+		>;
+	};
+
+	gpio4_pins: pinmux_gpio4_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x212e, PIN_INPUT | MUX_MODE4)   /* cam_xclkb.gpio_111 -> sja1000 IRQ */
+		>;
+	};
+
+	lcd_pins: pinmux_lcd_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+			OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+			OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+			OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+			OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+			OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+			OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+			OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+			OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+			OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+			OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+			OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+			OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+			OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+			OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+			OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+			OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+			OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+			OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+			OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+			OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+			OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+			OMAP3_CORE1_IOPAD(0x218c, PIN_OUTPUT | MUX_MODE4)   /* mcbsp1_clk.gpio_156 -> enable DSS */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc2_clk.sdmmc2_clk */
+			OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc2_cmd.sdmmc2_cmd */
+			OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc2_dat0.sdmmc2_dat0 */
+			OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc2_dat1.sdmmc2_dat1 */
+			OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc2_dat2.sdmmc2_dat2 */
+			OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc2_dat3.sdmmc2_dat3 */
+			OMAP3_CORE1_IOPAD(0x2164, PIN_OUTPUT | MUX_MODE1)   /* sdmmc2_dat4.sdmmc2_dir_dat0 */
+			OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE1)   /* sdmmc2_dat5.sdmmc2_dir_dat1 */
+			OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE1)   /* sdmmc2_dat6.sdmmc2_dir_cmd */
+			OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT | MUX_MODE1)    /* sdmmc2_dat7.sdmmc2_clkin */
+			OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLUP | MUX_MODE4)   /* uart3_cts_rctx.gpio_163 -> wp */
+			OMAP3_CORE1_IOPAD(0x219c, PIN_INPUT_PULLUP | MUX_MODE4)   /* uart3_rts_sd.gpio_164 -> cd */
+		>;
+	};
+
+	spi1_pins: pinmux_spi1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0)   /* mcspi1_clk.mcspi1_clk */
+			OMAP3_CORE1_IOPAD(0x21ca, PIN_INPUT | MUX_MODE0)   /* mcspi1_simo.mcspi1_simo */
+			OMAP3_CORE1_IOPAD(0x21cc, PIN_INPUT | MUX_MODE0)   /* mcspi1_somi.mcspi1_somi */
+			OMAP3_CORE1_IOPAD(0x21ce, PIN_INPUT_PULLDOWN | MUX_MODE0)   /* mcspi1_cs0.mcspi1_cs0 */
+		>;
+	};
+};
+
+&gpio4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpio4_pins>;
+};
+
+&mmc2 {
+	status = "okay";
+	bus-width = <4>;
+	vmmc-supply = <&vmmc1>;
+	cd-gpios = <&gpio6 4 0>;   /* gpio_164 */
+	wp-gpios = <&gpio6 3 0>;   /* gpio_163 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+	ti,dual-volt;
+};
+
+&mcspi1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+};
+
+&gpmc {
+	ranges = <0 0 0x30000000 0x1000000>,   /* nand assigned by COM a83x */
+		<4 0 0x20000000 0x01000000>,
+		<7 0 0x15000000 0x01000000>;   /* eth assigend by COM a83x */
+
+	ethernet at 4,0 {
+		compatible = "smsc,lan9117", "smsc,lan9115";
+		bank-width = <2>;
+		gpmc,mux-add-data = <2>;
+		gpmc,cs-on-ns = <10>;
+		gpmc,cs-rd-off-ns = <65>;
+		gpmc,cs-wr-off-ns = <65>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <10>;
+		gpmc,adv-wr-off-ns = <10>;
+		gpmc,oe-on-ns = <10>;
+		gpmc,oe-off-ns = <65>;
+		gpmc,we-on-ns = <10>;
+		gpmc,we-off-ns = <65>;
+		gpmc,rd-cycle-ns = <100>;
+		gpmc,wr-cycle-ns = <100>;
+		gpmc,access-ns = <60>;
+		gpmc,page-burst-access-ns = <5>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <75>;
+		gpmc,wr-data-mux-bus-ns = <15>;
+		gpmc,wr-access-ns = <75>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+		vddvario-supply = <&reg_vcc3>;
+		vdd33a-supply = <&reg_vcc3>;
+		reg-io-width = <4>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <2 0x2>;
+		reg = <4 0 0xff>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&lan9117_pins>;
+		phy-mode = "mii";
+		smsc,force-internal-phy;
+	};
+};
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 1/4] ARM: dts: omap3: Add support for INCOstartec a83x module
From: Christoph Fritz @ 2014-01-27  0:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390782797-24105-1-git-send-email-chf.fritz@googlemail.com>

INCOstartec LILLY-A83X module is a TI DM3730xx100 (OMAP3) SoC
computer-on-module.

This patch adds device tree support for most of its features.

Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
---
 arch/arm/boot/dts/omap3-lilly-a83x.dtsi |  459 +++++++++++++++++++++++++++++++
 1 file changed, 459 insertions(+)
 create mode 100644 arch/arm/boot/dts/omap3-lilly-a83x.dtsi

diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
new file mode 100644
index 0000000..6369d9f
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2014 Christoph Fritz <chf.fritzc@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "omap36xx.dtsi"
+
+/ {
+	model = "INCOstartec LILLY-A83X module (DM3730)";
+	compatible = "incostartec,omap3-lilly-a83x", "ti,omap36xx", "ti,omap3";
+
+	chosen {
+			bootargs = "console=ttyO0,115200n8 vt.global_cursor_default=0 consoleblank=0";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x8000000>;   /* 128 MB */
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led1 {
+			label = "lilly-a83x::led1";
+			gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+
+	};
+
+	sound {
+		compatible = "ti,omap-twl4030";
+		ti,model = "lilly-a83x";
+
+		ti,mcbsp = <&mcbsp2>;
+		ti,codec = <&twl_audio>;
+	};
+
+	reg_vcc3: vcc3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	hsusb1_phy: hsusb1_phy {
+		compatible = "usb-nop-xceiv";
+		vcc-supply = <&reg_vcc3>;
+	};
+};
+
+&omap3_pmx_wkup {
+	pinctrl-names = "default";
+
+	lan9221_pins: pinmux_lan9221_pins {
+		pinctrl-single,pins = <
+			OMAP3_WKUP_IOPAD(0x2a5a, PIN_INPUT | MUX_MODE4)   /* reserved.gpio_129 */
+		>;
+	};
+
+	tsc2048_pins: pinmux_tsc2048_pins {
+		pinctrl-single,pins = <
+			OMAP3_WKUP_IOPAD(0x2a16, PIN_INPUT_PULLUP | MUX_MODE4)   /* sys_boot6.gpio_8 */
+		>;
+	};
+
+	mmc1cd_pins: pinmux_mmc1cd_pins {
+		pinctrl-single,pins = <
+			OMAP3_WKUP_IOPAD(0x2a56, PIN_INPUT | MUX_MODE4)   /* reserved.gpio_126 */
+		>;
+	};
+};
+
+&omap3_pmx_core {
+	pinctrl-names = "default";
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0)   /* uart1_tx.uart1_tx */
+			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE0)   /* uart1_rts.uart1_rts */
+			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT | MUX_MODE0)    /* uart1_cts.uart1_cts */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0)    /* uart1_rx.uart1_rx */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2170, PIN_OUTPUT | MUX_MODE1)   /* mcbsp3_clkx.uart2_tx */
+			OMAP3_CORE1_IOPAD(0x2172, PIN_INPUT | MUX_MODE1)    /* mcbsp3_fsx.uart2_rx */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)    /* uart3_rx_irrx.uart3_rx_irrx */
+			OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)   /* uart3_tx_irtx.uart3_tx_irtx */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21ba ,PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c1_scl.i2c1_scl */
+			OMAP3_CORE1_IOPAD(0x21bc ,PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c1_sda.i2c1_sda */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT | MUX_MODE0)   /* i2c2_scl.i2c2_scl */
+			OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT | MUX_MODE0)   /* i2c2_sda.i2c2_sda */
+		>;
+	};
+
+	i2c3_pins: pinmux_i2c3_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0)   /* i2c3_scl.i2c3_scl */
+			OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0)   /* i2c3_sda.i2c3_sda */
+		>;
+	};
+
+	hsusb1_pins: pinmux_hsusb1_pins {
+		pinctrl-single,pins = <
+
+			/* GPIO 182 controls USB-Hub reset. But USB-Phy its
+			 * reset can't be controlled. So we clamp this GPIO to
+			 * high (PIN_OFF_OUTPUT_HIGH) to always enable USB-Hub.
+			 */
+
+			OMAP3_CORE1_IOPAD(0x21de, PIN_OUTPUT_PULLUP | PIN_OFF_OUTPUT_HIGH | MUX_MODE4)   /* mcspi2_cs1.gpio_182 */
+		>;
+	};
+
+	hsusb_otg_pins: pinmux_hsusb_otg_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21a2, PIN_INPUT | MUX_MODE0)   /* hsusb0_clk.hsusb0_clk */
+			OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0)  /* hsusb0_stp.hsusb0_stp */
+			OMAP3_CORE1_IOPAD(0x21a6, PIN_INPUT | MUX_MODE0)   /* hsusb0_dir.hsusb0_dir */
+			OMAP3_CORE1_IOPAD(0x21a8, PIN_INPUT | MUX_MODE0)   /* hsusb0_nxt.hsusb0_nxt */
+			OMAP3_CORE1_IOPAD(0x21aa, PIN_INPUT | MUX_MODE0)   /* hsusb0_data0.hsusb0_data0 */
+			OMAP3_CORE1_IOPAD(0x21ac, PIN_INPUT | MUX_MODE0)   /* hsusb0_data1.hsusb0_data1 */
+			OMAP3_CORE1_IOPAD(0x21ae, PIN_INPUT | MUX_MODE0)   /* hsusb0_data2.hsusb0_data2 */
+			OMAP3_CORE1_IOPAD(0x21b0, PIN_INPUT | MUX_MODE0)   /* hsusb0_data3.hsusb0_data3 */
+			OMAP3_CORE1_IOPAD(0x21b2, PIN_INPUT | MUX_MODE0)   /* hsusb0_data4.hsusb0_data4 */
+			OMAP3_CORE1_IOPAD(0x21b4, PIN_INPUT | MUX_MODE0)   /* hsusb0_data5.hsusb0_data5 */
+			OMAP3_CORE1_IOPAD(0x21b6, PIN_INPUT | MUX_MODE0)   /* hsusb0_data6.hsusb0_data6 */
+			OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT | MUX_MODE0)   /* hsusb0_data7.hsusb0_data7 */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc1_clk.sdmmc1_clk */
+			OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc1_cmd.sdmmc1_cmd */
+			OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc1_dat0.sdmmc1_dat0 */
+			OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc1_dat1.sdmmc1_dat1 */
+			OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc1_dat2.sdmmc1_dat2 */
+			OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0)   /* sdmmc1_dat3.sdmmc1_dat3 */
+		>;
+	};
+
+	spi2_pins: pinmux_spi2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE0)   /* mcspi2_clk.mcspi2_clk */
+			OMAP3_CORE1_IOPAD(0x21d8, PIN_INPUT_PULLDOWN | MUX_MODE0)   /* mcspi2_simo.mcspi2_simo */
+			OMAP3_CORE1_IOPAD(0x21da, PIN_INPUT_PULLDOWN | MUX_MODE0)   /* mcspi2_somi.mcspi2_somi */
+			OMAP3_CORE1_IOPAD(0x21dc, PIN_OUTPUT | MUX_MODE0)   /* mcspi2_cs0.mcspi2_cs0 */
+		>;
+	};
+};
+
+&omap3_pmx_core2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+			&hsusb1_2_pins
+	>;
+
+	hsusb1_2_pins: pinmux_hsusb1_2_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3)  /* etk_clk.hsusb1_stp */
+			OMAP3630_CORE2_IOPAD(0x25da, PIN_INPUT | MUX_MODE3)   /* etk_ctl.hsusb1_clk */
+			OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE3)   /* etk_d0.hsusb1_data0 */
+			OMAP3630_CORE2_IOPAD(0x25de, PIN_INPUT | MUX_MODE3)   /* etk_d1.hsusb1_data1 */
+			OMAP3630_CORE2_IOPAD(0x25e0, PIN_INPUT | MUX_MODE3)   /* etk_d2.hsusb1_data2 */
+			OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT | MUX_MODE3)   /* etk_d3.hsusb1_data7 */
+			OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT | MUX_MODE3)   /* etk_d4.hsusb1_data4 */
+			OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT | MUX_MODE3)   /* etk_d5.hsusb1_data5 */
+			OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT | MUX_MODE3)   /* etk_d6.hsusb1_data6 */
+			OMAP3630_CORE2_IOPAD(0x25ea, PIN_INPUT | MUX_MODE3)   /* etk_d7.hsusb1_data3 */
+			OMAP3630_CORE2_IOPAD(0x25ec, PIN_INPUT | MUX_MODE3)   /* etk_d8.hsusb1_dir */
+			OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE3)   /* etk_d9.hsusb1_nxt */
+		>;
+	};
+
+	gpio1_pins: pinmux_gpio1_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25fa, PIN_OUTPUT_PULLDOWN | MUX_MODE4)   /* etk_d15.gpio_29 */
+		>;
+	};
+
+};
+
+&gpio1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpio1_pins>;
+};
+
+&gpio6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb1_pins>;
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	twl: twl at 48 {
+		reg = <0x48>;
+		interrupts = <7>;   /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+
+		twl_audio: audio {
+			compatible = "ti,twl4030-audio";
+			codec {
+			};
+		};
+	};
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&twl {
+	vmmc1: regulator-vmmc1 {
+		regulator-always-on;
+	};
+
+	vdd1: regulator-vdd1 {
+		regulator-always-on;
+	};
+
+	vdd2: regulator-vdd2 {
+		regulator-always-on;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <2600000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+};
+
+&i2c3 {
+	clock-frequency = <2600000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins>;
+		gpiom1: gpio at 20 {
+			compatible = "mcp,mcp23017";
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x20>;
+		};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&mmc1 {
+	cd-gpios = <&gpio4 30 IRQ_TYPE_LEVEL_LOW>;
+	cd-inverted;
+	vmmc-supply = <&vmmc1>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins &mmc1cd_pins>;
+	cap-sdio-irq;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&mcspi2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2_pins>;
+
+	tsc2046 at 0 {
+		reg = <0>;   /* CS0 */
+		compatible = "ti,tsc2046";
+		interrupt-parent = <&gpio1>;
+		interrupts = <8 0>;   /* boot6 / gpio_8 */
+		spi-max-frequency = <1000000>;
+		pendown-gpio = <&gpio1 8 0>;
+		vcc-supply = <&reg_vcc3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tsc2048_pins>;
+
+		ti,x-min = <300>;
+		ti,x-max = <3000>;
+		ti,y-min = <600>;
+		ti,y-max = <3600>;
+		ti,x-plate-ohms = <80>;
+		ti,pressure-max = <255>;
+		ti,swap-xy;
+
+		linux,wakeup;
+	};
+};
+
+&usbhsehci {
+	phys = <&hsusb1_phy>;
+};
+
+&usbhshost {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb1_2_pins>;
+	num-ports = <2>;
+	port1-mode = "ehci-phy";
+};
+
+&usb_otg_hs {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb_otg_pins>;
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
+
+&gpmc {
+	ranges = <0 0 0x30000000 0x1000000>,
+		<7 0 0x15000000 0x01000000>;
+
+	nand at 0,0 {
+		reg = <0 0 0x1000000>;
+		nand-bus-width = <16>;
+		ti,nand-ecc-opt = "bch8";
+		/* no elm on omap3 */
+
+		gpmc,mux-add-data = <0>;
+		gpmc,device-nand;
+		gpmc,device-width = <2>;
+		gpmc,wait-pin = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,burst-length= <4>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <100>;
+		gpmc,cs-wr-off-ns = <100>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <100>;
+		gpmc,adv-wr-off-ns = <100>;
+		gpmc,oe-on-ns = <5>;
+		gpmc,oe-off-ns = <75>;
+		gpmc,we-on-ns = <5>;
+		gpmc,we-off-ns = <75>;
+		gpmc,rd-cycle-ns = <100>;
+		gpmc,wr-cycle-ns = <100>;
+		gpmc,access-ns = <60>;
+		gpmc,page-burst-access-ns = <5>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-delay-ns = <50>;
+		gpmc,wr-data-mux-bus-ns = <75>;
+		gpmc,wr-access-ns = <155>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition at 0 {
+			label = "MLO";
+			reg = <0 0x80000>;
+		};
+
+		partition at 0x80000 {
+			label = "u-boot";
+			reg = <0x80000 0x1e0000>;
+		};
+
+		partition at 0x260000 {
+			label = "u-boot-environment";
+			reg = <0x260000 0x20000>;
+		};
+
+		partition at 0x280000 {
+			label = "kernel";
+			reg = <0x280000 0x500000>;
+		};
+
+		partition at 0x780000 {
+			label = "filesystem";
+			reg = <0x780000 0xf880000>;
+		};
+	};
+
+	ethernet at 7,0 {
+		compatible = "smsc,lan9221", "smsc,lan9115";
+		bank-width = <2>;
+		gpmc,mux-add-data = <2>;
+		gpmc,cs-on-ns = <10>;
+		gpmc,cs-rd-off-ns = <60>;
+		gpmc,cs-wr-off-ns = <60>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <10>;
+		gpmc,adv-wr-off-ns = <10>;
+		gpmc,oe-on-ns = <10>;
+		gpmc,oe-off-ns = <60>;
+		gpmc,we-on-ns = <10>;
+		gpmc,we-off-ns = <60>;
+		gpmc,rd-cycle-ns = <100>;
+		gpmc,wr-cycle-ns = <100>;
+		gpmc,access-ns = <50>;
+		gpmc,page-burst-access-ns = <5>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <75>;
+		gpmc,wr-data-mux-bus-ns = <15>;
+		gpmc,wr-access-ns = <75>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+		vddvario-supply = <&reg_vcc3>;
+		vdd33a-supply = <&reg_vcc3>;
+		reg-io-width = <4>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <1 0x2>;
+		reg = <7 0 0xff>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&lan9221_pins>;
+		phy-mode = "mii";
+	};
+};
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v3 0/4] ARM: add omap3 INCOstartec board support
From: Christoph Fritz @ 2014-01-27  0:33 UTC (permalink / raw)
  To: linux-arm-kernel

This set of patches adds board support for an omap3 system from INCOstartec.
It's based on next-20140124.

Due to a regression since next-20140115 the following errors are present:

 - pin sys_clkout2, which gets configured to 24 Mhz by the fourth patch
   in this set, erroneously outputs only 12 Mhz.
   Just out of curiosity, configuring it to 48 Mhz puts out desired 24 Mhz.

 - omap_dss, which gets configured by the third patch in this set, fails
   to do 'dss_set_fck_rate(fck);' in
   drivers/video/omap2/dss/dss.c:dss_setup_default_clock() which leads to:

    | omapdss_dss: probe of omapdss_dss failed with error -22
    | omapdss CORE error: Failed to initialize DSS platform driver
    | panel-dpi panel-dpi.0: failed to find video source 'dpi.0

  Both regressions seem to have something to do with the clock framework. 
  Could this be related to the DT clock conversion patches?

Changes compared to previous version (v3):
 - rebased on next-20140124
 - use pinctrl macros OMAP3_WKUP_IOPAD, OMAP3_CORE1_IOPAD
   and OMAP3630_CORE2_IOPAD
 - use same convention for all comments
 - dss-quirk: name twl4030 VPLL2 regulator as vdds_dsi
 - fix style
Changes compared to previous version (v2):
 - rebased on next-20140122 from next-20140115
 - using omap36xx.dtsi instead of unsupported 1ghz omap37xx100
Initial version (v1):
 - based on next-20140115

Christoph Fritz (4):
  ARM: dts: omap3: Add support for INCOstartec a83x module
  ARM: dts: omap3: Add support for INCOstartec DBB056 baseboard
  ARM: OMAP2+: add legacy display for omap3 DBB056
  ARM: OMAP2+: Add pdata quirk for sys_clkout2 for omap3 DBB056

 arch/arm/boot/dts/Makefile               |    1 +
 arch/arm/boot/dts/omap3-lilly-a83x.dtsi  |  459 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/omap3-lilly-dbb056.dts |  165 +++++++++++
 arch/arm/mach-omap2/dss-common.c         |   49 ++++
 arch/arm/mach-omap2/dss-common.h         |    1 +
 arch/arm/mach-omap2/pdata-quirks.c       |   45 ++-
 6 files changed, 719 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/omap3-lilly-a83x.dtsi
 create mode 100644 arch/arm/boot/dts/omap3-lilly-dbb056.dts

-- 
1.7.10.4

^ permalink raw reply

* [PATCH v2 1/5] ARM: dts: omap3: Add support for INCOstartec a83x module
From: Christoph Fritz @ 2014-01-27  0:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52E0207E.3050900@ti.com>

Hi Nishanth,

 thanks for reviewing this patch. Please see my comments below.

On Wed, Jan 22, 2014 at 01:48:14PM -0600, Nishanth Menon wrote:
> On 01/22/2014 01:04 PM, Christoph Fritz wrote:

> > +	regulators {
> > +		compatible = "simple-bus";
> Shrug, just moving the fixed regulator to root also will do the job,
> not sure simple-bus much sense here :(
> 

will get fixed

> > +		reg_vcc3: vcc3 {
> > +                        compatible = "regulator-fixed";
> > +                        regulator-name = "VCC3";
> > +                        regulator-min-microvolt = <3300000>;
> > +                        regulator-max-microvolt = <3300000>;
> > +                        regulator-always-on;
> > +		};
> > +	};
> > +
> > +	hsusb1_phy: hsusb1_phy {
> > +		compatible = "usb-nop-xceiv";
> > +		vcc-supply = <&reg_vcc3>;
> > +	};
> > +};
> > +
> > +&omap3_pmx_wkup {
> > +	pinctrl-names = "default";
> > +
> > +	lan9221_pins: pinmux_lan9221_pins {
> > +		pinctrl-single,pins = <
> > +			0x5A (PIN_INPUT | MUX_MODE4)   /* gpio_129 */
> umm.. you might want to follow the convention as you followed later in
> comments.

My convention was: If pin can be described unique with one name,
don't use two. But I'll change that to be uniform with all comments.

> > +		>;
> > +	};
> > +
> > +	tsc2048_pins: pinmux_tsc2048_pins {
> > +		pinctrl-single,pins = <
> > +			0x16 (PIN_INPUT_PULLUP | MUX_MODE4)   /* gpio_8 */
> umm.. you might want to follow the convention as you followed later in
> comments.

will get fixed

> > +		>;
> > +	};
> > +
> > +	mmc1cd_pins: pinmux_mmc1cd_pins {
> > +		pinctrl-single,pins = <
> > +			0x56 (PIN_INPUT | MUX_MODE4)   /* gpio_126 */
> umm.. you might want to follow the convention as you followed later in
> comments.

will get fixed

> > +		>;
> > +	};
> > +};
> > +
> > +&omap3_pmx_core {
> > +	pinctrl-names = "default";
> > +
> > +	gpio1_pins: pinmux_gpio1_pins {
> > +		pinctrl-single,pins = <
> > +			0x5ca (PIN_OUTPUT_PULLDOWN | MUX_MODE4)   /* gpio_29 */
> umm.. you might want to follow the convention as you followed later in
> comments.

will get fixed

> > +		>;
> > +	};
> > +
> > +	uart1_pins: pinmux_uart1_pins {
> > +		pinctrl-single,pins = <
> > +			0x14c (PIN_OUTPUT | MUX_MODE0)   /* uart1_tx.uart1_tx */
> > +			0x14e (PIN_OUTPUT | MUX_MODE0)   /* uart1_rts.uart1_rts */
> > +			0x150 (PIN_INPUT | MUX_MODE0)    /* uart1_cts.uart1_cts */
> > +			0x152 (PIN_INPUT | MUX_MODE0)    /* uart1_rx.uart1_rx */
> > +		>;
> you may be interested in include/dt-bindings/pinctrl/omap.h
> OMAP3_CORE1_IOPAD, OMAP3_CORE2_IOPAD as needed here.

will get fixed

> > +	};
> > +
> > +	uart2_pins: pinmux_uart2_pins {
> > +		pinctrl-single,pins = <
> > +			0x140 (PIN_OUTPUT | MUX_MODE1)   /* mcbsp3_clkx.uart2_tx */
> > +			0x142 (PIN_INPUT | MUX_MODE1)    /* mcbsp3_fsx.uart2_rx */
> > +		>;
> > +	};
> > +
> > +	uart3_pins: pinmux_uart3_pins {
> > +		pinctrl-single,pins = <
> > +			0x16e (PIN_INPUT | MUX_MODE0)    /* uart3_rx_irrx.uart3_rx_irrx */
> > +			0x170 (PIN_OUTPUT | MUX_MODE0)   /* uart3_tx_irtx.uart3_tx_irtx */
> > +		>;
> > +	};
> > +
> > +	i2c1_pins: pinmux_i2c1_pins {
> > +		pinctrl-single,pins = <
> > +			0x18a (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c1_scl */
> > +			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c1_sda */
> umm.. you might want to follow the convention as you followed
> elsewhere in comments.

will get fixed

> > +		>;
> > +	};
> > +
> > +	i2c2_pins: pinmux_i2c2_pins {
> > +		pinctrl-single,pins = <
> > +			0x18e (PIN_INPUT | MUX_MODE0)   /* i2c2_scl.i2c2_scl */
> > +			0x190 (PIN_INPUT | MUX_MODE0)   /* i2c2_sda.i2c2_sda */
> > +		>;
> > +	};
> > +
> > +	i2c3_pins: pinmux_i2c3_pins {
> > +		pinctrl-single,pins = <
> > +			0x192 (PIN_INPUT | MUX_MODE0)   /* i2c3_scl.i2c3_scl */
> > +			0x194 (PIN_INPUT | MUX_MODE0)   /* i2c3_sda.i2c3_sda */
> > +		>;
> > +	};
> > +
> > +	hsusb1_pins: pinmux_hsusb1_pins {
> > +		pinctrl-single,pins = <
> > +			0x5a8 (PIN_OUTPUT | MUX_MODE3)  /* etk_clk.hsusb1_stp */
> &omap3_pmx_core2 and OMAP3_CORE2_IOPAD probably here. and probably see
> similar usage in other board dtsi.

will get fixed

> > +
> > +#include "twl4030.dtsi"
> > +#include "twl4030_omap3.dtsi"
> > +
> > +&twl {
> > +	vmmc1: regulator-vmmc1 {
> > +		regulator-always-on;
> > +	};
> > +
> > +	vdd1: regulator-vdd1 {
> > +		regulator-always-on;
> > +	};
> > +
> > +	vdd2: regulator-vdd2 {
> > +		regulator-always-on;
> > +	};
> I hope you have covered all required regulators here including the
> ones you might need for IO.1P8 perhaps?

Yes, I rechecked all and it's fine now. IO.1P8 was low due to a
hardware error which is now fixed.

> > +
> > +&mmc1 {
> > +	reg = <0x4809c000 0x400>;
> little curious as to why this. is that to override length 0x200 to
> 0x400? that belongs to soc.dtsi then.

This is a remnant from last year and will get purged.

Let me reroll this patch in a new v3 set.

Thanks
  -- Christoph

^ permalink raw reply

* [PATCH v2 4/5] ARM: OMAP2+: Add pdata quirk for sys_clkout2 for omap3 DBB056
From: Christoph Fritz @ 2014-01-27  0:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52E01D01.2010709@ti.com>

Hi Nishanth,

 thanks for reviewing this patch. Please see my comments below.

On Wed, Jan 22, 2014 at 01:33:21PM -0600, Nishanth Menon wrote:
> On 01/22/2014 01:04 PM, Christoph Fritz wrote:
> > Full device tree support for clock control is not yet accomplished. Until
> > then, configure the 24Mhz of sys_clkout2 to feed an USB-Hub here.
> > 
> > Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
> > ---
> >  arch/arm/mach-omap2/pdata-quirks.c |   37 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 37 insertions(+)
> > 
> > diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
> > index a58590f..9ef7ca8 100644
> > --- a/arch/arm/mach-omap2/pdata-quirks.c
> > +++ b/arch/arm/mach-omap2/pdata-quirks.c
> > @@ -171,6 +171,43 @@ static void __init am3517_evm_legacy_init(void)
> >  }
> >  static void __init omap3_dbb056_legacy_init(void)
> >  {
> > +	struct clk *clkout2;
> > +	struct clk *cm96fck;
> > +
> > +	/* Reparent clkout2 to 96M_FCK */
> > +	pr_info("a83x-quirk: Late Reparent clkout2 to 96M_FCK\n");
> what'd be a83x?

It's the computer-on-module name. Will get changed to __func__.

> > +	clkout2 = clk_get(NULL, "clkout2_src_ck");
> > +	if(clkout2 < 0) {
> > +		pr_err("a83x-quirk: couldn't get clkout2_src_ck\n");
> > +		return;
> > +	}
> > +	cm96fck = clk_get(NULL, "cm_96m_fck");
> > +	if(cm96fck < 0) {
> > +		pr_err("a83x-quirk: couldn't get cm_96m_fck\n");
> > +		return;
> > +	}
> > +	if(clk_set_parent(clkout2, cm96fck) < 0) {
> > +		pr_err("a83x-quirk: couldn't reparent clkout2_src_ck\n");
> > +		return;
> > +	}
> yep - we have bunch of similar code in drivers/clk/ti -> but we'd need
> a generic property to handle this.

This whole quirk of configuring sys_clkout2 in a platform file will
go away. Tero is planning to post some RFC patches to configure this
by DT.

> > +
> > +	/* Set clkout2 to 24MHz for internal usb hub*/
> > +	pr_info("a83x-quirk: Set clkout2 to 24MHz for internal usb hub\n");
> > +	clkout2 = clk_get(NULL, "sys_clkout2");
> > +	if(clkout2 < 0) {
> > +		pr_err("a83x-quirk: couldn't get sys_clkout2\n");
> > +		return;
> > +	}
> > +	if(clk_set_rate(clkout2, 24000000) < 0) {
> same here.
> > +		printk(KERN_ERR "board-omap3evm: couldn't set sys_clkout2 rate\n");
> "board-omap3evm:" copy paste?
> any reason why not pr_err?

will get fixed

> > +		return;
> > +	}
> > +	if(clk_prepare_enable(clkout2) < 0) {
> > +		pr_err("a83x-quirk: couldn't enable sys_clkout2\n");
> > +		return;
> > +	}
> > +
> > +	/* Initialize display */
> >  	omap3_dbb056_display_init_of();
> >  }
> >  #endif /* CONFIG_ARCH_OMAP3 */
> > 
> 
> looking at the coding style, I assume we'd missed running
> checkpatch.pl --strict?

Let me reroll this patch in a new v3 set.

Thanks
  -- Christoph

^ permalink raw reply

* [PATCHv3 00/41] OMAPDSS: DT support v3
From: Javier Martinez Canillas @ 2014-01-26 23:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390301833-24944-1-git-send-email-tomi.valkeinen@ti.com>

Hi Tomi,

On Tue, Jan 21, 2014 at 7:56 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> Hi,
>
> Here's version 3 of the DSS DT series.
>
> The previous version can be found from:
>
> v1: http://permalink.gmane.org/gmane.linux.ports.arm.omap/108249
> v2: http://permalink.gmane.org/gmane.linux.ports.arm.omap/108866
>
> The main changes to v2 are:
>
> - DT Binding documentation
> - OMAP2 DSS support
> - Split DSI register space
> - DSS nodes disabled by default
> - Hack to have generic DT bindings but OMAP specific drivers (for now)
>
> This series can also be found from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git work/dss-dt-review-3
>

I tested this branch on my DM3730 IGEPv2 and output display is working
correctly.

Tested-by: Javier Martinez Canillas <javier@dowhile0.org>

>  Tomi
>
> Javier Martinez Canillas (1):
>   ARM: omap3-igep0020.dts: add display information
>
> Sebastian Reichel (1):
>   OMAPDSS: acx565akm: Add DT support
>
> Tomi Valkeinen (39):
>   ARM: OMAP2+: add omapdss_init_of()
>   ARM: OMAP2+: DT 'compatible' tweak for displays
>   OMAPDSS: add 'label' support for DT
>   OMAPDSS: get dssdev->alias from DT alias
>   OMAPFB: clean up default display search
>   OMAPFB: search for default display with DT alias
>   OMAPDSS: add of helpers
>   OMAPDSS: Improve regulator names for DT
>   OMAPDSS: Add DT support to DSS
>   OMAPDSS: Add DT support to DISPC
>   OMAPDSS: Add DT support to HDMI
>   OMAPDSS: Add DT support to VENC
>   OMAPDSS: Add DT support to DSI
>   OMAPDSS: panel-dsi-cm: Add DT support
>   OMAPDSS: encoder-tfp410: Add DT support
>   OMAPDSS: connector-dvi: Add DT support
>   OMAPDSS: encoder-tpd12s015: Add DT support
>   OMAPDSS: hdmi-connector: Add DT support
>   OMAPDSS: panel-dpi: Add DT support
>   OMAPDSS: connector-analog-tv: Add DT support
>   ARM: omap2.dtsi: add omapdss information
>   ARM: omap3.dtsi: add omapdss information
>   ARM: omap4.dtsi: add omapdss information
>   ARM: omap4-panda.dts: add display information
>   ARM: omap4-sdp.dts: add display information
>   ARM: omap3-beagle.dts: add display information
>   ARM: omap3-beagle-xm.dts: add display information
>   ARM: omap3-n900.dts: add display information
>   OMAPDSS: remove DT hacks for regulators
>   ARM: OMAP2+: remove pdata quirks for displays
>   Doc/DT: Add OMAP DSS DT Bindings
>   Doc/DT: Add DT binding documentation for Analog TV Connector
>   Doc/DT: Add DT binding documentation for DVI Connector
>   Doc/DT: Add DT binding documentation for HDMI Connector
>   Doc/DT: Add DT binding documentation for MIPI DPI Panel
>   Doc/DT: Add DT binding documentation for MIPI DSI CM Panel
>   Doc/DT: Add DT binding documentation for Sony acx565akm panel
>   Doc/DT: Add DT binding documentation for TFP410 encoder
>   Doc/DT: Add DT binding documentation for tpd12s015 encoder
>
>  .../bindings/video/analog-tv-connector.txt         |  23 +++
>  .../devicetree/bindings/video/dvi-connector.txt    |  26 +++
>  .../devicetree/bindings/video/hdmi-connector.txt   |  23 +++
>  .../devicetree/bindings/video/panel-dpi.txt        |  43 ++++
>  .../devicetree/bindings/video/panel-dsi-cm.txt     |  26 +++
>  .../devicetree/bindings/video/sony,acx565akm.txt   |  28 +++
>  .../devicetree/bindings/video/ti,omap-dss.txt      | 197 ++++++++++++++++++
>  .../devicetree/bindings/video/ti,omap2-dss.txt     |  54 +++++
>  .../devicetree/bindings/video/ti,omap3-dss.txt     |  73 +++++++
>  .../devicetree/bindings/video/ti,omap4-dss.txt     |  99 +++++++++
>  .../devicetree/bindings/video/ti,tfp410.txt        |  41 ++++
>  .../devicetree/bindings/video/ti,tpd12s015.txt     |  44 ++++
>  .../devicetree/bindings/video/video-ports.txt      |  22 ++
>  arch/arm/boot/dts/omap2.dtsi                       |  31 +++
>  arch/arm/boot/dts/omap3-beagle-xm.dts              | 119 +++++++++++
>  arch/arm/boot/dts/omap3-beagle.dts                 | 116 +++++++++++
>  arch/arm/boot/dts/omap3-igep0020.dts               |  59 +++++-
>  arch/arm/boot/dts/omap3-n900.dts                   |  70 ++++++-
>  arch/arm/boot/dts/omap3.dtsi                       |  42 ++++
>  arch/arm/boot/dts/omap4-panda-common.dtsi          | 119 ++++++++++-
>  arch/arm/boot/dts/omap4-sdp.dts                    | 107 +++++++++-
>  arch/arm/boot/dts/omap4.dtsi                       |  65 ++++++
>  arch/arm/mach-omap2/board-generic.c                |   4 +
>  arch/arm/mach-omap2/common.h                       |   3 +
>  arch/arm/mach-omap2/display.c                      | 132 ++++++++++++
>  arch/arm/mach-omap2/dss-common.c                   | 224 ---------------------
>  arch/arm/mach-omap2/pdata-quirks.c                 |   3 -
>  .../video/omap2/displays-new/connector-analog-tv.c |  43 +++-
>  drivers/video/omap2/displays-new/connector-dvi.c   |  43 ++++
>  drivers/video/omap2/displays-new/connector-hdmi.c  |  30 +++
>  drivers/video/omap2/displays-new/encoder-tfp410.c  |  43 +++-
>  .../video/omap2/displays-new/encoder-tpd12s015.c   |  56 ++++++
>  drivers/video/omap2/displays-new/panel-dpi.c       |  64 +++++-
>  drivers/video/omap2/displays-new/panel-dsi-cm.c    |  65 +++++-
>  .../omap2/displays-new/panel-sony-acx565akm.c      |  33 ++-
>  drivers/video/omap2/dss/Makefile                   |   2 +-
>  drivers/video/omap2/dss/dispc.c                    |   8 +
>  drivers/video/omap2/dss/display.c                  |  28 ++-
>  drivers/video/omap2/dss/dpi.c                      |  47 +++++
>  drivers/video/omap2/dss/dsi.c                      | 147 +++++++++++++-
>  drivers/video/omap2/dss/dss-of.c                   | 159 +++++++++++++++
>  drivers/video/omap2/dss/dss.c                      |  64 ++++++
>  drivers/video/omap2/dss/dss.h                      |   6 +
>  drivers/video/omap2/dss/hdmi4.c                    |  14 +-
>  drivers/video/omap2/dss/sdi.c                      |  45 +++++
>  drivers/video/omap2/dss/venc.c                     |  66 +++++-
>  drivers/video/omap2/omapfb/omapfb-main.c           |  67 ++++--
>  include/video/omapdss.h                            |  14 ++
>  48 files changed, 2550 insertions(+), 287 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/video/analog-tv-connector.txt
>  create mode 100644 Documentation/devicetree/bindings/video/dvi-connector.txt
>  create mode 100644 Documentation/devicetree/bindings/video/hdmi-connector.txt
>  create mode 100644 Documentation/devicetree/bindings/video/panel-dpi.txt
>  create mode 100644 Documentation/devicetree/bindings/video/panel-dsi-cm.txt
>  create mode 100644 Documentation/devicetree/bindings/video/sony,acx565akm.txt
>  create mode 100644 Documentation/devicetree/bindings/video/ti,omap-dss.txt
>  create mode 100644 Documentation/devicetree/bindings/video/ti,omap2-dss.txt
>  create mode 100644 Documentation/devicetree/bindings/video/ti,omap3-dss.txt
>  create mode 100644 Documentation/devicetree/bindings/video/ti,omap4-dss.txt
>  create mode 100644 Documentation/devicetree/bindings/video/ti,tfp410.txt
>  create mode 100644 Documentation/devicetree/bindings/video/ti,tpd12s015.txt
>  create mode 100644 Documentation/devicetree/bindings/video/video-ports.txt
>  create mode 100644 drivers/video/omap2/dss/dss-of.c
>
> --
> 1.8.3.2
>

Thanks a lot and best regards,
Javier

^ permalink raw reply

* Freescale FEC packet loss
From: Ben Hutchings @ 2014-01-26 21:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401262012.13051.marex@denx.de>

On Sun, 2014-01-26 at 20:12 +0100, Marek Vasut wrote:
> On Sunday, January 26, 2014 at 07:56:30 PM, Ben Hutchings wrote:
> > On Wed, 2014-01-22 at 22:55 +0100, Marek Vasut wrote:
> > > Hi guys,
> > > 
> > > I am running stock Linux 3.13 on i.MX6Q SabreLite board. The CPU is
> > > i.MX6Q TO 1.0 .
> > > 
> > > I am hitting a WARNING when I use the FEC ethernet to transfer data, thus
> > > I started investigating this problem. TL;DR I am not able to figure this
> > > problem out, so I am not attaching a patch :-(
> > > 
> > > Steps to reproduce:
> > > -------------------
> > > 1) Boot stock Linux 3.13 on i.MX6Q SabreLite board
> > > 2) Plug in an SD card into one of the SD slots (I use the full-size one)
> > > 3) Plug in an USB stick into one of the USB ports (I use the upper one)
> > > 4) Plug in an ethernet cable into the board
> > > 
> > >    -> Connect the other side into a gigabit-capable PC
> > 
> > [...]
> > 
> > I think there are known problems with 1000BASE-T on the Sabre Lite
> > board.
> 
> This is MX6-wide thing, not sabrelite specific actually.
> 
> > Two possible workarounds are to limit the PHY to 100BASE-TX
> > (should be doable with ethtool) or force it to be clock master for
> > 1000BASE-T (requires a driver patch).
> 
> Can you please elaborate on the later ? I don't quite understand that.

1000BASE-T uses all 4 pairs in both directions at the same time, which
requires that both ends transmit symbols synchronously.  As part of the
autonegotiation protocol, they decide which is the clock master (using a
local clock generator) and which is the clock slave (generating a clock
from the received signal).  A PHY can be configured to support only one
of these roles.

> > The vendor kernel apparently does both!
> 
> More like the vendor kernel papers over this bug.
> 
> > Matthew Garrett has been trying to implement a workaround in a
> > clean way.
> 
> Do you have any pointers about this please ?

http://thread.gmane.org/gmane.linux.drivers.devicetree/58570

Ben.

-- 
Ben Hutchings
If the facts do not conform to your theory, they must be disposed of.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140126/3121cd37/attachment.sig>

^ permalink raw reply

* linux-next: manual merge of the clk tree with the arm-soc tree
From: Tomasz Figa @ 2014-01-26 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52E57744.5030807@gmail.com>

On 26.01.2014 21:59, Tomasz Figa wrote:
> Hi Stephen,
>
> On 13.01.2014 06:06, Stephen Rothwell wrote:
>> Hi Mike,
>>
>> Today's linux-next merge of the clk tree got a conflict in
>> drivers/clk/samsung/clk-exynos4.c between commit 86576fbe201b ("clk:
>> samsung: exynos4: Fix definition of div_mmc_pre4 divider") from the
>> arm-soc tree and commit 2d7382375054 ("clk: exynos4: replace clock ID
>> private enums with IDs from DT header") from the clk tree.
>>
>> I fixed it up (see below) and can carry the fix as necessary (no action
>> is required).
>
> It seems like somehow this fix-up has been lost in action and the
> conflict ended up being merged incorrectly in linux-next. Could you take
> a look?

Ehh, it's a false alarm fortunately. I've been looking at wrong ref, 
silly me. Sorry for the noise.

Best regards,
Tomasz

^ permalink raw reply

* linux-next: manual merge of the clk tree with the arm-soc tree
From: Tomasz Figa @ 2014-01-26 20:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140113160630.cf720268510f5e0931c24284@canb.auug.org.au>

Hi Stephen,

On 13.01.2014 06:06, Stephen Rothwell wrote:
> Hi Mike,
>
> Today's linux-next merge of the clk tree got a conflict in
> drivers/clk/samsung/clk-exynos4.c between commit 86576fbe201b ("clk:
> samsung: exynos4: Fix definition of div_mmc_pre4 divider") from the
> arm-soc tree and commit 2d7382375054 ("clk: exynos4: replace clock ID
> private enums with IDs from DT header") from the clk tree.
>
> I fixed it up (see below) and can carry the fix as necessary (no action
> is required).

It seems like somehow this fix-up has been lost in action and the 
conflict ended up being merged incorrectly in linux-next. Could you take 
a look?

Best regards,
Tomasz

^ permalink raw reply

* [PATCH] arm64: add workaround for ambiguous C99 stdint.h types
From: Ard Biesheuvel @ 2014-01-26 20:30 UTC (permalink / raw)
  To: linux-arm-kernel

In a way similar to ARM commit 09096f6a0ee2 ("ARM: 7822/1: add workaround
for ambiguous C99 stdint.h types"), this patch redefines the macros that
are used in stdint.h so its definitions of uint64_t and int64_t are
compatible with those of the kernel.

In order to do so, drop types.h from generic-y and create a specific arm64
version identical to the generic one with just the #define overrides added.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/include/asm/Kbuild  |  1 -
 arch/arm64/include/asm/types.h | 26 ++++++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/types.h

diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index d0ff25de67ca..93e0653e8c65 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -44,7 +44,6 @@ generic-y += termbits.h
 generic-y += termios.h
 generic-y += topology.h
 generic-y += trace_clock.h
-generic-y += types.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
diff --git a/arch/arm64/include/asm/types.h b/arch/arm64/include/asm/types.h
new file mode 100644
index 000000000000..6519296da003
--- /dev/null
+++ b/arch/arm64/include/asm/types.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_TYPES_H
+#define __ASM_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+/*
+ * For Aarch64, there is some ambiguity in the definition of the types below
+ * between the kernel and GCC itself. This is usually not a big deal, but it
+ * causes trouble when including GCC's version of 'stdint.h' (this is the file
+ * that gets included when you #include <stdint.h> on a -ffreestanding build).
+ * As this file also gets included implicitly when including 'arm_neon.h' (the
+ * NEON intrinsics support header), we need the following to work around the
+ * issue if we want to use NEON intrinsics in the kernel.
+ */
+
+#ifdef __INT64_TYPE__
+#undef __INT64_TYPE__
+#define __INT64_TYPE__		__signed__ long long
+#endif
+
+#ifdef __UINT64_TYPE__
+#undef __UINT64_TYPE__
+#define __UINT64_TYPE__		unsigned long long
+#endif
+
+#endif /* __ASM_TYPES_H */
-- 
1.8.3.2

^ permalink raw reply related

* Freescale FEC packet loss
From: Marek Vasut @ 2014-01-26 19:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390762590.2735.39.camel@deadeye.wl.decadent.org.uk>

On Sunday, January 26, 2014 at 07:56:30 PM, Ben Hutchings wrote:
> On Wed, 2014-01-22 at 22:55 +0100, Marek Vasut wrote:
> > Hi guys,
> > 
> > I am running stock Linux 3.13 on i.MX6Q SabreLite board. The CPU is
> > i.MX6Q TO 1.0 .
> > 
> > I am hitting a WARNING when I use the FEC ethernet to transfer data, thus
> > I started investigating this problem. TL;DR I am not able to figure this
> > problem out, so I am not attaching a patch :-(
> > 
> > Steps to reproduce:
> > -------------------
> > 1) Boot stock Linux 3.13 on i.MX6Q SabreLite board
> > 2) Plug in an SD card into one of the SD slots (I use the full-size one)
> > 3) Plug in an USB stick into one of the USB ports (I use the upper one)
> > 4) Plug in an ethernet cable into the board
> > 
> >    -> Connect the other side into a gigabit-capable PC
> 
> [...]
> 
> I think there are known problems with 1000BASE-T on the Sabre Lite
> board.

This is MX6-wide thing, not sabrelite specific actually.

> Two possible workarounds are to limit the PHY to 100BASE-TX
> (should be doable with ethtool) or force it to be clock master for
> 1000BASE-T (requires a driver patch).

Can you please elaborate on the later ? I don't quite understand that.

> The vendor kernel apparently does both!

More like the vendor kernel papers over this bug.

> Matthew Garrett has been trying to implement a workaround in a
> clean way.

Do you have any pointers about this please ?

Best regards,
Marek Vasut

^ permalink raw reply

* Freescale FEC packet loss
From: Ben Hutchings @ 2014-01-26 18:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201401222255.29467.marex@denx.de>

On Wed, 2014-01-22 at 22:55 +0100, Marek Vasut wrote:
> Hi guys,
> 
> I am running stock Linux 3.13 on i.MX6Q SabreLite board. The CPU is i.MX6Q TO 
> 1.0 .
> 
> I am hitting a WARNING when I use the FEC ethernet to transfer data, thus I 
> started investigating this problem. TL;DR I am not able to figure this problem 
> out, so I am not attaching a patch :-(
> 
> Steps to reproduce:
> -------------------
> 1) Boot stock Linux 3.13 on i.MX6Q SabreLite board
> 2) Plug in an SD card into one of the SD slots (I use the full-size one)
> 3) Plug in an USB stick into one of the USB ports (I use the upper one)
> 4) Plug in an ethernet cable into the board
>    -> Connect the other side into a gigabit-capable PC
[...]

I think there are known problems with 1000BASE-T on the Sabre Lite
board.  Two possible workarounds are to limit the PHY to 100BASE-TX
(should be doable with ethtool) or force it to be clock master for
1000BASE-T (requires a driver patch).  The vendor kernel apparently does
both!  Matthew Garrett has been trying to implement a workaround in a
clean way.

Ben.

-- 
Ben Hutchings
If the facts do not conform to your theory, they must be disposed of.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140126/b5b61309/attachment-0001.sig>

^ permalink raw reply

* [PATCH v3 2/5] ASoC: tda998x: add a codec driver for the TDA998x
From: Jean-Francois Moine @ 2014-01-26 18:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1391274627.git.moinejf@free.fr>

This patch adds a CODEC driver for the NXP TDA998x HDMI transmitter.

The CODEC handles both I2S and S/PDIF input and does dynamic input
switch in the TDA998x I2C driver on start/stop audio streaming.

This driver is DT only and it is loaded from its DT description as
a subnode in the TDA998x node.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/gpu/drm/i2c/tda998x_drv.c |   4 +
 sound/soc/codecs/Kconfig          |   6 ++
 sound/soc/codecs/Makefile         |   2 +
 sound/soc/codecs/tda998x.c        | 216 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 228 insertions(+)
 create mode 100644 sound/soc/codecs/tda998x.c

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 2643be4..68f0b7b 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -20,6 +20,7 @@
 #include <linux/hdmi.h>
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/of_platform.h>
 #include <sound/asoundef.h>
 
 #include <drm/drmP.h>
@@ -1387,6 +1388,9 @@ tda998x_encoder_init(struct i2c_client *client,
 		priv->vip_cntrl_2 = video;
 	}
 
+	/* load the optional CODEC */
+	of_platform_populate(np, NULL, NULL, &client->dev);
+
 	return 0;
 
 fail:
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b33b45d..747e387 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -352,6 +352,12 @@ config SND_SOC_STAC9766
 config SND_SOC_TAS5086
 	tristate
 
+config SND_SOC_TDA998X
+	tristate
+	depends on OF
+	default y if DRM_I2C_NXP_TDA998X=y
+	default m if DRM_I2C_NXP_TDA998X=m
+
 config SND_SOC_TLV320AIC23
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..a53d09e 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -62,6 +62,7 @@ snd-soc-sta32x-objs := sta32x.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tda998x-objs := tda998x.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -192,6 +193,7 @@ obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TDA998X)	+= snd-soc-tda998x.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/tda998x.c b/sound/soc/codecs/tda998x.c
new file mode 100644
index 0000000..34d7086
--- /dev/null
+++ b/sound/soc/codecs/tda998x.c
@@ -0,0 +1,216 @@
+/*
+ * ALSA SoC TDA998X driver
+ *
+ * This driver is used by the NXP TDA998x HDMI transmitter.
+ *
+ * Copyright (C) 2014 Jean-Francois Moine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/i2c/tda998x.h>
+
+#define TDA998X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | \
+			SNDRV_PCM_FMTBIT_S32_LE)
+
+struct tda_priv {
+	struct i2c_client *i2c_client;
+	struct snd_soc_codec *codec;
+	u8 ports[2];
+	int dai_id;
+	u8 *eld;
+};
+
+static int tda_get_encoder(struct tda_priv *priv)
+{
+	struct snd_soc_codec *codec = priv->codec;
+	struct device_node *np;
+
+	/* get the parent tda998x device */
+	np = of_get_parent(codec->dev->of_node);
+	if (!np || !of_device_is_compatible(np, "nxp,tda998x")) {
+		dev_err(codec->dev, "no or bad parent!\n");
+		return -EINVAL;
+	}
+	priv->i2c_client = of_find_i2c_device_by_node(np);
+	of_node_put(np);
+	return 0;
+}
+
+static int tda_start_stop(struct tda_priv *priv)
+{
+	int port;
+
+	/* give the audio parameters to the HDMI encoder */
+	if (priv->dai_id == AFMT_I2S)
+		port = priv->ports[0];
+	else
+		port = priv->ports[1];
+	tda998x_audio_update(priv->i2c_client, priv->dai_id, port);
+	return 0;
+}
+
+static int tda_startup(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+	/* memorize the used DAI */
+	priv->dai_id = dai->id;
+
+	/* start the TDA998x audio */
+	return tda_start_stop(priv);
+}
+
+static void tda_shutdown(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+	priv->dai_id = 0;		/* streaming stop */
+	tda_start_stop(priv);
+}
+
+static const struct snd_soc_dai_ops tda_ops = {
+	.startup = tda_startup,
+	.shutdown = tda_shutdown,
+};
+
+static const struct snd_soc_dai_driver tda998x_dai[] = {
+	{
+		.name = "i2s-hifi",
+		.id = AFMT_I2S,
+		.playback = {
+			.stream_name	= "HDMI I2S Playback",
+			.channels_min	= 1,
+			.channels_max	= 8,
+			.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+			.rate_min	= 5512,
+			.rate_max	= 192000,
+			.formats	= TDA998X_FORMATS,
+		},
+		.ops = &tda_ops,
+	},
+	{
+		.name = "spdif-hifi",
+		.id = AFMT_SPDIF,
+		.playback = {
+			.stream_name	= "HDMI SPDIF Playback",
+			.channels_min	= 1,
+			.channels_max	= 2,
+			.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+			.rate_min	= 22050,
+			.rate_max	= 192000,
+			.formats	= TDA998X_FORMATS,
+		},
+		.ops = &tda_ops,
+	},
+};
+
+static const struct snd_soc_dapm_widget tda_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("hdmi-out"),
+};
+static const struct snd_soc_dapm_route tda_routes[] = {
+	{ "hdmi-out", NULL, "HDMI I2S Playback" },
+	{ "hdmi-out", NULL, "HDMI SPDIF Playback" },
+};
+
+static int tda_probe(struct snd_soc_codec *codec)
+{
+	struct tda_priv *priv;
+	struct device_node *np = codec->dev->of_node;
+	int i, j, ret;
+	const char *p;
+
+	priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	snd_soc_codec_set_drvdata(codec, priv);
+	priv->codec = codec;
+
+	/* get the audio input ports (I2s and S/PDIF) */
+	for (i = 0; i < 2; i++) {
+		u32 port;
+
+		ret = of_property_read_u32_index(np, "audio-ports", i, &port);
+		if (ret) {
+			if (i == 0)
+				dev_err(codec->dev,
+					"bad or missing audio-ports\n");
+			break;
+		}
+		ret = of_property_read_string_index(np, "audio-port-names",
+						i, &p);
+		if (ret) {
+			dev_err(codec->dev,
+				"missing audio-port-names[%d]\n", i);
+			break;
+		}
+		if (strcmp(p, "i2s") == 0) {
+			j = 0;
+		} else if (strcmp(p, "spdif") == 0) {
+			j = 1;
+		} else {
+			dev_err(codec->dev,
+				"bad audio-port-names '%s'\n", p);
+			break;
+		}
+		priv->ports[j] = port;
+	}
+
+	/* get the tda998x device */
+	return tda_get_encoder(priv);
+}
+
+static const struct snd_soc_codec_driver soc_codec_tda998x = {
+	.probe = tda_probe,
+	.dapm_widgets = tda_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tda_widgets),
+	.dapm_routes = tda_routes,
+	.num_dapm_routes = ARRAY_SIZE(tda_routes),
+};
+
+static int tda998x_dev_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev,
+				&soc_codec_tda998x,
+				tda998x_dai, ARRAY_SIZE(tda998x_dai));
+}
+
+static int tda998x_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id tda998x_codec_ids[] = {
+	{ .compatible = "nxp,tda998x-codec", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tda998x_codec_ids);
+
+static struct platform_driver tda998x_driver = {
+	.probe		= tda998x_dev_probe,
+	.remove		= tda998x_dev_remove,
+	.driver		= {
+		.name	= "tda998x-codec",
+		.owner	= THIS_MODULE,
+		.of_match_table = tda998x_codec_ids,
+	},
+};
+
+module_platform_driver(tda998x_driver);
+
+MODULE_AUTHOR("Jean-Francois Moine");
+MODULE_DESCRIPTION("TDA998x codec driver");
+MODULE_LICENSE("GPL");
-- 
1.9.rc1

^ permalink raw reply related

* [PATCH v2 2/5] ASoC: tda998x: add a codec driver for TDA998x
From: Jean-Francois Moine @ 2014-01-26 18:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1391081933.git.moinejf@free.fr>

This patch adds a CODEC driver for the NXP TDA998x HDMI transmitter.

The CODEC handles both I2S and S/PDIF input and does dynamic input
switch in the TDA998x I2C driver on audio streaming start/stop.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 sound/soc/codecs/Kconfig   |   6 ++
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tda998x.c | 237 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 245 insertions(+)
 create mode 100644 sound/soc/codecs/tda998x.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b33b45d..747e387 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -352,6 +352,12 @@ config SND_SOC_STAC9766
 config SND_SOC_TAS5086
 	tristate
 
+config SND_SOC_TDA998X
+	tristate
+	depends on OF
+	default y if DRM_I2C_NXP_TDA998X=y
+	default m if DRM_I2C_NXP_TDA998X=m
+
 config SND_SOC_TLV320AIC23
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..a53d09e 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -62,6 +62,7 @@ snd-soc-sta32x-objs := sta32x.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tda998x-objs := tda998x.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -192,6 +193,7 @@ obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TDA998X)	+= snd-soc-tda998x.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/tda998x.c b/sound/soc/codecs/tda998x.c
new file mode 100644
index 0000000..585cdb6
--- /dev/null
+++ b/sound/soc/codecs/tda998x.c
@@ -0,0 +1,237 @@
+/*
+ * ALSA SoC TDA998X driver
+ *
+ * This driver is used by the NXP TDA998x HDMI transmitter.
+ *
+ * Copyright (C) 2014 Jean-Francois Moine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/i2c/tda998x.h>
+
+#define TDA998X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | \
+			SNDRV_PCM_FMTBIT_S32_LE)
+
+struct tda_priv {
+	struct i2c_client *i2c_client;
+	struct snd_soc_codec *codec;
+	u8 ports[2];
+	int dai_id;
+	u8 *eld;
+};
+
+static void tda_get_encoder(struct tda_priv *priv)
+{
+	struct snd_soc_codec *codec = priv->codec;
+	struct device_node *np;
+	struct i2c_client *i2c_client;
+	static const struct of_device_id tda_dt[] = {
+		{ .compatible = "nxp,tda998x" },
+		{ },
+	};
+
+	/* search the tda998x device */
+	np = of_find_matching_node_and_match(NULL, tda_dt, NULL);
+	if (!np || !of_device_is_available(np)) {
+		dev_err(codec->dev, "No tda998x in DT\n");
+		return;
+	}
+	i2c_client = of_find_i2c_device_by_node(np);
+	of_node_put(np);
+	if (!i2c_client) {
+		dev_err(codec->dev, "no tda998x i2c client\n");
+		return;
+	}
+	if (!i2c_get_clientdata(i2c_client)) {
+		dev_err(codec->dev, "tda998x not initialized\n");
+		return;
+	}
+
+	priv->i2c_client = i2c_client;
+}
+
+static int tda_start_stop(struct tda_priv *priv)
+{
+	int port;
+
+	if (!priv->i2c_client) {
+		tda_get_encoder(priv);
+		if (!priv->i2c_client)
+			return -EINVAL;
+	}
+
+	/* give the audio parameters to the HDMI encoder */
+	if (priv->dai_id == AFMT_I2S)
+		port = priv->ports[0];
+	else
+		port = priv->ports[1];
+	tda998x_audio_update(priv->i2c_client, priv->dai_id, port);
+	return 0;
+}
+
+static int tda_startup(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+	/* memorize the used DAI */
+	priv->dai_id = dai->id;
+
+	/* start the TDA998x audio */
+	return tda_start_stop(priv);
+}
+
+static void tda_shutdown(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+	priv->dai_id = 0;		/* streaming stop */
+	tda_start_stop(priv);
+}
+
+static const struct snd_soc_dai_ops tda_ops = {
+	.startup = tda_startup,
+	.shutdown = tda_shutdown,
+};
+
+static const struct snd_soc_dai_driver tda998x_dai[] = {
+    {
+	.name = "i2s-hifi",
+	.id = AFMT_I2S,
+	.playback = {
+		.stream_name	= "HDMI I2S Playback",
+		.channels_min	= 1,
+		.channels_max	= 8,
+		.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+		.rate_min	= 5512,
+		.rate_max	= 192000,
+		.formats	= TDA998X_FORMATS,
+
+	},
+	.ops = &tda_ops,
+    },
+    {
+	.name = "spdif-hifi",
+	.id = AFMT_SPDIF,
+	.playback = {
+		.stream_name	= "HDMI SPDIF Playback",
+		.channels_min	= 1,
+		.channels_max	= 2,
+		.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+		.rate_min	= 22050,
+		.rate_max	= 192000,
+		.formats	= TDA998X_FORMATS,
+	},
+	.ops = &tda_ops,
+    },
+};
+
+static const struct snd_soc_dapm_widget tda_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("hdmi-out"),
+};
+static const struct snd_soc_dapm_route tda_routes[] = {
+	{ "hdmi-out", NULL, "HDMI I2S Playback" },
+	{ "hdmi-out", NULL, "HDMI SPDIF Playback" },
+};
+
+static int tda_probe(struct snd_soc_codec *codec)
+{
+	struct tda_priv *priv;
+	struct device_node *np;
+	int i, j, ret;
+	const char *p;
+
+	priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	snd_soc_codec_set_drvdata(codec, priv);
+	priv->codec = codec;
+
+	/* get the audio input ports (I2s and S/PDIF) */
+	np = codec->dev->of_node;
+	for (i = 0; i < 2; i++) {
+		u32 port;
+
+		ret = of_property_read_u32_index(np, "audio-ports", i, &port);
+		if (ret) {
+			if (i == 0)
+				dev_err(codec->dev,
+					"bad or missing audio-ports\n");
+			break;
+		}
+		ret = of_property_read_string_index(np, "audio-port-names",
+						i, &p);
+		if (ret) {
+			dev_err(codec->dev,
+				"missing audio-port-names[%d]\n", i);
+			break;
+		}
+		if (strcmp(p, "i2s") == 0) {
+			j = 0;
+		} else if (strcmp(p, "spdif") == 0) {
+			j = 1;
+		} else {
+			dev_err(codec->dev,
+				"bad audio-port-names '%s'\n", p);
+			break;
+		}
+		priv->ports[j] = port;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_codec_driver soc_codec_tda998x = {
+	.probe = tda_probe,
+	.dapm_widgets = tda_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tda_widgets),
+	.dapm_routes = tda_routes,
+	.num_dapm_routes = ARRAY_SIZE(tda_routes),
+};
+
+static int tda998x_dev_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev,
+				&soc_codec_tda998x,
+				tda998x_dai, ARRAY_SIZE(tda998x_dai));
+}
+
+static int tda998x_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id tda998x_codec_ids[] = {
+	{ .compatible = "nxp,tda998x-codec", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tda998x_codec_ids);
+
+static struct platform_driver tda998x_driver = {
+	.probe		= tda998x_dev_probe,
+	.remove		= tda998x_dev_remove,
+	.driver		= {
+		.name	= "tda998x-codec",
+		.owner	= THIS_MODULE,
+		.of_match_table = tda998x_codec_ids,
+	},
+};
+
+module_platform_driver(tda998x_driver);
+
+MODULE_AUTHOR("Jean-Francois Moine");
+MODULE_DESCRIPTION("TDA998x codec driver");
+MODULE_LICENSE("GPL");
-- 
1.9.rc1

^ permalink raw reply related

* [PATCH 2/4] ASoC: tda998x: add a codec driver for TDA998x
From: Jean-Francois Moine @ 2014-01-26 18:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1390813480.git.moinejf@free.fr>

This patch adds a CODEC driver for the NXP TDA998x HDMI transmitter.

The CODEC handles both I2S and S/PDIF input and does dynamic input
switch in the TDA998x I2C driver on audio streaming start/stop.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 sound/soc/codecs/Kconfig   |   7 ++
 sound/soc/codecs/Makefile  |   2 +
 sound/soc/codecs/tda998x.c | 227 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 236 insertions(+)
 create mode 100644 sound/soc/codecs/tda998x.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b33b45d..7cec76e 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -71,6 +71,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_STA529 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_TAS5086 if I2C
+	select SND_SOC_TDA998X if I2C
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
 	select SND_SOC_TLV320AIC32X4 if I2C
@@ -352,6 +353,12 @@ config SND_SOC_STAC9766
 config SND_SOC_TAS5086
 	tristate
 
+config SND_SOC_TDA998X
+	tristate
+	depends on OF
+	default y if DRM_I2C_NXP_TDA998X=y
+	default m if DRM_I2C_NXP_TDA998X=m
+
 config SND_SOC_TLV320AIC23
 	tristate
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..a53d09e 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -62,6 +62,7 @@ snd-soc-sta32x-objs := sta32x.o
 snd-soc-sta529-objs := sta529.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tas5086-objs := tas5086.o
+snd-soc-tda998x-objs := tda998x.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
@@ -192,6 +193,7 @@ obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
+obj-$(CONFIG_SND_SOC_TDA998X)	+= snd-soc-tda998x.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)	+= snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)	+= snd-soc-tlv320aic3x.o
diff --git a/sound/soc/codecs/tda998x.c b/sound/soc/codecs/tda998x.c
new file mode 100644
index 0000000..d724f7d
--- /dev/null
+++ b/sound/soc/codecs/tda998x.c
@@ -0,0 +1,227 @@
+/*
+ * ALSA SoC TDA998X driver
+ *
+ * This driver is used by the NXP TDA998x HDMI transmitter.
+ *
+ * Copyright (C) 2014 Jean-Francois Moine
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/i2c/tda998x.h>
+
+#define TDA998X_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
+			SNDRV_PCM_FMTBIT_S20_3LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | \
+			SNDRV_PCM_FMTBIT_S32_LE)
+
+struct tda_priv {
+	struct i2c_client *i2c_client;
+	struct snd_soc_codec *codec;
+	u8 ports[2];
+	int dai_id;
+	u8 *eld;
+};
+
+static void tda_get_encoder(struct tda_priv *priv)
+{
+	struct snd_soc_codec *codec = priv->codec;
+	struct device_node *np;
+	struct i2c_client *i2c_client;
+	static const struct of_device_id tda_dt[] = {
+		{ .compatible = "nxp,tda998x" },
+		{ },
+	};
+
+	/* search the tda998x device */
+	np = of_find_matching_node_and_match(NULL, tda_dt, NULL);
+	if (!np || !of_device_is_available(np)) {
+		dev_err(codec->dev, "No tda998x in DT\n");
+		return;
+	}
+	i2c_client = of_find_i2c_device_by_node(np);
+	of_node_put(np);
+	if (!i2c_client) {
+		dev_err(codec->dev, "no tda998x i2c client\n");
+		return;
+	}
+	if (!i2c_get_clientdata(i2c_client)) {
+		dev_err(codec->dev, "tda998x not initialized\n");
+		return;
+	}
+
+	priv->i2c_client = i2c_client;
+}
+
+static int tda_start_stop(struct tda_priv *priv,
+			int start)
+{
+	int format, port;
+
+	if (!priv->i2c_client) {
+		tda_get_encoder(priv);
+		if (!priv->i2c_client)
+			return -EINVAL;
+	}
+
+	/* give the audio input type and ports to the HDMI encoder */
+	format = start ? priv->dai_id : 0;
+	switch (format) {
+	case AFMT_I2S:
+		port = priv->ports[0];
+		break;
+	default:
+	case AFMT_SPDIF:
+		port = priv->ports[1];
+		break;
+	}
+	tda998x_audio_update(priv->i2c_client, format, port);
+	return 0;
+}
+
+static int tda_startup(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+	/* memorize the used DAI */
+	priv->dai_id = dai->id;
+
+	/* start the TDA998x audio */
+	return tda_start_stop(priv, 1);
+}
+
+static void tda_shutdown(struct snd_pcm_substream *substream,
+			struct snd_soc_dai *dai)
+{
+	struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+
+	priv->dai_id = 0;
+	tda_start_stop(priv, 0);
+}
+
+static const struct snd_soc_dai_ops tda_ops = {
+	.startup = tda_startup,
+	.shutdown = tda_shutdown,
+};
+
+static const struct snd_soc_dai_driver tda998x_dai[] = {
+    {
+	.name = "i2s-hifi",
+	.id = AFMT_I2S,
+	.playback = {
+		.stream_name	= "HDMI I2S Playback",
+		.channels_min	= 1,
+		.channels_max	= 8,
+		.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+		.rate_min	= 5512,
+		.rate_max	= 192000,
+		.formats	= TDA998X_FORMATS,
+
+	},
+	.ops = &tda_ops,
+    },
+    {
+	.name = "spdif-hifi",
+	.id = AFMT_SPDIF,
+	.playback = {
+		.stream_name	= "HDMI SPDIF Playback",
+		.channels_min	= 1,
+		.channels_max	= 2,
+		.rates		= SNDRV_PCM_RATE_CONTINUOUS,
+		.rate_min	= 22050,
+		.rate_max	= 192000,
+		.formats	= TDA998X_FORMATS,
+	},
+	.ops = &tda_ops,
+    },
+};
+
+static const struct snd_soc_dapm_widget tda_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("hdmi-out"),
+};
+static const struct snd_soc_dapm_route tda_routes[] = {
+	{ "hdmi-out", NULL, "HDMI I2S Playback" },
+	{ "hdmi-out", NULL, "HDMI SPDIF Playback" },
+};
+
+static int tda_probe(struct snd_soc_codec *codec)
+{
+	struct tda_priv *priv;
+	struct device_node *np;
+	int i, ret;
+
+	priv = devm_kzalloc(codec->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	snd_soc_codec_set_drvdata(codec, priv);
+	priv->codec = codec;
+
+	/* get the audio input ports (I2s and S/PDIF) */
+	np = codec->dev->of_node;
+	for (i = 0; i < 2; i++) {
+		u32 port;
+
+		ret = of_property_read_u32_index(np, "audio-ports", i, &port);
+		if (ret) {
+			if (i == 0)
+				dev_err(codec->dev,
+					"bad or missing audio-ports\n");
+			break;
+		}
+		priv->ports[i] = port;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_codec_driver soc_codec_tda998x = {
+	.probe = tda_probe,
+	.dapm_widgets = tda_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(tda_widgets),
+	.dapm_routes = tda_routes,
+	.num_dapm_routes = ARRAY_SIZE(tda_routes),
+};
+
+static int tda998x_dev_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev,
+				&soc_codec_tda998x,
+				tda998x_dai, ARRAY_SIZE(tda998x_dai));
+}
+
+static int tda998x_dev_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static const struct of_device_id tda998x_codec_ids[] = {
+	{ .compatible = "nxp,tda998x-codec", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tda998x_codec_ids);
+
+static struct platform_driver tda998x_driver = {
+	.probe		= tda998x_dev_probe,
+	.remove		= tda998x_dev_remove,
+	.driver		= {
+		.name	= "tda998x-codec",
+		.owner	= THIS_MODULE,
+		.of_match_table = tda998x_codec_ids,
+	},
+};
+
+module_platform_driver(tda998x_driver);
+
+MODULE_AUTHOR("Jean-Francois Moine");
+MODULE_DESCRIPTION("TDA998x codec driver");
+MODULE_LICENSE("GPL");
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v3 1/5] drm/i2c: tda998x: add a function for dynamic audio input switch
From: Jean-Francois Moine @ 2014-01-26 18:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1391274627.git.moinejf@free.fr>

When both I2S and S/PDIF are wired from the audio device to the
TDA998x, the user or some internal mechanism may choose to do audio
streaming via either inputs.

This patch adds an exported function in the TDA998x driver which
initializes the audio input parameters according to the audio
subsystem.

The audio format values in the encoder configuration interface  are
changed to non null values so that the value 0 is used in the audio
function to indicate that audio streaming is stopped.

As the audio clock depends on the input type, it is set so.
Then, the configuration value audio_clk_cfg is now ignored.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 48 ++++++++++++++++++++++++++++++++++++---
 include/drm/i2c/tda998x.h         |  7 ++++--
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 2f97290..2643be4 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -35,6 +35,7 @@ struct tda998x_priv {
 	struct i2c_client *hdmi;
 	uint16_t rev;
 	uint8_t current_page;
+	u8 audio_active;
 	int dpms;
 	bool is_hdmi_sink;
 	u8 vip_cntrl_0;
@@ -640,12 +641,11 @@ static void
 tda998x_configure_audio(struct tda998x_priv *priv,
 		struct drm_display_mode *mode, struct tda998x_encoder_params *p)
 {
-	uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv;
+	uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv, aclk;
 	uint32_t n;
 
 	/* Enable audio ports */
 	reg_write(priv, REG_ENA_AP, p->audio_cfg);
-	reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
 
 	/* Set audio input source */
 	switch (p->audio_format) {
@@ -654,6 +654,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 		clksel_aip = AIP_CLKSEL_AIP_SPDIF;
 		clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
 		cts_n = CTS_N_M(3) | CTS_N_K(3);
+		aclk = 0;				/* no clock */
 		break;
 
 	case AFMT_I2S:
@@ -661,6 +662,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 		clksel_aip = AIP_CLKSEL_AIP_I2S;
 		clksel_fs = AIP_CLKSEL_FS_ACLK;
 		cts_n = CTS_N_M(3) | CTS_N_K(3);
+		aclk = 1;				/* clock enable */
 		break;
 
 	default:
@@ -672,6 +674,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
 					AIP_CNTRL_0_ACR_MAN);	/* auto CTS */
 	reg_write(priv, REG_CTS_N, cts_n);
+	reg_write(priv, REG_ENA_ACLK, aclk);
 
 	/*
 	 * Audio input somehow depends on HDMI line rate which is
@@ -728,6 +731,37 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	tda998x_write_aif(priv, p);
 }
 
+/* tda998x codec interface */
+void tda998x_audio_update(struct i2c_client *client,
+			int format,
+			int port)
+{
+	struct tda998x_priv *priv = i2c_get_clientdata(client);
+	struct tda998x_encoder_params *p = &priv->params;
+
+	/* if the audio output is active, it may be a second start or a stop */
+	if (format == 0 || priv->audio_active) {
+		if (format == 0) {
+			priv->audio_active = 0;
+			reg_write(priv, REG_ENA_AP, 0);
+		}
+		return;
+	}
+	priv->audio_active = 1;
+
+	p->audio_cfg = port;
+
+	/* don't restart audio if same input format */
+	if (format == p->audio_format) {
+		reg_write(priv, REG_ENA_AP, p->audio_cfg);
+		return;
+	}
+	p->audio_format = format;
+
+	tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode, p);
+}
+EXPORT_SYMBOL_GPL(tda998x_audio_update);
+
 /* DRM encoder functions */
 
 static void
@@ -750,6 +784,9 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
 	priv->params = *p;
+
+	if (p->audio_cfg)
+		priv->audio_active = 1;
 }
 
 static void
@@ -999,7 +1036,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
 
 		tda998x_write_avi(priv, adjusted_mode);
 
-		if (priv->params.audio_cfg)
+		if (priv->audio_active)
 			tda998x_configure_audio(priv, adjusted_mode,
 						&priv->params);
 	}
@@ -1239,10 +1276,15 @@ tda998x_encoder_init(struct i2c_client *client,
 	if (!priv)
 		return -ENOMEM;
 
+	i2c_set_clientdata(client, priv);
+
 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
 	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
 
+	priv->params.audio_frame[1] = 1;		/* channels - 1 */
+	priv->params.audio_sample_rate = 48000;		/* 48kHz */
+
 	priv->current_page = 0xff;
 	priv->hdmi = client;
 	priv->cec = i2c_new_dummy(client->adapter, 0x34);
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 3e419d9..7e4806d 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -20,11 +20,14 @@ struct tda998x_encoder_params {
 	u8 audio_frame[6];
 
 	enum {
-		AFMT_SPDIF,
-		AFMT_I2S
+		AFMT_I2S = 1,
+		AFMT_SPDIF
 	} audio_format;
 
 	unsigned audio_sample_rate;
 };
 
+void tda998x_audio_update(struct i2c_client *client,
+			int format,
+			int port);
 #endif
-- 
1.9.rc1

^ permalink raw reply related

* [PATCH v2 1/5] drm/i2c: tda998x: add a function for dynamic audio input switch
From: Jean-Francois Moine @ 2014-01-26 18:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1391081933.git.moinejf@free.fr>

When both I2S and S/PDIF are wired from the audio device to the
TDA998x, the user or some internal mechanism may choose to do audio
streaming via either inputs.

This patch adds an exported function in the TDA998x driver which
initializes the audio input parameters according to the audio
subsystem.

The audio format values in the encoder configuration interface  are
changed to non null values so that the value 0 is used in the audio
function to indicate that audio streaming is stopped.

As the audio clock depends on the input type, it is set so.
Then, the configuration value audio_clk_cfg is now ignored.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 48 ++++++++++++++++++++++++++++++++++++---
 include/drm/i2c/tda998x.h         |  7 ++++--
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 2f97290..2643be4 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -35,6 +35,7 @@ struct tda998x_priv {
 	struct i2c_client *hdmi;
 	uint16_t rev;
 	uint8_t current_page;
+	u8 audio_active;
 	int dpms;
 	bool is_hdmi_sink;
 	u8 vip_cntrl_0;
@@ -640,12 +641,11 @@ static void
 tda998x_configure_audio(struct tda998x_priv *priv,
 		struct drm_display_mode *mode, struct tda998x_encoder_params *p)
 {
-	uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv;
+	uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv, aclk;
 	uint32_t n;
 
 	/* Enable audio ports */
 	reg_write(priv, REG_ENA_AP, p->audio_cfg);
-	reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
 
 	/* Set audio input source */
 	switch (p->audio_format) {
@@ -654,6 +654,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 		clksel_aip = AIP_CLKSEL_AIP_SPDIF;
 		clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
 		cts_n = CTS_N_M(3) | CTS_N_K(3);
+		aclk = 0;				/* no clock */
 		break;
 
 	case AFMT_I2S:
@@ -661,6 +662,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 		clksel_aip = AIP_CLKSEL_AIP_I2S;
 		clksel_fs = AIP_CLKSEL_FS_ACLK;
 		cts_n = CTS_N_M(3) | CTS_N_K(3);
+		aclk = 1;				/* clock enable */
 		break;
 
 	default:
@@ -672,6 +674,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
 					AIP_CNTRL_0_ACR_MAN);	/* auto CTS */
 	reg_write(priv, REG_CTS_N, cts_n);
+	reg_write(priv, REG_ENA_ACLK, aclk);
 
 	/*
 	 * Audio input somehow depends on HDMI line rate which is
@@ -728,6 +731,37 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	tda998x_write_aif(priv, p);
 }
 
+/* tda998x codec interface */
+void tda998x_audio_update(struct i2c_client *client,
+			int format,
+			int port)
+{
+	struct tda998x_priv *priv = i2c_get_clientdata(client);
+	struct tda998x_encoder_params *p = &priv->params;
+
+	/* if the audio output is active, it may be a second start or a stop */
+	if (format == 0 || priv->audio_active) {
+		if (format == 0) {
+			priv->audio_active = 0;
+			reg_write(priv, REG_ENA_AP, 0);
+		}
+		return;
+	}
+	priv->audio_active = 1;
+
+	p->audio_cfg = port;
+
+	/* don't restart audio if same input format */
+	if (format == p->audio_format) {
+		reg_write(priv, REG_ENA_AP, p->audio_cfg);
+		return;
+	}
+	p->audio_format = format;
+
+	tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode, p);
+}
+EXPORT_SYMBOL_GPL(tda998x_audio_update);
+
 /* DRM encoder functions */
 
 static void
@@ -750,6 +784,9 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
 	priv->params = *p;
+
+	if (p->audio_cfg)
+		priv->audio_active = 1;
 }
 
 static void
@@ -999,7 +1036,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
 
 		tda998x_write_avi(priv, adjusted_mode);
 
-		if (priv->params.audio_cfg)
+		if (priv->audio_active)
 			tda998x_configure_audio(priv, adjusted_mode,
 						&priv->params);
 	}
@@ -1239,10 +1276,15 @@ tda998x_encoder_init(struct i2c_client *client,
 	if (!priv)
 		return -ENOMEM;
 
+	i2c_set_clientdata(client, priv);
+
 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
 	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
 
+	priv->params.audio_frame[1] = 1;		/* channels - 1 */
+	priv->params.audio_sample_rate = 48000;		/* 48kHz */
+
 	priv->current_page = 0xff;
 	priv->hdmi = client;
 	priv->cec = i2c_new_dummy(client->adapter, 0x34);
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 3e419d9..7e4806d 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -20,11 +20,14 @@ struct tda998x_encoder_params {
 	u8 audio_frame[6];
 
 	enum {
-		AFMT_SPDIF,
-		AFMT_I2S
+		AFMT_I2S = 1,
+		AFMT_SPDIF
 	} audio_format;
 
 	unsigned audio_sample_rate;
 };
 
+void tda998x_audio_update(struct i2c_client *client,
+			int format,
+			int port);
 #endif
-- 
1.9.rc1

^ permalink raw reply related

* [PATCH 1/4] drm/i2c: tda998x: add a function for dynamic audio input switch
From: Jean-Francois Moine @ 2014-01-26 18:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1390813480.git.moinejf@free.fr>

When both I2S and S/PDIF are wired from the audio device to the
TDA998x, the user or some internal mechanism may choose to do audio
streaming via either inputs.

This patch adds an exported function in the TDA998x driver which
initializes the audio input parameters according to the audio
subsystem.

The audio format values in the encoder configuration interface  are
changed to non null values so that the value 0 is used in the audio
function to indicate that audio streaming is stopped.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 43 ++++++++++++++++++++++++++++++++++++++-
 include/drm/i2c/tda998x.h         |  7 +++++--
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index e5bbaf2..186c751 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -34,6 +34,7 @@ struct tda998x_priv {
 	struct i2c_client *hdmi;
 	uint16_t rev;
 	uint8_t current_page;
+	u8 audio_active;
 	int dpms;
 	bool is_hdmi_sink;
 	u8 vip_cntrl_0;
@@ -729,6 +730,38 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	tda998x_write_aif(priv, p);
 }
 
+/* tda998x codec interface */
+void tda998x_audio_update(struct i2c_client *client,
+			int format,
+			int port)
+{
+	struct tda998x_priv *priv = i2c_get_clientdata(client);
+	struct tda998x_encoder_params *p = &priv->params;
+
+	/* if the audio output is active, it may be a second start or a stop */
+	if (format == 0 || priv->audio_active) {
+		if (format == 0) {
+			priv->audio_active = 0;
+			reg_write(priv, REG_ENA_AP, 0);
+		}
+		return;
+	}
+
+	p->audio_cfg = port;
+
+	/* don't restart audio if same input format */
+	if (format == p->audio_format) {
+		priv->audio_active = 1;
+		reg_write(priv, REG_ENA_AP, p->audio_cfg);
+		return;
+	}
+	p->audio_format = format;
+	priv->audio_active = 1;
+
+	tda998x_configure_audio(priv, &priv->encoder->crtc->hwmode, p);
+}
+EXPORT_SYMBOL_GPL(tda998x_audio_update);
+
 /* DRM encoder functions */
 
 static void
@@ -751,6 +784,9 @@ tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
 	priv->params = *p;
+
+	if (p->audio_cfg)
+		priv->audio_active = 1;
 }
 
 static void
@@ -1001,7 +1037,7 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
 
 		tda998x_write_avi(priv, adj_mode);
 
-		if (priv->params.audio_cfg)
+		if (priv->audio_active)
 			tda998x_configure_audio(priv, adj_mode, &priv->params);
 	}
 }
@@ -1233,10 +1269,15 @@ tda998x_encoder_init(struct i2c_client *client,
 	if (!priv)
 		return -ENOMEM;
 
+	i2c_set_clientdata(client, priv);
+
 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
 	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
 
+	priv->params.audio_frame[1] = 1;		/* channels - 1 */
+	priv->params.audio_sample_rate = 48000;		/* 48kHz */
+
 	priv->current_page = 0xff;
 	priv->hdmi = client;
 	priv->cec = i2c_new_dummy(client->adapter, 0x34);
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index f3bb25c..0459931 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -19,11 +19,14 @@ struct tda998x_encoder_params {
 	u8 audio_frame[6];
 
 	enum {
-		AFMT_SPDIF,
-		AFMT_I2S
+		AFMT_I2S = 1,
+		AFMT_SPDIF
 	} audio_format;
 
 	unsigned audio_sample_rate;
 };
 
+void tda998x_audio_update(struct i2c_client *client,
+			int format,
+			int port);
 #endif
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
From: Lars-Peter Clausen @ 2014-01-26 17:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140126142436.GF10628@intel.com>

On 01/26/2014 03:24 PM, Vinod Koul wrote:
> On Wed, Jan 22, 2014 at 10:22:45PM +0530, Srikanth Thokala wrote:
>> This is the driver for the AXI Video Direct Memory Access (AXI
>> VDMA) core, which is a soft Xilinx IP core that provides high-
>> bandwidth direct memory access between memory and AXI4-Stream
>> type video target peripherals. The core provides efficient two
>> dimensional DMA operations with independent asynchronous read
> ok here is tha catch, do you want to support interleaved API rather?
> 
>> +* DMA client + +Required properties: +- dmas: a list of <[Video DMA device
>> phandle] [Channel ID]> pairs, +	where Channel ID is '0' for write/tx and
>> '1' for read/rx +	channel.  +- dma-names: a list of DMA channel names, one
>> per "dmas" entry + +Example: +++++++++ + +vdmatest_0: vdmatest at 0 { +
>> compatible ="xlnx,axi-vdma-test-1.00.a"; +	dmas = <&axi_vdma_0 0 +
>> &axi_vdma_0 1>; +	dma-names = "vdma0", "vdma1"; +} ;
> Need ack from DT folks. ALso would be better to split the binding to a separate
> patch
> 
> 
>> +/**
>> + * struct xilinx_vdma_chan - Driver specific VDMA channel structure
>> + * @xdev: Driver specific device structure
>> + * @ctrl_offset: Control registers offset
>> + * @desc_offset: TX descriptor registers offset
>> + * @completed_cookie: Maximum cookie completed
>> + * @cookie: The current cookie
>> + * @lock: Descriptor operation lock
>> + * @pending_list: Descriptors waiting
>> + * @active_desc: Active descriptor
>> + * @done_list: Complete descriptors
>> + * @common: DMA common channel
>> + * @desc_pool: Descriptors pool
>> + * @dev: The dma device
>> + * @irq: Channel IRQ
>> + * @id: Channel ID
>> + * @direction: Transfer direction
>> + * @num_frms: Number of frames
>> + * @has_sg: Support scatter transfers
>> + * @genlock: Support genlock mode
>> + * @err: Channel has errors
>> + * @tasklet: Cleanup work after irq
>> + * @config: Device configuration info
>> + * @flush_on_fsync: Flush on Frame sync
>> + */
>> +struct xilinx_vdma_chan {
>> +	struct xilinx_vdma_device *xdev;
>> +	u32 ctrl_offset;
>> +	u32 desc_offset;
>> +	dma_cookie_t completed_cookie;
>> +	dma_cookie_t cookie;
>> +	spinlock_t lock;
>> +	struct list_head pending_list;
>> +	struct xilinx_vdma_tx_descriptor *active_desc;
>> +	struct list_head done_list;
>> +	struct dma_chan common;
>> +	struct dma_pool *desc_pool;
>> +	struct device *dev;
>> +	int irq;
>> +	int id;
>> +	enum dma_transfer_direction direction;
> why should channel have a direction... descriptor should have direction and not
> the channel!

The channel only supports transfers in one direction. Either from memory to
peripheral or from peripheral to memory, that's fixed and can't be changed
at runtime. The driver needs to know which direction the channel supports so
it can reject transfers with the wrong direction.

[...]
>> +
> 
>> + * xilinx_vdma_tx_status - Get VDMA transaction status
>> + * @dchan: DMA channel
>> + * @cookie: Transaction identifier
>> + * @txstate: Transaction state
>> + *
>> + * Return: DMA transaction status
>> + */
>> +static enum dma_status xilinx_vdma_tx_status(struct dma_chan *dchan,
>> +					dma_cookie_t cookie,
>> +					struct dma_tx_state *txstate)
>> +{
>> +	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
>> +	dma_cookie_t last_used;
>> +	dma_cookie_t last_complete;
>> +
>> +	xilinx_vdma_chan_desc_cleanup(chan);
>> +
>> +	last_used = dchan->cookie;
>> +	last_complete = chan->completed_cookie;
>> +
>> +	dma_set_tx_state(txstate, last_complete, last_used, 0);
>> +
>> +	return dma_async_is_complete(cookie, last_complete, last_used);
> no residue calculation?
> 

The hardware doesn't support that.

>> +/**
>> + * xilinx_vdma_prep_slave_sg - prepare a descriptor for a DMA_SLAVE transaction
>> + * @dchan: DMA channel
>> + * @sgl: scatterlist to transfer to/from
>> + * @sg_len: number of entries in @sgl
>> + * @dir: DMA direction
>> + * @flags: transfer ack flags
>> + * @context: unused
>> + *
>> + * Return: Async transaction descriptor on success and NULL on failure
>> + */
>> +static struct dma_async_tx_descriptor *
>> +xilinx_vdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
>> +			  unsigned int sg_len, enum dma_transfer_direction dir,
>> +			  unsigned long flags, void *context)
> okay now am worried, this is supposed to memcpy DMA so why slave-sg??

The DMA is either from memory to peripheral or from peripheral to memory
depending on the direction. So slave sg should be fine.

> 
> Looking at the driver overall, IMHO we need to do:
> - use the virt-dma to simplfy the cookie handling and perhpasn the descrptors
>   too!
> - Perhpas use interleaved API..?
> - I dont think we should use the slave API as this seems memcpy case!
> 

^ permalink raw reply

* [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
From: Lars-Peter Clausen @ 2014-01-26 17:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140126140318.GE10628@intel.com>

On 01/26/2014 03:03 PM, Vinod Koul wrote:
> On Thu, Jan 23, 2014 at 03:07:32PM +0100, Lars-Peter Clausen wrote:
>> On 01/23/2014 03:00 PM, Andy Shevchenko wrote:
>>> On Thu, 2014-01-23 at 14:50 +0100, Lars-Peter Clausen wrote:
>>>> On 01/23/2014 02:38 PM, Shevchenko, Andriy wrote:
>>>>> On Thu, 2014-01-23 at 12:25 +0100, Lars-Peter Clausen wrote:
>>>>>> On 01/22/2014 05:52 PM, Srikanth Thokala wrote:
>>>>>
>>>>> [...]
>>>>>
>>>>>>> +	/* Request the interrupt */
>>>>>>> +	chan->irq = irq_of_parse_and_map(node, 0);
>>>>>>> +	err = devm_request_irq(xdev->dev, chan->irq, xilinx_vdma_irq_handler,
>>>>>>> +			       IRQF_SHARED, "xilinx-vdma-controller", chan);
>>>>>>
>>>>>> This is a clasic example of where to not use devm_request_irq. 'chan' is
>>>>>> accessed in the interrupt handler, but if you use devm_request_irq 'chan'
>>>>>> will be freed before the interrupt handler has been released, which means
>>>>>> there is now a race condition where the interrupt handler can access already
>>>>>> freed memory.ta
>>>>>
>>>>> Could you elaborate this case? As far as I understood managed resources
>>>>> are a kind of stack pile. In this case you have no such condition. Where
>>>>> am I wrong?
>>>>
>>>> The stacked stuff is only ran after the remove() function. Which means that
>>>> you call dma_async_device_unregister() before the interrupt handler is
>>>> freed. Another issue with the interrupt handler is a bit hidden. The driver
>>>> does not call tasklet_kill in the remove function. Which it should though to
>>>> make sure that the tasklet does not race against the freeing of the memory.
>>>> And in order to make sure that the tasklet is not rescheduled you need to
>>>> free the irq before killing the tasklet, since the interrupt handler
>>>> schedules the tasklet.
>>>
>>> So, you mean devm_request_irq() will race in any DMA driver?
>>
>> Most likely yes. devm_request_irq() is race condition prone for the majority
>> of device driver. You have to be really careful if you want to use it.
>>
>>>
>>> I think the proper solution is to disable all device work in
>>> the .remove() and devm will care about resources.
>>
>> As long as the interrupt handler is registered it can be called, the only
>> proper solution is to make sure that the order in which resources are torn
>> down is correct.
> Wouldn't it work if we register the irq last in the probe. That wil ensure on
> success the channel is always valid.

Yes, but only if the irq is not device managed. All device managed resources
will be freed after the remove function has been called. Which is to late in
our case since we make sure that the tasklet is not running in the remove
function.

- Lars

^ permalink raw reply

* [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
From: Lars-Peter Clausen @ 2014-01-26 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140126135933.GD10628@intel.com>

On 01/26/2014 02:59 PM, Vinod Koul wrote:
> On Fri, Jan 24, 2014 at 02:24:27PM +0100, Lars-Peter Clausen wrote:
>> On 01/24/2014 12:16 PM, Srikanth Thokala wrote:
>>> Hi Lars,
>>>
>>> On Thu, Jan 23, 2014 at 4:55 PM, Lars-Peter Clausen <lars@metafoo.de> wrote:
>>>> On 01/22/2014 05:52 PM, Srikanth Thokala wrote:
>>>> [...]
>>>>> +/**
>>>>> + * xilinx_vdma_device_control - Configure DMA channel of the device
>>>>> + * @dchan: DMA Channel pointer
>>>>> + * @cmd: DMA control command
>>>>> + * @arg: Channel configuration
>>>>> + *
>>>>> + * Return: '0' on success and failure value on error
>>>>> + */
>>>>> +static int xilinx_vdma_device_control(struct dma_chan *dchan,
>>>>> +                                   enum dma_ctrl_cmd cmd, unsigned long arg)
>>>>> +{
>>>>> +     struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
>>>>> +
>>>>> +     switch (cmd) {
>>>>> +     case DMA_TERMINATE_ALL:
>>>>> +             xilinx_vdma_terminate_all(chan);
>>>>> +             return 0;
>>>>> +     case DMA_SLAVE_CONFIG:
>>>>> +             return xilinx_vdma_slave_config(chan,
>>>>> +                                     (struct xilinx_vdma_config *)arg);
>>>>
>>>> You really shouldn't be overloading the generic API with your own semantics.
>>>> DMA_SLAVE_CONFIG should take a dma_slave_config and nothing else.
>>>
>>> Ok.  The driver needs few additional configuration from the slave
>>> device like Vertical
>>> Size, Horizontal Size,  Stride etc., for the DMA transfers, in that case do you
>>> suggest me to define a separate dma_ctrl_cmd like the one FSLDMA_EXTERNAL_START
>>> defined for Freescale drivers?
>>
>> In my opinion it is not a good idea to have driver implement a generic API,
>> but at the same time let the driver have custom semantics for those API
>> calls. It's a bit like having a gpio driver that expects 23 and 42 as the
>> values passed to gpio_set_value instead of 0 and 1. It completely defeats
>> the purpose of a generic API, namely that you are able to write generic code
>> that makes use of the API without having to know about which implementation
>> API it is talking to. The dmaengine framework provides the
>> dmaengine_prep_interleaved_dma() function to setup two dimensional
>> transfers, e.g. take a look at sirf-dma.c or imx-dma.c.
> 
> The question here i think would be waht this device supports? Is the hardware
> capable of doing interleaved transfers, then would make sense.

The hardware does 2D transfers. The parameters for a transfer are height,
width and stride. That's only a subset of what interleaved transfers can be
(xt->num_frames must be one for 2d transfers). But if I remember correctly
there has been some discussion on this in the past and the result of that
discussion was that using interleaved transfers for 2D transfers is
preferred over adding a custom API for 2D transfers.

- Lars

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox