Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH 3/4] OMAPDSS: panel-sharp-ls037v7dw01: add device tree support
From: Tony Lindgren @ 2014-05-07 17:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <536A5920.1020908@ti.com>

* Tomi Valkeinen <tomi.valkeinen@ti.com> [140507 09:03]:
> On 07/05/14 18:03, Tony Lindgren wrote:
> 
> >>> +	lcd0: display {
> >>> +		compatible = "sharp,ls037v7dw01";
> >>> +		power-supply = <&lcd_3v3>;
> >>> +		reset-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;	/* gpio155, lcd RESB */
> >>> +		enable-gpios = <&gpio5 26 GPIO_ACTIVE_HIGH	/* gpio154, lcd MO */
> >>> +				&gpio1 2 GPIO_ACTIVE_HIGH	/* gpio2, lcd LR */
> >>> +				&gpio1 3 GPIO_ACTIVE_HIGH	/* gpio3, lcd UD */
> >>> +				&gpio5 24 GPIO_ACTIVE_HIGH>;	/* gpio152, lcd INI */
> >>
> >> Why are most of the gpios in 'enable-gpios'? MO, LR and UD don't really
> >> have anything to do with enabling the panel. Why not just have one
> >> 'gpios' array with all the gpios, as they are quite a mixed bunch?
> > 
> > Yeah that's what I had initially, but reading simple-panel.txt noticed
> > there are some standardized GPIOs for reset and enable.
> 
> I'm not sure if it's worth to try to make it compatible with
> simple-panel. simple-panel bindings do not work with omapdss anyway, and
> simple-panel doesn't have the support for input ports/endpoints.
> 
> Can the panel be used with only one gpio (I guess that would be INI or
> RESB)? If not, simple-panel doesn't work.

I guess in theory yes.
 
> > How about we set up one reset-gpios, one enable-gpios and an array of
> > three unlabelled GPIOs?
> > 
> > Or if we want to add something generic, we could add new mode-gpios
> > property that other panels might be able to use too?
> > 
> > BTW, I'm also personally fine with all five gpios showing in a single
> > gpios property, I'm not too exited about naming anything in DT..
> 
> I don't have a strong opinion here. I don't have much experience with
> DT, especially with making bindings compatible with other ones.
> 
> I'd just forget the simple-panel, and have single gpio array.

Well if it's a don't care flag for both of us, let's try to use
the existing standard for simple-panel.txt and add mode-gpios
property. I'll post a patch for that.

Regards,

Tony

^ permalink raw reply

* Re: [PATCH v2 1/3] video: clps711x: Add new C =?UTF-8?B?aXJydXMgTG9naWMgQ
From: Alexander Shiyan @ 2014-05-08  8:27 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1398327006.501536964@f133.i.mail.ru>

V2VkLCA3IE1heSAyMDE0IDEyOjQwOjQ5ICswMzAwINC+0YIgVG9taSBWYWxrZWluZW4gPHRvbWku
dmFsa2VpbmVuQHRpLmNvbT46Cj4gT24gMzAvMDQvMTQgMTU6MzYsIEFsZXhhbmRlciBTaGl5YW4g
d3JvdGU6Cj4gCj4gPj4gSG1tIHdoYXQ/IFNvIGlzIHRoZSBvbGQgZHJpdmVyIHRvdGFsbHkgYnJv
a2VuLCBhbmQgY2Fubm90IGJlIHVzZWQgYXQgdGhlCj4gPj4gbW9tZW50PyBPciB3aHkgeW91IGNh
bid0IHRlc3Qgb24gcmVhbCBoYXJkd2FyZT8KPiA+IAo+ID4gRmlyc3RseSwgdGhlIGRyaXZlciB1
c2VzIGEgZml4ZWQgdmFsdWVzIGZvciB4cmVzLCB5cmVzLCBwaXhjbG9jayBhbmQgc3BlY2lmaWMK
PiA+IHZhcmlhYmxlIGFjX3ByZWNhbGUuCj4gPiBTZWNvbmRseSwgdGhlIGRyaXZlciB1c2VzIGEg
Zml4ZWQgdmFsdWUgZm9yIHRoZSBwaHlzaWNhbCBhZGRyZXNzIG9mIHRoZSBidWZmZXIuCj4gPiBU
b3RhbGx5LCBpdCBkb2VzIG5vdCBnaXZlIG1lIHRoZSBhYmlsaXR5IHRvIHVzZSB0aGUgZHJpdmVy
IGluIHRoZSBjdXJyZW50IHN0YXRlLgo+ID4gVW5saWtlbHkgdGhhdCB0aGlzIHdpbGwgbG9vayBn
b29kIGlmIEkgbWFrZSB0aGVzZSB0d28gc2lnbmlmaWNhbnQgY2hhbmdlcyBpbgo+ID4gYSBzaW5n
bGUgcGF0Y2guLi4KPiA+IAo+ID4gQXQgdGhpcyB0aW1lIHRoZSBkcml2ZXIgaGFzIHRocmVlIHVz
ZXIuCj4gPiBPbmx5IG9uZSBvZiB0aGVtIHNob3VsZCB0aGVvcmV0aWNhbGx5IHdvcmsuCj4gPiBj
bHBzNzExeC1hdXRjcHUxMiBzaG91bGQgbm90IHdvcmsgaW4gdGhlIGFic2VuY2Ugb2YgbWVtYmxv
Y2tfcmVzZXJ2ZSgpLgo+ID4gY2xwczcxMXgtcDcyMHQgc2hvdWxkIG5vdCB3b3JrIGR1ZSB0byBw
aHlzaWNhbCBhZGRyZXNzIGxpbWl0YXRpb24gYXMgaQo+ID4gbm90aWNlZCBiZWZvcmUuIEJvYXJk
IG1lYW5zIHRvIHVzZSBTUkFNIGluc3RlYWQgb2YgU0RSQU0uCj4gPiBPbmx5IGNscHM3MTF4LWVk
YjcyMTEgc2hvdWxkIHdvcmsgZmluZSAoaW4gdGhlb3J5KS4KPiA+IElzIHRoaXMgYSBnb29kIHJl
YXNvbiB0byByZXBsYWNlIHRoZSBkcml2ZXI/IEkgdGhpbmsgeWVzLgo+IAo+IE9rLCBpZiB0aGUg
c2l0dWF0aW9uIGlzIHRoYXQgYmFkLCBtYXliZSB3ZSBjYW4ganVzdCBzd2l0Y2ggdG8gdGhlIG5l
dwo+IGRyaXZlci4gSGF2ZSB5b3UgdmVyaWZpZWQgdGhhdCB0aG9zZSBib2FyZHMgZG8gbm90IHdv
cmsgZnJvbSBhbnlvbmU/IE9yCj4gYXNrZWQgc29tZW9uZSB0byB0ZXN0IHRoZSBuZXcgZHJpdmVy
IHdpdGggdGhvc2UgYm9hcmRzPwoKSSdtIG5vdCBmYW1pbGlhciB3aXRoIG90aGVyIHVzZXJzIG9m
IHRoaXMgcGxhdGZvcm0gLgpJIGFtIGRvIG5vdCBoYXZlIHRoZXNlIGJvYXJkcywgYWxsIHRoYXQg
SSBoYXZlIHdyaXR0ZW4gYmVmb3JlIHRoYXQgaXQncyBqdXN0IGEgdGhlb3J5LgpGaXJtIGluIHdo
aWNoIEkgd29yaywgdXNlcyBpdHMgb3duIGJvYXJkIHdpdGggQ0xQUzcxMVggQ1BVICwgdGhpcyBi
b2FyZCBpcyB0aGUKb25seSB3YXkgdG8gY2hlY2sgZm9yIGNoYW5nZXMgb24gcmVhbCBoYXJkd2Fy
ZSAuCgo+IEknbSBzdGlsbCBub3QgcmVhbGx5IGhhcHB5IGFib3V0IGl0LCBhbmQgSSdkIG11Y2gg
cmF0aGVyIHNlZSB0aGUgY3VycmVudAo+IGRyaXZlciBmaXhlZC4gQnV0IGlmIG5vIG9uZSBoYXZp
bmcgdGhvc2UgYm9hcmRzIGlzIHVwIHRvIHRoZSB0YXNrCj4gKHByb2JhYmx5IG5vdCBpZiB0aGV5
IGhhdmUgbm90IGJlZW4gd29ya2luZyBhdCBhbGwpLCBtYXliZSBqdXN0IGRpdGNoaW5nCj4gdGhl
IG9sZCBkcml2ZXIgYW5kIGFkZGluZyBhIG5ldyBpcyB0aGUgb25seSB3YXkgZm9yd2FyZC4KPiAK
PiBPbmUgY2hhbmdlIHRoYXQgSSB0aGluayB3b3VsZCBiZSBnb29kIGlzIHRvIGNoYW5nZSB0aGUg
c2VyaWVzIHRvIGZpcnN0Cj4gcmVtb3ZlIHRoZSBvbGQgZHJpdmVyLCBhbmQgdGhlbiBhZGQgdGhl
IG5ldyBvbmUsIHdpdGggdGhlIHNhbWUgZmlsZSBuYW1lCj4gYXMgdGhlIG9sZCBvbmUuIFRoYXQg
d2F5IGdpdCBsb2cgd2lsbCBzaG93IHRoZSBoaXN0b3J5IGZvciBib3RoIHRoZSBuZXcKPiBhbmQg
dGhlIG9sZCBkcml2ZXIuCgpJbiB0aGlzIGNhc2UgZ2l0LWJpc2VjdCB3aWxsIGJlIGJyb2tlbi4g
SXMgdGhpcyBPSz8KCi0tLQoK

^ permalink raw reply

* [RFC 1/6] omapdss: remove check for simpler port/endpoint binding
From: Archit Taneja @ 2014-05-08  9:27 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja

The support for simpler port/endpoint binding was removed in the merged version
of omapdss DT. But dss_init_ports still tries to get to an endpoint even if no
port exists. Remove this as this doesn't work.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/fbdev/omap2/dss/dss.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index d55266c..31ef262 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -784,12 +784,8 @@ static int __init dss_init_ports(struct platform_device *pdev)
 		return 0;
 
 	port = omapdss_of_get_next_port(parent, NULL);
-	if (!port) {
-#ifdef CONFIG_OMAP2_DSS_DPI
-		dpi_init_port(pdev, parent);
-#endif
+	if (!port)
 		return 0;
-	}
 
 	do {
 		u32 reg;
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 2/6] omapdss: add init port functions for different omap revs
From: Archit Taneja @ 2014-05-08  9:27 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1399540517-17883-1-git-send-email-archit@ti.com>

The init/uninit port functions are used to set up the DPI and SDI outputs under
the dss platform device. A 'reg' property is used to determine whether the node
is DPI or SDI for OMAP34xx DSS revision. For other DSS revisions, only DPI
output exists.

For multiple DPI output instances(introduced in DRA7xx DSS), we would use the
'reg' property to specify the DPI output number.

The current functions work fine if there is only one DPI output instance in
DSS. For multiple DPI instances, it would get complicated to figure out whether
'reg' is used to specify whether the output is SDI, or a later DPI instance.

Create DSS revision specific init/uninit_port functions such that we have a
separate functions for OMAP34xx, this helps us deal with the SDI case
separately.

Also, make the uninit_port functions iterative since we will have multiple DPI
ports in the future.

dpi_uninit_port/sdi_uninit_port functions have to be removed from the exit
section as dss_features(which is initconst data) uses it, this prevents the
section mismatch.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/fbdev/omap2/dss/dpi.c |  2 +-
 drivers/video/fbdev/omap2/dss/dss.c | 88 ++++++++++++++++++++++++++++++++++---
 drivers/video/fbdev/omap2/dss/dss.h |  4 +-
 drivers/video/fbdev/omap2/dss/sdi.c |  2 +-
 4 files changed, 86 insertions(+), 10 deletions(-)

diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index 157921d..6593c8b 100644
--- a/drivers/video/fbdev/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -765,7 +765,7 @@ err_datalines:
 	return r;
 }
 
-void __exit dpi_uninit_port(void)
+void dpi_uninit_port(struct platform_device *pdev, struct device_node *port)
 {
 	if (!dpi.port_initialized)
 		return;
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index 31ef262..c415029 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -65,12 +65,18 @@ struct dss_reg {
 
 static int dss_runtime_get(void);
 static void dss_runtime_put(void);
+static int __init dss_init_ports(struct platform_device *pdev);
+static int __init dss_init_ports_omap34xx(struct platform_device *pdev);
+static void dss_uninit_ports(struct platform_device *pdev);
+static void dss_uninit_ports_omap34xx(struct platform_device *pdev);
 
 struct dss_features {
 	u8 fck_div_max;
 	u8 dss_fck_multiplier;
 	const char *parent_clk_name;
 	int (*dpi_select_source)(enum omap_channel channel);
+	int (*init_ports)(struct platform_device *pdev);
+	void (*uninit_ports)(struct platform_device *pdev);
 };
 
 static struct {
@@ -698,6 +704,8 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
 	.dss_fck_multiplier	=	2,
 	.parent_clk_name	=	"core_ck",
 	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
+	.init_ports		=	&dss_init_ports,
+	.uninit_ports		=	&dss_uninit_ports,
 };
 
 static const struct dss_features omap34xx_dss_feats __initconst = {
@@ -705,6 +713,8 @@ static const struct dss_features omap34xx_dss_feats __initconst = {
 	.dss_fck_multiplier	=	2,
 	.parent_clk_name	=	"dpll4_ck",
 	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
+	.init_ports		=	&dss_init_ports_omap34xx,
+	.uninit_ports		=	&dss_uninit_ports_omap34xx,
 };
 
 static const struct dss_features omap3630_dss_feats __initconst = {
@@ -712,6 +722,8 @@ static const struct dss_features omap3630_dss_feats __initconst = {
 	.dss_fck_multiplier	=	1,
 	.parent_clk_name	=	"dpll4_ck",
 	.dpi_select_source	=	&dss_dpi_select_source_omap2_omap3,
+	.init_ports		=	&dss_init_ports,
+	.uninit_ports		=	&dss_uninit_ports,
 };
 
 static const struct dss_features omap44xx_dss_feats __initconst = {
@@ -719,6 +731,8 @@ static const struct dss_features omap44xx_dss_feats __initconst = {
 	.dss_fck_multiplier	=	1,
 	.parent_clk_name	=	"dpll_per_x2_ck",
 	.dpi_select_source	=	&dss_dpi_select_source_omap4,
+	.init_ports		=	&dss_init_ports,
+	.uninit_ports		=	&dss_uninit_ports,
 };
 
 static const struct dss_features omap54xx_dss_feats __initconst = {
@@ -726,6 +740,8 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
 	.dss_fck_multiplier	=	1,
 	.parent_clk_name	=	"dpll_per_x2_ck",
 	.dpi_select_source	=	&dss_dpi_select_source_omap5,
+	.init_ports		=	&dss_init_ports,
+	.uninit_ports		=	&dss_uninit_ports,
 };
 
 static int __init dss_init_features(struct platform_device *pdev)
@@ -774,7 +790,7 @@ static int __init dss_init_features(struct platform_device *pdev)
 	return 0;
 }
 
-static int __init dss_init_ports(struct platform_device *pdev)
+static int __init dss_init_ports_omap34xx(struct platform_device *pdev)
 {
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
@@ -809,15 +825,75 @@ static int __init dss_init_ports(struct platform_device *pdev)
 	return 0;
 }
 
-static void dss_uninit_ports(void)
+static int __init dss_init_ports(struct platform_device *pdev)
 {
+	struct device_node *parent = pdev->dev.of_node;
+	struct device_node *port;
+
+	if (parent = NULL)
+		return 0;
+
+	port = omapdss_of_get_next_port(parent, NULL);
+	if (!port)
+		return 0;
+
+	do {
 #ifdef CONFIG_OMAP2_DSS_DPI
-	dpi_uninit_port();
+			dpi_init_port(pdev, port);
+#endif
+	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+
+	return 0;
+}
+
+static void dss_uninit_ports_omap34xx(struct platform_device *pdev)
+{
+	struct device_node *parent = pdev->dev.of_node;
+	struct device_node *port;
+	int r;
+
+	if (parent = NULL)
+		return;
+
+	port = omapdss_of_get_next_port(parent, NULL);
+	if (!port)
+		return;
+
+	do {
+		u32 reg;
+
+		r = of_property_read_u32(port, "reg", &reg);
+		if (r)
+			reg = 0;
+
+#ifdef CONFIG_OMAP2_DSS_DPI
+		if (reg = 0)
+			dpi_uninit_port(pdev, port);
 #endif
 
 #ifdef CONFIG_OMAP2_DSS_SDI
-	sdi_uninit_port();
+		if (reg = 1)
+			sdi_uninit_port();
 #endif
+	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+}
+
+static void dss_uninit_ports(struct platform_device *pdev)
+{
+	struct device_node *parent = pdev->dev.of_node;
+	struct device_node *port;
+
+	if (parent = NULL)
+		return;
+
+	port = omapdss_of_get_next_port(parent, NULL);
+	if (!port)
+		return;
+	do {
+#ifdef CONFIG_OMAP2_DSS_DPI
+			dpi_uninit_port(pdev, port);
+#endif
+	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
 }
 
 /* DSS HW IP initialisation */
@@ -878,7 +954,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
 	dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
 	dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
 
-	dss_init_ports(pdev);
+	dss.feat->init_ports(pdev);
 
 	rev = dss_read_reg(DSS_REVISION);
 	printk(KERN_INFO "OMAP DSS rev %d.%d\n",
@@ -899,7 +975,7 @@ err_setup_clocks:
 
 static int __exit omap_dsshw_remove(struct platform_device *pdev)
 {
-	dss_uninit_ports();
+	dss.feat->uninit_ports(pdev);
 
 	pm_runtime_disable(&pdev->dev);
 
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
index 560078f..9f4ee49 100644
--- a/drivers/video/fbdev/omap2/dss/dss.h
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -245,7 +245,7 @@ int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;
 
 int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
-void sdi_uninit_port(void) __exit;
+void sdi_uninit_port(void);
 
 /* DSI */
 
@@ -359,7 +359,7 @@ int dpi_init_platform_driver(void) __init;
 void dpi_uninit_platform_driver(void) __exit;
 
 int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
-void dpi_uninit_port(void) __exit;
+void dpi_uninit_port(struct platform_device *pdev, struct device_node *port);
 
 /* DISPC */
 int dispc_init_platform_driver(void) __init;
diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c
index 911dcc9..71a3083 100644
--- a/drivers/video/fbdev/omap2/dss/sdi.c
+++ b/drivers/video/fbdev/omap2/dss/sdi.c
@@ -424,7 +424,7 @@ err_datapairs:
 	return r;
 }
 
-void __exit sdi_uninit_port(void)
+void sdi_uninit_port(void)
 {
 	if (!sdi.port_initialized)
 		return;
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 3/6] omapdss: DT: Get source endpoint by matching reg-id
From: Archit Taneja @ 2014-05-08  9:27 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1399540517-17883-1-git-send-email-archit@ti.com>

In omapdss_of_find_source_for_first_ep, we retrieve a source endpoint's DT node,
and then see what omapdss output has the matching device_node pointer in
omap_dss_find_output_by_node.

For all DPI and SDI outputs, the device_node pointer is set as the parent's DSS
device_node pointer. If the source is one of these outputs, the above method
won't work.

To get the correct output for ports within DSS with the existing omapdss DT
framework, we check in omapdss_of_find_source_for_first_ep, whether the source
node is of the DSS parent device. If so, we take an extra step of extracting
the 'reg' property from the port corresponding to the endpoint source, and get
the omap_dss_device output by matching both device_node and reg-id.

We would want to get rid of this eventually, and support multiple ports in
general. That would involve making some more changes the omapdss DT
framework.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/fbdev/omap2/dss/dss-of.c | 41 ++++++++++++++++++++++++++++++----
 drivers/video/fbdev/omap2/dss/dss.c    |  6 +++++
 drivers/video/fbdev/omap2/dss/dss.h    |  2 ++
 drivers/video/fbdev/omap2/dss/output.c | 15 +++++++++++++
 include/video/omapdss.h                |  6 +++++
 5 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/drivers/video/fbdev/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c
index a4b20aa..4261c14 100644
--- a/drivers/video/fbdev/omap2/dss/dss-of.c
+++ b/drivers/video/fbdev/omap2/dss/dss-of.c
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 
 #include <video/omapdss.h>
+#include "dss.h"
 
 struct device_node *
 omapdss_of_get_next_port(const struct device_node *parent,
@@ -142,12 +143,44 @@ omapdss_of_find_source_for_first_ep(struct device_node *node)
 
 	src_node = omapdss_of_get_remote_device_node(ep);
 
-	of_node_put(ep);
-
-	if (!src_node)
+	if (!src_node) {
+		of_node_put(ep);
 		return ERR_PTR(-EINVAL);
+	}
 
-	src = omap_dss_find_output_by_node(src_node);
+	/*
+	 * TODO: Find a better solution for this.
+	 *
+	 * DPI and SDI outputs share the same DSS device node. In order to find
+	 * the correct omap_dss_device output, we need to match the reg-id
+	 * property of the DPI/SDI port.
+	 *
+	 * For the special case of device_node being the parent DSS device, make
+	 * sure we check for both device_node and reg-id to get the correct
+	 * source
+	 */
+	if (src_node = dss_device_node()) {
+		struct device_node *src_port;
+		u32 reg;
+		int r;
+
+		src_port = of_parse_phandle(ep, "remote-endpoint", 0);
+
+		/* the parent of the endpoint is always the port node */
+		src_port = of_get_next_parent(src_port);
+
+		r = of_property_read_u32(src_port, "reg", &reg);
+		if (r)
+			reg = 0;
+
+		of_node_put(src_port);
+
+		src = omap_dss_find_output_by_node_and_reg(src_node, reg);
+	} else {
+		src = omap_dss_find_output_by_node(src_node);
+	}
+
+	of_node_put(ep);
 
 	of_node_put(src_node);
 
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index c415029..4087f3b 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -790,6 +790,12 @@ static int __init dss_init_features(struct platform_device *pdev)
 	return 0;
 }
 
+/* of_node pointer for the DSS parent node */
+struct device_node *dss_device_node(void)
+{
+	return dss.pdev->dev.of_node;
+}
+
 static int __init dss_init_ports_omap34xx(struct platform_device *pdev)
 {
 	struct device_node *parent = pdev->dev.of_node;
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
index 9f4ee49..6f68f72 100644
--- a/drivers/video/fbdev/omap2/dss/dss.h
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -240,6 +240,8 @@ typedef bool (*dss_div_calc_func)(unsigned long fck, void *data);
 bool dss_div_calc(unsigned long pck, unsigned long fck_min,
 		dss_div_calc_func func, void *data);
 
+struct device_node *dss_device_node(void);
+
 /* SDI */
 int sdi_init_platform_driver(void) __init;
 void sdi_uninit_platform_driver(void) __exit;
diff --git a/drivers/video/fbdev/omap2/dss/output.c b/drivers/video/fbdev/omap2/dss/output.c
index 2ab3afa..2b556f1 100644
--- a/drivers/video/fbdev/omap2/dss/output.c
+++ b/drivers/video/fbdev/omap2/dss/output.c
@@ -144,6 +144,21 @@ struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node)
 }
 EXPORT_SYMBOL(omap_dss_find_output_by_node);
 
+struct omap_dss_device
+		*omap_dss_find_output_by_node_and_reg(struct device_node *node,
+		u32 reg)
+{
+	struct omap_dss_device *out;
+
+	list_for_each_entry(out, &output_list, list) {
+		if (out->dev->of_node = node && out->reg = reg)
+			return omap_dss_get_device(out);
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(omap_dss_find_output_by_node_and_reg);
+
 struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
 {
 	while (dssdev->src)
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 6adb445..7ce2d83 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -789,6 +789,9 @@ struct omap_dss_device {
 	/* output instance */
 	enum omap_dss_output_id id;
 
+	/* the <reg> value in the DT node */
+	int reg;
+
 	/* dynamic fields */
 	struct omap_overlay_manager *manager;
 
@@ -909,6 +912,9 @@ void omapdss_unregister_output(struct omap_dss_device *output);
 struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id);
 struct omap_dss_device *omap_dss_find_output(const char *name);
 struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node);
+struct omap_dss_device
+		*omap_dss_find_output_by_node_and_reg(struct device_node *node,
+		u32 reg);
 int omapdss_output_set_device(struct omap_dss_device *out,
 		struct omap_dss_device *dssdev);
 int omapdss_output_unset_device(struct omap_dss_device *out);
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 4/6] omapdss: DPI: support multiple DPI instances
From: Archit Taneja @ 2014-05-08  9:27 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1399540517-17883-1-git-send-email-archit@ti.com>

SoCs containing DSS until now had only one DPI instance. DRA7x has 3 DPI
instances.

In order to support multiple instances, we allocate a driver data
struct(dpi_data) for each instance. This is somewhat similar to how DSI driver
was changed to support multiple instances.

One difference is that there are no platform devices for each instance when DT
is used. In the DT case, we store the dpi_data pointer in the DPI port's
(of the type struct device_node) data pointer. In the non DT case, we still
have dummy platform devices, and the device's private data pointer is used to
store the DPI instance's dpi_data.

When an encoder/panel driver calls a dpi op, we get dpi_data using the function
dpi_get_data_from_dssdev. This function iterates through the ports under DSS
device node, and returns the port which has reg-id matching the reg-id specified
in omap_dss_device.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/fbdev/omap2/dss/dpi.c | 282 +++++++++++++++++++++++++-----------
 1 file changed, 200 insertions(+), 82 deletions(-)

diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index 6593c8b..b891e17 100644
--- a/drivers/video/fbdev/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -37,7 +37,7 @@
 #include "dss.h"
 #include "dss_features.h"
 
-static struct {
+struct dpi_data {
 	struct platform_device *pdev;
 
 	struct regulator *vdds_dsi_reg;
@@ -52,7 +52,45 @@ static struct {
 	struct omap_dss_device output;
 
 	bool port_initialized;
-} dpi;
+};
+
+static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
+{
+	struct device_node *parent = dssdev->dev->of_node;
+	struct device_node *port;
+
+	/* non DT */
+	if (!parent) {
+		struct omap_dss_device *out = dssdev->src;
+
+		return dev_get_drvdata(out->dev);
+	}
+
+	port = omapdss_of_get_next_port(parent, NULL);
+	if (!port)
+		return NULL;
+
+	do {
+		int r;
+		u32 reg;
+
+		r = of_property_read_u32(port, "reg", &reg);
+		if (r)
+			reg = 0;
+
+		if (reg = dssdev->reg)
+			return port->data;
+
+	} while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+
+	return NULL;
+}
+
+/* use only for non DT mode */
+static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
+{
+	return dev_get_drvdata(&pdev->dev);
+}
 
 static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
 {
@@ -197,15 +235,16 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
 			dpi_calc_dispc_cb, ctx);
 }
 
-static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
+static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck,
+		struct dpi_clk_calc_ctx *ctx)
 {
 	unsigned long clkin;
 	unsigned long pll_min, pll_max;
 
-	clkin = dsi_get_pll_clkin(dpi.dsidev);
+	clkin = dsi_get_pll_clkin(dpi->dsidev);
 
 	memset(ctx, 0, sizeof(*ctx));
-	ctx->dsidev = dpi.dsidev;
+	ctx->dsidev = dpi->dsidev;
 	ctx->pck_min = pck - 1000;
 	ctx->pck_max = pck + 1000;
 	ctx->dsi_cinfo.clkin = clkin;
@@ -213,7 +252,7 @@ static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
 	pll_min = 0;
 	pll_max = 0;
 
-	return dsi_pll_calc(dpi.dsidev, clkin,
+	return dsi_pll_calc(dpi->dsidev, clkin,
 			pll_min, pll_max,
 			dpi_calc_pll_cb, ctx);
 }
@@ -249,7 +288,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
 
 
 
-static int dpi_set_dsi_clk(enum omap_channel channel,
+static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
 		unsigned long pck_req, unsigned long *fck, int *lck_div,
 		int *pck_div)
 {
@@ -257,18 +296,18 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
 	int r;
 	bool ok;
 
-	ok = dpi_dsi_clk_calc(pck_req, &ctx);
+	ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx);
 	if (!ok)
 		return -EINVAL;
 
-	r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
+	r = dsi_pll_set_clock_div(dpi->dsidev, &ctx.dsi_cinfo);
 	if (r)
 		return r;
 
 	dss_select_lcd_clk_source(channel,
 			dpi_get_alt_clk_src(channel));
 
-	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
+	dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
 	*fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
 	*lck_div = ctx.dispc_cinfo.lck_div;
@@ -277,8 +316,8 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
 	return 0;
 }
 
-static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
-		int *lck_div, int *pck_div)
+static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
+		unsigned long *fck, int *lck_div, int *pck_div)
 {
 	struct dpi_clk_calc_ctx ctx;
 	int r;
@@ -292,7 +331,7 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
 	if (r)
 		return r;
 
-	dpi.mgr_config.clock_info = ctx.dispc_cinfo;
+	dpi->mgr_config.clock_info = ctx.dispc_cinfo;
 
 	*fck = ctx.fck;
 	*lck_div = ctx.dispc_cinfo.lck_div;
@@ -301,19 +340,21 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
 	return 0;
 }
 
-static int dpi_set_mode(struct omap_overlay_manager *mgr)
+static int dpi_set_mode(struct dpi_data *dpi)
 {
-	struct omap_video_timings *t = &dpi.timings;
+	struct omap_dss_device *out = &dpi->output;
+	struct omap_overlay_manager *mgr = out->manager;
+	struct omap_video_timings *t = &dpi->timings;
 	int lck_div = 0, pck_div = 0;
 	unsigned long fck = 0;
 	unsigned long pck;
 	int r = 0;
 
-	if (dpi.dsidev)
-		r = dpi_set_dsi_clk(mgr->id, t->pixelclock, &fck,
+	if (dpi->dsidev)
+		r = dpi_set_dsi_clk(dpi, mgr->id, t->pixelclock, &fck,
 				&lck_div, &pck_div);
 	else
-		r = dpi_set_dispc_clk(t->pixelclock, &fck,
+		r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
 				&lck_div, &pck_div);
 	if (r)
 		return r;
@@ -332,28 +373,32 @@ static int dpi_set_mode(struct omap_overlay_manager *mgr)
 	return 0;
 }
 
-static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr)
+static void dpi_config_lcd_manager(struct dpi_data *dpi)
 {
-	dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
+	struct omap_dss_device *out = &dpi->output;
+	struct omap_overlay_manager *mgr = out->manager;
 
-	dpi.mgr_config.stallmode = false;
-	dpi.mgr_config.fifohandcheck = false;
+	dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
 
-	dpi.mgr_config.video_port_width = dpi.data_lines;
+	dpi->mgr_config.stallmode = false;
+	dpi->mgr_config.fifohandcheck = false;
 
-	dpi.mgr_config.lcden_sig_polarity = 0;
+	dpi->mgr_config.video_port_width = dpi->data_lines;
 
-	dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
+	dpi->mgr_config.lcden_sig_polarity = 0;
+
+	dss_mgr_set_lcd_config(mgr, &dpi->mgr_config);
 }
 
 static int dpi_display_enable(struct omap_dss_device *dssdev)
 {
-	struct omap_dss_device *out = &dpi.output;
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+	struct omap_dss_device *out = &dpi->output;
 	int r;
 
-	mutex_lock(&dpi.lock);
+	mutex_lock(&dpi->lock);
 
-	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
+	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) {
 		DSSERR("no VDSS_DSI regulator\n");
 		r = -ENODEV;
 		goto err_no_reg;
@@ -366,7 +411,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
 	}
 
 	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
-		r = regulator_enable(dpi.vdds_dsi_reg);
+		r = regulator_enable(dpi->vdds_dsi_reg);
 		if (r)
 			goto err_reg_enable;
 	}
@@ -379,21 +424,21 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_src_sel;
 
-	if (dpi.dsidev) {
-		r = dsi_runtime_get(dpi.dsidev);
+	if (dpi->dsidev) {
+		r = dsi_runtime_get(dpi->dsidev);
 		if (r)
 			goto err_get_dsi;
 
-		r = dsi_pll_init(dpi.dsidev, 0, 1);
+		r = dsi_pll_init(dpi->dsidev, 0, 1);
 		if (r)
 			goto err_dsi_pll_init;
 	}
 
-	r = dpi_set_mode(out->manager);
+	r = dpi_set_mode(dpi);
 	if (r)
 		goto err_set_mode;
 
-	dpi_config_lcd_manager(out->manager);
+	dpi_config_lcd_manager(dpi);
 
 	mdelay(2);
 
@@ -401,78 +446,84 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_mgr_enable;
 
-	mutex_unlock(&dpi.lock);
+	mutex_unlock(&dpi->lock);
 
 	return 0;
 
 err_mgr_enable:
 err_set_mode:
-	if (dpi.dsidev)
-		dsi_pll_uninit(dpi.dsidev, true);
+	if (dpi->dsidev)
+		dsi_pll_uninit(dpi->dsidev, true);
 err_dsi_pll_init:
-	if (dpi.dsidev)
-		dsi_runtime_put(dpi.dsidev);
+	if (dpi->dsidev)
+		dsi_runtime_put(dpi->dsidev);
 err_get_dsi:
 err_src_sel:
 	dispc_runtime_put();
 err_get_dispc:
 	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-		regulator_disable(dpi.vdds_dsi_reg);
+		regulator_disable(dpi->vdds_dsi_reg);
 err_reg_enable:
 err_no_out_mgr:
 err_no_reg:
-	mutex_unlock(&dpi.lock);
+	mutex_unlock(&dpi->lock);
 	return r;
 }
 
 static void dpi_display_disable(struct omap_dss_device *dssdev)
 {
-	struct omap_overlay_manager *mgr = dpi.output.manager;
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+	struct omap_overlay_manager *mgr = dpi->output.manager;
 
-	mutex_lock(&dpi.lock);
+	mutex_lock(&dpi->lock);
 
 	dss_mgr_disable(mgr);
 
-	if (dpi.dsidev) {
+	if (dpi->dsidev) {
 		dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
-		dsi_pll_uninit(dpi.dsidev, true);
-		dsi_runtime_put(dpi.dsidev);
+		dsi_pll_uninit(dpi->dsidev, true);
+		dsi_runtime_put(dpi->dsidev);
 	}
 
 	dispc_runtime_put();
 
 	if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
-		regulator_disable(dpi.vdds_dsi_reg);
+		regulator_disable(dpi->vdds_dsi_reg);
 
-	mutex_unlock(&dpi.lock);
+	mutex_unlock(&dpi->lock);
 }
 
 static void dpi_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+
 	DSSDBG("dpi_set_timings\n");
 
-	mutex_lock(&dpi.lock);
+	mutex_lock(&dpi->lock);
 
-	dpi.timings = *timings;
+	dpi->timings = *timings;
 
-	mutex_unlock(&dpi.lock);
+	mutex_unlock(&dpi->lock);
 }
 
 static void dpi_get_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
-	mutex_lock(&dpi.lock);
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+
+	mutex_lock(&dpi->lock);
 
-	*timings = dpi.timings;
+	*timings = dpi->timings;
 
-	mutex_unlock(&dpi.lock);
+	mutex_unlock(&dpi->lock);
 }
 
 static int dpi_check_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
 {
-	struct omap_overlay_manager *mgr = dpi.output.manager;
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
+	struct omap_overlay_manager *mgr = dpi->output.manager;
 	int lck_div, pck_div;
 	unsigned long fck;
 	unsigned long pck;
@@ -485,8 +536,8 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
 	if (timings->pixelclock = 0)
 		return -EINVAL;
 
-	if (dpi.dsidev) {
-		ok = dpi_dsi_clk_calc(timings->pixelclock, &ctx);
+	if (dpi->dsidev) {
+		ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx);
 		if (!ok)
 			return -EINVAL;
 
@@ -511,11 +562,13 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
 
 static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
 {
-	mutex_lock(&dpi.lock);
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
-	dpi.data_lines = data_lines;
+	mutex_lock(&dpi->lock);
 
-	mutex_unlock(&dpi.lock);
+	dpi->data_lines = data_lines;
+
+	mutex_unlock(&dpi->lock);
 }
 
 static int dpi_verify_dsi_pll(struct platform_device *dsidev)
@@ -540,36 +593,36 @@ static int dpi_verify_dsi_pll(struct platform_device *dsidev)
 	return 0;
 }
 
-static int dpi_init_regulator(void)
+static int dpi_init_regulator(struct dpi_data *dpi)
 {
 	struct regulator *vdds_dsi;
 
 	if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
 		return 0;
 
-	if (dpi.vdds_dsi_reg)
+	if (dpi->vdds_dsi_reg)
 		return 0;
 
-	vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi");
+	vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
 	if (IS_ERR(vdds_dsi)) {
 		if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
 			DSSERR("can't get VDDS_DSI regulator\n");
 		return PTR_ERR(vdds_dsi);
 	}
 
-	dpi.vdds_dsi_reg = vdds_dsi;
+	dpi->vdds_dsi_reg = vdds_dsi;
 
 	return 0;
 }
 
-static void dpi_init_pll(void)
+static void dpi_init_pll(struct dpi_data *dpi)
 {
 	struct platform_device *dsidev;
 
-	if (dpi.dsidev)
+	if (dpi->dsidev)
 		return;
 
-	dsidev = dpi_get_dsidev(dpi.output.dispc_channel);
+	dsidev = dpi_get_dsidev(dpi->output.dispc_channel);
 	if (!dsidev)
 		return;
 
@@ -578,7 +631,7 @@ static void dpi_init_pll(void)
 		return;
 	}
 
-	dpi.dsidev = dsidev;
+	dpi->dsidev = dsidev;
 }
 
 /*
@@ -614,14 +667,15 @@ static enum omap_channel dpi_get_channel(void)
 static int dpi_connect(struct omap_dss_device *dssdev,
 		struct omap_dss_device *dst)
 {
+	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 	struct omap_overlay_manager *mgr;
 	int r;
 
-	r = dpi_init_regulator();
+	r = dpi_init_regulator(dpi);
 	if (r)
 		return r;
 
-	dpi_init_pll();
+	dpi_init_pll(dpi);
 
 	mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
 	if (!mgr)
@@ -672,7 +726,8 @@ static const struct omapdss_dpi_ops dpi_ops = {
 
 static void dpi_init_output(struct platform_device *pdev)
 {
-	struct omap_dss_device *out = &dpi.output;
+	struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
+	struct omap_dss_device *out = &dpi->output;
 
 	out->dev = &pdev->dev;
 	out->id = OMAP_DSS_OUTPUT_DPI;
@@ -685,18 +740,72 @@ static void dpi_init_output(struct platform_device *pdev)
 	omapdss_register_output(out);
 }
 
+static void dpi_init_output_port(struct platform_device *pdev,
+		struct device_node *port)
+{
+	struct dpi_data *dpi = port->data;
+	struct omap_dss_device *out = &dpi->output;
+	int r;
+	u32 reg;
+
+	r = of_property_read_u32(port, "reg", &reg);
+	if (r)
+		reg = 0;
+
+	switch (reg) {
+	case 2:
+		out->name = "dpi.2";
+		break;
+	case 1:
+		out->name = "dpi.1";
+		break;
+	case 0:
+	default:
+		out->name = "dpi.0";
+		break;
+	}
+
+	out->dev = &pdev->dev;
+	out->id = OMAP_DSS_OUTPUT_DPI;
+	out->output_type = OMAP_DISPLAY_TYPE_DPI;
+	out->dispc_channel = dpi_get_channel();
+	out->ops.dpi = &dpi_ops;
+	out->reg = reg;
+	out->owner = THIS_MODULE;
+
+	omapdss_register_output(out);
+}
+
 static void __exit dpi_uninit_output(struct platform_device *pdev)
 {
-	struct omap_dss_device *out = &dpi.output;
+	struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
+	struct omap_dss_device *out = &dpi->output;
+
+	omapdss_unregister_output(out);
+}
+
+static void dpi_uninit_output_port(struct platform_device *pdev,
+		struct device_node *port)
+{
+	struct dpi_data *dpi = port->data;
+	struct omap_dss_device *out = &dpi->output;
 
 	omapdss_unregister_output(out);
 }
 
 static int omap_dpi_probe(struct platform_device *pdev)
 {
-	dpi.pdev = pdev;
+	struct dpi_data *dpi;
+
+	dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
+	if (!dpi)
+		return -ENOMEM;
+
+	dpi->pdev = pdev;
+
+	dev_set_drvdata(&pdev->dev, dpi);
 
-	mutex_init(&dpi.lock);
+	mutex_init(&dpi->lock);
 
 	dpi_init_output(pdev);
 
@@ -731,10 +840,15 @@ void __exit dpi_uninit_platform_driver(void)
 
 int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
 {
+	struct dpi_data *dpi;
 	struct device_node *ep;
 	u32 datalines;
 	int r;
 
+	dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
+	if (!dpi)
+		return -ENOMEM;
+
 	ep = omapdss_of_get_next_endpoint(port, NULL);
 	if (!ep)
 		return 0;
@@ -745,17 +859,19 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
 		goto err_datalines;
 	}
 
-	dpi.data_lines = datalines;
-
 	of_node_put(ep);
 
-	dpi.pdev = pdev;
+	dpi->data_lines = datalines;
 
-	mutex_init(&dpi.lock);
+	port->data = dpi;
 
-	dpi_init_output(pdev);
+	dpi->pdev = pdev;
 
-	dpi.port_initialized = true;
+	mutex_init(&dpi->lock);
+
+	dpi_init_output_port(pdev, port);
+
+	dpi->port_initialized = true;
 
 	return 0;
 
@@ -767,8 +883,10 @@ err_datalines:
 
 void dpi_uninit_port(struct platform_device *pdev, struct device_node *port)
 {
-	if (!dpi.port_initialized)
+	struct dpi_data *dpi = port->data;
+
+	if (!dpi->port_initialized)
 		return;
 
-	dpi_uninit_output(dpi.pdev);
+	dpi_uninit_output_port(pdev, port);
 }
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 5/6] omapdss: DPI: make dpi_get_channel take DPI reg-id
From: Archit Taneja @ 2014-05-08  9:27 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1399540517-17883-1-git-send-email-archit@ti.com>

To support multiple DPI instances, dpi_get_channel needs to take the DPI
instance's reg-id to get the corresponding channel. Make it take this
argument.

We just pass 0 in the non-DT path, since we don't support multiple instances
in the non-DT case.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/fbdev/omap2/dss/dpi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index b891e17..faf266e 100644
--- a/drivers/video/fbdev/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -640,7 +640,7 @@ static void dpi_init_pll(struct dpi_data *dpi)
  * the channel in some more dynamic manner, or get the channel as a user
  * parameter.
  */
-static enum omap_channel dpi_get_channel(void)
+static enum omap_channel dpi_get_channel(int reg)
 {
 	switch (omapdss_get_version()) {
 	case OMAPDSS_VER_OMAP24xx:
@@ -733,7 +733,7 @@ static void dpi_init_output(struct platform_device *pdev)
 	out->id = OMAP_DSS_OUTPUT_DPI;
 	out->output_type = OMAP_DISPLAY_TYPE_DPI;
 	out->name = "dpi.0";
-	out->dispc_channel = dpi_get_channel();
+	out->dispc_channel = dpi_get_channel(0);
 	out->ops.dpi = &dpi_ops;
 	out->owner = THIS_MODULE;
 
@@ -768,7 +768,7 @@ static void dpi_init_output_port(struct platform_device *pdev,
 	out->dev = &pdev->dev;
 	out->id = OMAP_DSS_OUTPUT_DPI;
 	out->output_type = OMAP_DISPLAY_TYPE_DPI;
-	out->dispc_channel = dpi_get_channel();
+	out->dispc_channel = dpi_get_channel(reg);
 	out->ops.dpi = &dpi_ops;
 	out->reg = reg;
 	out->owner = THIS_MODULE;
-- 
1.8.3.2


^ permalink raw reply related

* [RFC 6/6] omapdss: DSS: add reg-id param to dpi_select_source
From: Archit Taneja @ 2014-05-08  9:27 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, Archit Taneja
In-Reply-To: <1399540517-17883-1-git-send-email-archit@ti.com>

Add an argument which describes which DPI instance we are referring to when
selecting it's overlay manager. This will come into use when a DSS version
supports multiple DPI instances.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/fbdev/omap2/dss/dpi.c |  2 +-
 drivers/video/fbdev/omap2/dss/dss.c | 12 ++++++------
 drivers/video/fbdev/omap2/dss/dss.h |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index faf266e..def8e68 100644
--- a/drivers/video/fbdev/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -420,7 +420,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_get_dispc;
 
-	r = dss_dpi_select_source(out->manager->id);
+	r = dss_dpi_select_source(out->reg, out->manager->id);
 	if (r)
 		goto err_src_sel;
 
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index 4087f3b..ffa6d84 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -74,7 +74,7 @@ struct dss_features {
 	u8 fck_div_max;
 	u8 dss_fck_multiplier;
 	const char *parent_clk_name;
-	int (*dpi_select_source)(enum omap_channel channel);
+	int (*dpi_select_source)(int id, enum omap_channel channel);
 	int (*init_ports)(struct platform_device *pdev);
 	void (*uninit_ports)(struct platform_device *pdev);
 };
@@ -570,7 +570,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
 	return REG_GET(DSS_CONTROL, 15, 15);
 }
 
-static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
+static int dss_dpi_select_source_omap2_omap3(int id, enum omap_channel channel)
 {
 	if (channel != OMAP_DSS_CHANNEL_LCD)
 		return -EINVAL;
@@ -578,7 +578,7 @@ static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
 	return 0;
 }
 
-static int dss_dpi_select_source_omap4(enum omap_channel channel)
+static int dss_dpi_select_source_omap4(int id, enum omap_channel channel)
 {
 	int val;
 
@@ -598,7 +598,7 @@ static int dss_dpi_select_source_omap4(enum omap_channel channel)
 	return 0;
 }
 
-static int dss_dpi_select_source_omap5(enum omap_channel channel)
+static int dss_dpi_select_source_omap5(int id, enum omap_channel channel)
 {
 	int val;
 
@@ -624,9 +624,9 @@ static int dss_dpi_select_source_omap5(enum omap_channel channel)
 	return 0;
 }
 
-int dss_dpi_select_source(enum omap_channel channel)
+int dss_dpi_select_source(int id, enum omap_channel channel)
 {
-	return dss.feat->dpi_select_source(channel);
+	return dss.feat->dpi_select_source(id, channel);
 }
 
 static int dss_get_clocks(void)
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
index 6f68f72..f3ddcc9 100644
--- a/drivers/video/fbdev/omap2/dss/dss.h
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -209,7 +209,7 @@ int dss_init_platform_driver(void) __init;
 void dss_uninit_platform_driver(void);
 
 unsigned long dss_get_dispc_clk_rate(void);
-int dss_dpi_select_source(enum omap_channel channel);
+int dss_dpi_select_source(int id, enum omap_channel channel);
 void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
 enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
 const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH v2 2/3] ARM: dts: oma3-gta04: Add display support
From: Tomi Valkeinen @ 2014-05-08  9:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAfyv36L_vh+iwrqsePsF8oOxOJ=JXUAk2nJ6F120w+0ivAn8w@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 427 bytes --]

On 07/05/14 10:21, Belisko Marek wrote:

>> Did you try this on 3.15-rc? The above is not right, and I don't think
>> it works. You need 'port' node for the dpi_out endpoint.
> This patches was tested against 3.15 series and it works. I'l recheck.

Ah, we still have some code that makes that work. But it's against the
bindings documentations, and that code will be removed. So better add
the port node.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v2 1/3] video: clps711x: Add new Cirrus Logic CLPS711X framebuffer driver
From: Tomi Valkeinen @ 2014-05-08 10:14 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1397285583-15187-1-git-send-email-shc_work@mail.ru>

[-- Attachment #1: Type: text/plain, Size: 2011 bytes --]

On 08/05/14 11:27, Alexander Shiyan wrote:

>>> At this time the driver has three user.
>>> Only one of them should theoretically work.
>>> clps711x-autcpu12 should not work in the absence of memblock_reserve().
>>> clps711x-p720t should not work due to physical address limitation as i
>>> noticed before. Board means to use SRAM instead of SDRAM.
>>> Only clps711x-edb7211 should work fine (in theory).
>>> Is this a good reason to replace the driver? I think yes.
>>
>> Ok, if the situation is that bad, maybe we can just switch to the new
>> driver. Have you verified that those boards do not work from anyone? Or
>> asked someone to test the new driver with those boards?
> 
> I'm not familiar with other users of this platform .
> I am do not have these boards, all that I have written before that it's just a theory.
> Firm in which I work, uses its own board with CLPS711X CPU , this board is the
> only way to check for changes on real hardware .

Ok. That makes me a bit nervous... You're removing a driver, which may
(or may not) have been working for other users. And adding a new one,
which may not (or may) work for the other users.

>> I'm still not really happy about it, and I'd much rather see the current
>> driver fixed. But if no one having those boards is up to the task
>> (probably not if they have not been working at all), maybe just ditching
>> the old driver and adding a new is the only way forward.
>>
>> One change that I think would be good is to change the series to first
>> remove the old driver, and then add the new one, with the same file name
>> as the old one. That way git log will show the history for both the new
>> and the old driver.
> 
> In this case git-bisect will be broken. Is this OK?

I think this is such a big change for the users of the driver that it's
not an issue. Of course, kernel should still build at all steps, but I
think it's fine if the fb driver in question will be out for a commit or
two.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v7][ 1/5] video: mx3fb: Use devm_kzalloc
From: Tomi Valkeinen @ 2014-05-08 10:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1394788369-5096-1-git-send-email-denis@eukrea.com>

[-- Attachment #1: Type: text/plain, Size: 571 bytes --]

On 14/03/14 11:12, Denis Carikli wrote:
> Replace kzalloc by devm_kzalloc and remove the kfree() calls.
> 
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> ChangeLog v6->v7:
> - Removed the Cc from the patch, they went into 
>   git send-email instead.
> ChangeLog v5->v6:
>  - New patch need
> ---
>  drivers/video/fbdev/mx3fb.c |    4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)

I've picked this patch for 3.16. I didn't pick the DT related patches in
this series as there seemed to be unanswered questions about them.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] video: exynos: Add a dependency to the menu
From: Tomi Valkeinen @ 2014-05-08 10:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140408120056.57556a00@endymion.delvare>

[-- Attachment #1: Type: text/plain, Size: 1366 bytes --]

On 08/04/14 13:00, Jean Delvare wrote:
> All drivers under menu EXYNOS_VIDEO depend on either ARCH_S5PV210 or
> ARCH_EXYNOS, so add these as dependencies to the menu itself. This
> avoids presenting an empty and useless menu on other architectures.
> 
> Then drivers under the menu only need a dependency if they depend on
> one of the supported architectures specifically.
> 
> Signed-off-by: Jean Delvare <jdelvare@suse.de>
> Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> ---
>  drivers/video/exynos/Kconfig |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> --- linux-3.15-rc0.orig/drivers/video/exynos/Kconfig	2014-04-07 10:23:07.316226676 +0200
> +++ linux-3.15-rc0/drivers/video/exynos/Kconfig	2014-04-08 11:50:17.406723187 +0200
> @@ -4,6 +4,7 @@
>  
>  menuconfig EXYNOS_VIDEO
>  	bool "Exynos Video driver support"
> +	depends on ARCH_S5PV210 || ARCH_EXYNOS
>  	help
>  	  This enables support for EXYNOS Video device.
>  
> @@ -15,7 +16,6 @@ if EXYNOS_VIDEO
>  
>  config EXYNOS_MIPI_DSI
>  	bool "EXYNOS MIPI DSI driver support."
> -	depends on ARCH_S5PV210 || ARCH_EXYNOS
>  	select GENERIC_PHY
>  	help
>  	  This enables support for MIPI-DSI device.
> 
> 

I've applied this for 3.16.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v2] video: mx3fb: Add backlight support
From: Tomi Valkeinen @ 2014-05-08 10:47 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1399273010-24706-1-git-send-email-alexander.stein@systec-electronic.com>

[-- Attachment #1: Type: text/plain, Size: 399 bytes --]

Hi,

On 05/05/14 09:56, Alexander Stein wrote:
> Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
> ---

Please always have a commit description, even if it's more or less the
same as the subject.

Is the backlight PWM hardware part of the display hardware on mx3fb? If
so, I guess it's ok to have the backlight in the fb driver, as you're
doing here.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v2] video: mx3fb: Add backlight support
From: Tomi Valkeinen @ 2014-05-08 10:48 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1399273010-24706-1-git-send-email-alexander.stein@systec-electronic.com>

[-- Attachment #1: Type: text/plain, Size: 486 bytes --]

On 08/05/14 13:47, Tomi Valkeinen wrote:
> Hi,
> 
> On 05/05/14 09:56, Alexander Stein wrote:
>> Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
>> ---
> 
> Please always have a commit description, even if it's more or less the
> same as the subject.

Oh, and I'd rather have a bit more explanation than "add backlight
support". The current driver seems to have some backlight code. So what
are you actually adding with this patch? Etc.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] video: Kconfig: Add a dependency to the Goldfish framebuffer driver
From: Tomi Valkeinen @ 2014-05-08 10:50 UTC (permalink / raw)
  To: linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 926 bytes --]

On 23/04/14 13:42, Jean Delvare wrote:
> All other Goldfish drivers depend on GOLDFISH, I see no reason why the
> framebuffer driver would be an exception.
> 
> Signed-off-by: Jean Delvare <jdelvare@suse.de>
> Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> ---
>  drivers/video/fbdev/Kconfig |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> --- linux-3.15-rc2.orig/drivers/video/fbdev/Kconfig	2014-04-22 14:20:30.949107522 +0200
> +++ linux-3.15-rc2/drivers/video/fbdev/Kconfig	2014-04-23 11:51:17.163933232 +0200
> @@ -2169,7 +2169,7 @@ config FB_XILINX
>  
>  config FB_GOLDFISH
>  	tristate "Goldfish Framebuffer"
> -	depends on FB && HAS_DMA
> +	depends on FB && HAS_DMA && (GOLDFISH || COMPILE_TEST)
>  	select FB_CFB_FILLRECT
>  	select FB_CFB_COPYAREA
>  	select FB_CFB_IMAGEBLIT
> 
> 

Queued for 3.16.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] fbcon: Fix memory leak in con2fb_release_oldinfo()
From: Tomi Valkeinen @ 2014-05-08 10:55 UTC (permalink / raw)
  To: Masami Ichikawa, plagnioj, udknight, gregkh, keithp,
	mika.kuoppala, viresh.kumar, linux-kernel, linux-fbdev
In-Reply-To: <1398263722-10436-1-git-send-email-masami256@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2223 bytes --]

On 23/04/14 17:35, Masami Ichikawa wrote:
> kmemleak reported a memory leak as below.
> 
> unreferenced object 0xffff8800dab6d8d8 (size 96):
>   comm "swapper/0", pid 1, jiffies 4294877598 (age 38.483s)
>   hex dump (first 32 bytes):
>     00 00 00 00 00 01 00 00 08 00 00 00 10 00 00 00  ................
>     07 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00  ................
>   backtrace:
>     [<ffffffff814e8f2e>] kmemleak_alloc+0x4e/0xb0
>     [<ffffffff811a0600>] __kmalloc+0x280/0x320
>     [<ffffffff81309b61>] soft_cursor+0x231/0x290
>     [<ffffffff81309393>] bit_cursor+0x613/0x650
>     [<ffffffff8130556b>] fbcon_cursor+0x13b/0x1c0
>     [<ffffffff813755f8>] hide_cursor+0x28/0xa0
>     [<ffffffff81376e98>] redraw_screen+0x168/0x240
>     [<ffffffff81303891>] fbcon_prepare_logo+0x381/0x420
>     [<ffffffff81303c7e>] fbcon_init+0x34e/0x590
>     [<ffffffff81375828>] visual_init+0xb8/0x120
>     [<ffffffff81377c93>] do_bind_con_driver+0x163/0x380
>     [<ffffffff81378494>] do_take_over_console+0x114/0x1c0
>     [<ffffffff81303f23>] do_fbcon_takeover+0x63/0xd0
>     [<ffffffff813086dd>] fbcon_event_notify+0x68d/0x7e0
>     [<ffffffff814ff7ac>] notifier_call_chain+0x4c/0x70
>     [<ffffffff8108c85d>] __blocking_notifier_call_chain+0x4d/0x70
> 
> This memory leak cause is, fbcon_ops's cursor_src is allocated in
> soft_cursor() but not released in con2fb_release_oldinfo().
> so, cursor_src is needed to be released when oldinfo is going to be
> released.
> 
> Signed-off-by: Masami Ichikawa <masami256@gmail.com>
> ---
>  drivers/video/console/fbcon.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
> index f447734..57b1d44 100644
> --- a/drivers/video/console/fbcon.c
> +++ b/drivers/video/console/fbcon.c
> @@ -748,6 +748,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
>  		fbcon_del_cursor_timer(oldinfo);
>  		kfree(ops->cursor_state.mask);
>  		kfree(ops->cursor_data);
> +		kfree(ops->cursor_src);
>  		kfree(ops->fontbuffer);
>  		kfree(oldinfo->fbcon_par);
>  		oldinfo->fbcon_par = NULL;
> 

Thanks, queued for 3.16.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [PATCH v6 1/2] video: ARM CLCD: Add DT support
From: Pawel Moll @ 2014-05-08 11:00 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds basic DT bindings for the PL11x CLCD cells
and make their fbdev driver use them.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
Changes since v5:
- realised that dma_alloc_writecombine() is a arm-specific function;
  replaced with generic dma_alloc_coherent()/dma_mmap_writecombine()

Changes since v4:
- simplified the pads description property and made it optional

Changes since v3:
- changed wording and order of interrupt-names and interrupts
  properties documentation
- changed wording of arm,pl11x,framebuffer-base property
  documentation
- cleaned up binding documentation indentation

Changes since v2:
- replaced video-ram phandle with arm,pl11x,framebuffer-base
- replaced panel-* properties with arm,pl11x,panel-data-pads
- replaced max-framebuffer-size with max-memory-bandwidth
- modified clcdfb_of_init_tft_panel() to use the pads
  data and take differences between PL110 and PL110 into
  account

Changes since v1:
- minor code cleanups as suggested by Sylwester Nawrocki

 .../devicetree/bindings/video/arm,pl11x.txt        |  83 ++++++++
 drivers/video/fbdev/Kconfig                        |   2 +
 drivers/video/fbdev/amba-clcd.c                    | 219 +++++++++++++++++++++
 3 files changed, 304 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/arm,pl11x.txt

diff --git a/Documentation/devicetree/bindings/video/arm,pl11x.txt b/Documentation/devicetree/bindings/video/arm,pl11x.txt
new file mode 100644
index 0000000..75da7b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/arm,pl11x.txt
@@ -0,0 +1,83 @@
+* ARM PrimeCell Color LCD Controller PL110/PL111
+
+See also Documentation/devicetree/bindings/arm/primecell.txt
+
+Required properties:
+
+- compatible: must be one of:
+	"arm,pl110", "arm,primecell"
+	"arm,pl111", "arm,primecell"
+
+- reg: base address and size of the control registers block
+
+- interrupt-names: either the single entry "combined" representing a
+	combined interrupt output (CLCDINTR), or the four entries
+	"mbe", "vcomp", "lnbu", "fuf" representing the individual
+	CLCDMBEINTR, CLCDVCOMPINTR, CLCDLNBUINTR, CLCDFUFINTR interrupts
+
+- interrupts: contains an interrupt specifier for each entry in
+	interrupt-names
+
+- clocks-names: should contain "clcdclk" and "apb_pclk"
+
+- clocks: contains phandle and clock specifier pairs for the entries
+	in the clock-names property. See
+	Documentation/devicetree/binding/clock/clock-bindings.txt
+
+Optional properties:
+
+- arm,pl11x,framebuffer-base: a pair of two 32-bit values, address and size,
+	defining the framebuffer that must be used; if not present, the
+	framebuffer may be located anywhere in the memory
+
+- arm,pl11x,tft-r0g0b0-pads: when connected to a TFT panel, an array of three
+	32-bit values, defining the way CLD pads are wired up; this implicitly
+	defines available color modes, for example:
+	- PL111 TFT 4:4:4 panel:
+		arm,pl11x,tft-r0g0b0-pads = <4 15 20>;
+	- PL110 TFT (1:)5:5:5 panel:
+		arm,pl11x,tft-r0g0b0-pads = <1 7 13>;
+	- PL111 TFT (1:)5:5:5 panel:
+		arm,pl11x,tft-r0g0b0-pads = <3 11 19>;
+	- PL111 TFT 5:6:5 panel:
+		arm,pl11x,tft-r0g0b0-pads = <3 10 19>;
+	- PL110 and PL111 TFT 8:8:8 panel:
+		arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+	- PL110 and PL111 TFT 8:8:8 panel, R & B components swapped:
+		arm,pl11x,tft-r0g0b0-pads = <16 8 0>;
+
+- max-memory-bandwidth: maximum bandwidth in bytes per second that the
+	cell's memory interface can handle
+
+- display-timings: standard display timings sub-node, defining possible
+	video modes of a connected panel; for details see
+	Documentation/devicetree/bindings/video/display-timing.txt
+
+Example:
+
+	clcd@1f0000 {
+		compatible = "arm,pl111", "arm,primecell";
+		reg = <0x1f0000 0x1000>;
+		interrupt-names = "combined";
+		interrupts = <14>;
+		clock-names = "clcdclk", "apb_pclk";
+		clocks = <&v2m_oscclk1>, <&smbclk>;
+
+		arm,pl11x,framebuffer-base = <0x18000000 0x00800000>;
+		arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+		max-memory-bandwidth = <36864000>; /* bps, 640x480@60 16bpp */
+		display-timings {
+			native-mode = <&v2m_clcd_timing0>;
+			v2m_clcd_timing0: vga {
+				clock-frequency = <25175000>;
+				hactive = <640>;
+				hback-porch = <40>;
+				hfront-porch = <24>;
+				hsync-len = <96>;
+				vactive = <480>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <2>;
+			};
+		};
+	};
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index e1f4727..06045d8 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -280,6 +280,8 @@ config FB_ARMCLCD
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_MODE_HELPERS if OF
+	select VIDEOMODE_HELPERS if OF
 	help
 	  This framebuffer device driver is for the ARM PrimeCell PL110
 	  Colour LCD controller.  ARM PrimeCells provide the building
diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c
index 14d6b37..c1f2eaa 100644
--- a/drivers/video/fbdev/amba-clcd.c
+++ b/drivers/video/fbdev/amba-clcd.c
@@ -26,6 +26,11 @@
 #include <linux/amba/clcd.h>
 #include <linux/clk.h>
 #include <linux/hardirq.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
 
 #include <asm/sizes.h>
 
@@ -543,6 +548,217 @@ static int clcdfb_register(struct clcd_fb *fb)
 	return ret;
 }
 
+#ifdef CONFIG_OF
+static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
+{
+	static struct {
+		unsigned int part;
+		u32 r0, g0, b0;
+		u32 caps;
+	} panels[] = {
+		{ 0x110, 1,  7, 13, CLCD_CAP_5551 },
+		{ 0x110, 0,  8, 16, CLCD_CAP_888 },
+		{ 0x111, 4, 14, 20, CLCD_CAP_444 },
+		{ 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 },
+		{ 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 |
+				    CLCD_CAP_565 },
+		{ 0x111, 0,  8, 16, CLCD_CAP_444 | CLCD_CAP_5551 |
+				    CLCD_CAP_565 | CLCD_CAP_888 },
+	};
+	int i;
+
+	/* Bypass pixel clock divider, data output on the falling edge */
+	fb->panel->tim2 = TIM2_BCD | TIM2_IPC;
+
+	/* TFT display, vert. comp. interrupt at the start of the back porch */
+	fb->panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1);
+
+	fb->panel->caps = 0;
+
+	/* Match the setup with known variants */
+	for (i = 0; i < ARRAY_SIZE(panels) && !fb->panel->caps; i++) {
+		if (amba_part(fb->dev) != panels[i].part)
+			continue;
+		if (g0 != panels[i].g0)
+			continue;
+		if (r0 = panels[i].r0 && b0 = panels[i].b0)
+			fb->panel->caps = panels[i].caps & CLCD_CAP_RGB;
+		if (r0 = panels[i].b0 && b0 = panels[i].r0)
+			fb->panel->caps = panels[i].caps & CLCD_CAP_BGR;
+	}
+
+	return fb->panel->caps ? 0 : -EINVAL;
+}
+
+static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode)
+{
+	return snprintf(buf, size, "%ux%u@%u", mode->xres, mode->yres,
+			mode->refresh);
+}
+
+static int clcdfb_of_init_display(struct clcd_fb *fb)
+{
+	struct device_node *node = fb->dev->dev.of_node;
+	int err, len;
+	char *mode_name;
+	u32 max_bandwidth;
+	u32 tft_r0b0g0[3];
+
+	fb->panel = devm_kzalloc(&fb->dev->dev, sizeof(*fb->panel), GFP_KERNEL);
+	if (!fb->panel)
+		return -ENOMEM;
+
+	err = of_get_fb_videomode(node, &fb->panel->mode, OF_USE_NATIVE_MODE);
+	if (err)
+		return err;
+
+	len = clcdfb_snprintf_mode(NULL, 0, &fb->panel->mode);
+	mode_name = devm_kzalloc(&fb->dev->dev, len + 1, GFP_KERNEL);
+	clcdfb_snprintf_mode(mode_name, len + 1, &fb->panel->mode);
+	fb->panel->mode.name = mode_name;
+
+	err = of_property_read_u32(node, "max-memory-bandwidth",
+			&max_bandwidth);
+	if (!err)
+		fb->panel->bpp = 8 * max_bandwidth / (fb->panel->mode.xres *
+				fb->panel->mode.yres * fb->panel->mode.refresh);
+	else
+		fb->panel->bpp = 32;
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	fb->panel->cntl |= CNTL_BEBO;
+#endif
+	fb->panel->width = -1;
+	fb->panel->height = -1;
+
+	if (of_property_read_u32_array(node, "arm,pl11x,tft-r0g0b0-pads",
+			tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) = 0)
+		return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
+				 tft_r0b0g0[1],  tft_r0b0g0[2]);
+
+	return -ENOENT;
+}
+
+static int clcdfb_of_vram_setup(struct clcd_fb *fb)
+{
+	int err;
+	u32 values[2];
+	phys_addr_t phys_base;
+	size_t size;
+
+	err = clcdfb_of_init_display(fb);
+	if (err)
+		return err;
+
+	err = of_property_read_u32_array(fb->dev->dev.of_node,
+			"arm,pl11x,framebuffer-base",
+			values, ARRAY_SIZE(values));
+	if (err)
+		return err;
+
+	phys_base = values[0];
+	size = values[1];
+
+	fb->fb.screen_base = ioremap(phys_base, size);
+	if (!fb->fb.screen_base)
+		return -ENOMEM;
+
+	fb->fb.fix.smem_start = phys_base;
+	fb->fb.fix.smem_len = size;
+
+	return 0;
+}
+
+static int clcdfb_of_vram_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	unsigned long off, user_size, kernel_size;
+
+
+	off = vma->vm_pgoff << PAGE_SHIFT;
+	user_size = vma->vm_end - vma->vm_start;
+	kernel_size = fb->fb.fix.smem_len;
+
+	if (off >= kernel_size || user_size > (kernel_size - off))
+		return -ENXIO;
+
+	return remap_pfn_range(vma, vma->vm_start,
+			__phys_to_pfn(fb->fb.fix.smem_start) + vma->vm_pgoff,
+			user_size,
+			pgprot_writecombine(vma->vm_page_prot));
+}
+
+static void clcdfb_of_vram_remove(struct clcd_fb *fb)
+{
+	iounmap(fb->fb.screen_base);
+}
+
+static int clcdfb_of_dma_setup(struct clcd_fb *fb)
+{
+	unsigned long framesize;
+	dma_addr_t dma;
+	int err;
+
+	err = clcdfb_of_init_display(fb);
+	if (err)
+		return err;
+
+	framesize = fb->panel->mode.xres * fb->panel->mode.yres *
+			fb->panel->bpp / 8;
+	fb->fb.screen_base = dma_alloc_coherent(&fb->dev->dev, framesize,
+			&dma, GFP_KERNEL);
+	if (!fb->fb.screen_base)
+		return -ENOMEM;
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = framesize;
+
+	return 0;
+}
+
+static int clcdfb_of_dma_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
+			fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+}
+
+static void clcdfb_of_dma_remove(struct clcd_fb *fb)
+{
+	dma_free_coherent(&fb->dev->dev, fb->fb.fix.smem_len,
+			fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
+{
+	struct clcd_board *board = devm_kzalloc(&dev->dev, sizeof(*board),
+			GFP_KERNEL);
+	struct device_node *node = dev->dev.of_node;
+
+	if (!board)
+		return NULL;
+
+	board->name = of_node_full_name(node);
+	board->caps = CLCD_CAP_ALL;
+	board->check = clcdfb_check;
+	board->decode = clcdfb_decode;
+	if (of_find_property(node, "arm,pl11x,framebuffer-base", NULL)) {
+		board->setup = clcdfb_of_vram_setup;
+		board->mmap = clcdfb_of_vram_mmap;
+		board->remove = clcdfb_of_vram_remove;
+	} else {
+		board->setup = clcdfb_of_dma_setup;
+		board->mmap = clcdfb_of_dma_mmap;
+		board->remove = clcdfb_of_dma_remove;
+	}
+
+	return board;
+}
+#else
+static struct clcd_board *clcdfb_of_get_board(struct amba_dev *dev)
+{
+	return NULL;
+}
+#endif
+
 static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct clcd_board *board = dev_get_platdata(&dev->dev);
@@ -550,6 +766,9 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
 	int ret;
 
 	if (!board)
+		board = clcdfb_of_get_board(dev);
+
+	if (!board)
 		return -EINVAL;
 
 	ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
-- 
1.9.1


^ permalink raw reply related

* [PATCH v6 2/2] ARM: vexpress: Add CLCD Device Tree properties
From: Pawel Moll @ 2014-05-08 11:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1399546830-2931-1-git-send-email-pawel.moll@arm.com>

... for V2M-P1 motherboard CLCD (limited to 640x480 16bpp and using
dedicated video RAM bank) and for V2P-CA9 (up to 1024x768 16bpp).

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 21 ++++++++++++++++++++-
 arch/arm/boot/dts/vexpress-v2m.dtsi     | 21 ++++++++++++++++++++-
 arch/arm/boot/dts/vexpress-v2p-ca9.dts  | 18 ++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index ac870fb..c95a4cb 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -230,9 +230,28 @@
 			clcd@1f0000 {
 				compatible = "arm,pl111", "arm,primecell";
 				reg = <0x1f0000 0x1000>;
+				interrupt-names = "combined";
 				interrupts = <14>;
 				clocks = <&v2m_oscclk1>, <&smbclk>;
 				clock-names = "clcdclk", "apb_pclk";
+
+				arm,pl11x,framebuffer-base = <0x18000000 0x00800000>;
+				arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+				max-memory-bandwidth = <36864000>; /* Bps, 640x480@60 16bpp */
+				display-timings {
+					native-mode = <&v2m_clcd_timing0>;
+					v2m_clcd_timing0: vga {
+						clock-frequency = <25175000>;
+						hactive = <640>;
+						hback-porch = <40>;
+						hfront-porch = <24>;
+						hsync-len = <96>;
+						vactive = <480>;
+						vback-porch = <32>;
+						vfront-porch = <11>;
+						vsync-len = <2>;
+					};
+				};
 			};
 		};
 
@@ -282,7 +301,7 @@
 				/* CLCD clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 1>;
-				freq-range = <23750000 63500000>;
+				freq-range = <23750000 65000000>;
 				#clock-cells = <0>;
 				clock-output-names = "v2m:oscclk1";
 			};
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index f142036..9224834 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -229,9 +229,28 @@
 			clcd@1f000 {
 				compatible = "arm,pl111", "arm,primecell";
 				reg = <0x1f000 0x1000>;
+				interrupt-names = "combined";
 				interrupts = <14>;
 				clocks = <&v2m_oscclk1>, <&smbclk>;
 				clock-names = "clcdclk", "apb_pclk";
+
+				arm,pl11x,framebuffer-base = <0x4c000000 0x00800000>;
+				arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+				max-memory-bandwidth = <36864000>; /* Bps, 640x480@60 16bpp */
+				display-timings {
+					native-mode = <&v2m_clcd_timing0>;
+					v2m_clcd_timing0: vga {
+						clock-frequency = <25175000>;
+						hactive = <640>;
+						hback-porch = <40>;
+						hfront-porch = <24>;
+						hsync-len = <96>;
+						vactive = <480>;
+						vback-porch = <32>;
+						vfront-porch = <11>;
+						vsync-len = <2>;
+					};
+				};
 			};
 		};
 
@@ -281,7 +300,7 @@
 				/* CLCD clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 1>;
-				freq-range = <23750000 63500000>;
+				freq-range = <23750000 65000000>;
 				#clock-cells = <0>;
 				clock-output-names = "v2m:oscclk1";
 			};
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
index 62d9b22..ed4f223 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
@@ -70,9 +70,27 @@
 	clcd@10020000 {
 		compatible = "arm,pl111", "arm,primecell";
 		reg = <0x10020000 0x1000>;
+		interrupt-names = "combined";
 		interrupts = <0 44 4>;
 		clocks = <&oscclk1>, <&oscclk2>;
 		clock-names = "clcdclk", "apb_pclk";
+
+		arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+		max-memory-bandwidth = <94371840>; /* Bps, 1024x768@60 16bpp */
+		display-timings {
+			native-mode = <&clcd_timing0>;
+			clcd_timing0: xga {
+				clock-frequency = <63500127>;
+				hactive = <1024>;
+				hback-porch = <152>;
+				hfront-porch = <48>;
+				hsync-len = <104>;
+				vactive = <768>;
+				vback-porch = <23>;
+				vfront-porch = <3>;
+				vsync-len = <4>;
+			};
+		};
 	};
 
 	memory-controller@100e0000 {
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH v6 1/2] video: ARM CLCD: Add DT support
From: Pawel Moll @ 2014-05-08 11:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1399546830-2931-1-git-send-email-pawel.moll@arm.com>

On Thu, 2014-05-08 at 12:00 +0100, Pawel Moll wrote:
> This patch adds basic DT bindings for the PL11x CLCD cells
> and make their fbdev driver use them.
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>

Russell,

I've added it to your patch system as 8005/2. If you were so kind to
have a look, I would appreciate either ack or nak.

Thanks!

Pawel


^ permalink raw reply

* [PATCH v3] video: mx3fb: Add backlight control support
From: Alexander Stein @ 2014-05-08 14:38 UTC (permalink / raw)
  To: linux-fbdev

This patch add backlight control support to allow dimming the backlight
using the internal PWM. Currently the brightness is set fixed to a
maximum of 255.

Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
---
Changes in v3:
* Add a more descriptive commit message

Changes in v2:
* rebased to v3.15-rc4

 drivers/video/fbdev/mx3fb.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/drivers/video/fbdev/mx3fb.c b/drivers/video/fbdev/mx3fb.c
index 142e860..10a7244 100644
--- a/drivers/video/fbdev/mx3fb.c
+++ b/drivers/video/fbdev/mx3fb.c
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/mutex.h>
 #include <linux/dma/ipu-dma.h>
+#include <linux/backlight.h>
 
 #include <linux/platform_data/dma-imx.h>
 #include <linux/platform_data/video-mx3fb.h>
@@ -34,6 +35,12 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
+	(defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) && \
+		defined(CONFIG_MX3FB_MODULE))
+#define PWM_BACKLIGHT_AVAILABLE
+#endif
+
 #define MX3FB_NAME		"mx3_sdc_fb"
 
 #define MX3FB_REG_OFFSET	0xB4
@@ -242,6 +249,10 @@ struct mx3fb_data {
 	spinlock_t		lock;
 	struct device		*dev;
 
+#ifdef PWM_BACKLIGHT_AVAILABLE
+	struct backlight_device	*bl;
+#endif
+
 	uint32_t		h_start_width;
 	uint32_t		v_start_width;
 	enum disp_data_mapping	disp_data_fmt;
@@ -271,6 +282,74 @@ struct mx3fb_info {
 	struct fb_var_screeninfo	cur_var; /* current var info */
 };
 
+static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value);
+
+#ifdef PWM_BACKLIGHT_AVAILABLE
+static u32 sdc_get_brightness(struct mx3fb_data *mx3fb);
+
+static int mx3fb_bl_get_brightness(struct backlight_device *bl)
+{
+	struct mx3fb_data *fbd = bl_get_data(bl);
+
+	return sdc_get_brightness(fbd);
+}
+
+static int mx3fb_bl_update_status(struct backlight_device *bl)
+{
+	struct mx3fb_data *fbd = bl_get_data(bl);
+	int brightness = bl->props.brightness;
+
+	if (bl->props.power != FB_BLANK_UNBLANK)
+		brightness = 0;
+	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	fbd->backlight_level = (fbd->backlight_level & ~0xFF) | brightness;
+
+	sdc_set_brightness(fbd, fbd->backlight_level);
+
+	return 0;
+}
+
+static const struct backlight_ops mx3fb_lcdc_bl_ops = {
+	.update_status = mx3fb_bl_update_status,
+	.get_brightness = mx3fb_bl_get_brightness,
+};
+
+static void mx3fb_init_backlight(struct mx3fb_data *fbd)
+{
+	struct backlight_properties props;
+	struct backlight_device	*bl;
+
+	if (fbd->bl)
+		return;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 0xff;
+	props.type = BACKLIGHT_RAW;
+	sdc_set_brightness(fbd, fbd->backlight_level);
+
+	bl = backlight_device_register("mx3fb-bl", fbd->dev, fbd,
+				       &mx3fb_lcdc_bl_ops, &props);
+	if (IS_ERR(bl)) {
+		dev_err(fbd->dev, "error %ld on backlight register\n",
+				PTR_ERR(bl));
+		return;
+	}
+
+	fbd->bl = bl;
+	bl->props.power = FB_BLANK_UNBLANK;
+	bl->props.fb_blank = FB_BLANK_UNBLANK;
+	bl->props.brightness = mx3fb_bl_get_brightness(bl);
+}
+
+static void mx3fb_exit_backlight(struct mx3fb_data *fbd)
+{
+	if (fbd->bl)
+		backlight_device_unregister(fbd->bl);
+}
+#endif
+
 static void mx3fb_dma_done(void *);
 
 /* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */
@@ -628,6 +707,18 @@ static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t a
 	return 0;
 }
 
+#ifdef PWM_BACKLIGHT_AVAILABLE
+static u32 sdc_get_brightness(struct mx3fb_data *mx3fb)
+{
+	u32 brightness;
+
+	brightness = mx3fb_read_reg(mx3fb, SDC_PWM_CTRL);
+	brightness = (brightness >> 16) & 0xFF;
+
+	return brightness;
+}
+#endif
+
 static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
 {
 	dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
@@ -1534,6 +1625,9 @@ static int mx3fb_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto eisdc0;
 
+#ifdef PWM_BACKLIGHT_AVAILABLE
+	mx3fb_init_backlight(mx3fb);
+#endif
 	return 0;
 
 eisdc0:
@@ -1557,6 +1651,10 @@ static int mx3fb_remove(struct platform_device *dev)
 	chan = &mx3_fbi->idmac_channel->dma_chan;
 	release_fbi(fbi);
 
+#ifdef PWM_BACKLIGHT_AVAILABLE
+	mx3fb_exit_backlight(mx3fb);
+#endif
+
 	dma_release_channel(chan);
 	dmaengine_put();
 
-- 
1.8.5.5


^ permalink raw reply related

* [PATCH v3 0/3] Add display support for gta04 device
From: Marek Belisko @ 2014-05-08 20:16 UTC (permalink / raw)
  To: linux-arm-kernel

This 3 patches adding display support for openmoko gta04 device.
First patch add DT bindings for topolly td028 panel. Second add description for
dss + panel and third fix panel probing when panel is compiled as module.

Changes from v2:
- add missing 'port' node for dpi_out endpoint (comment from Tomi Valkeinen)

Changes from v1:
- extend panel compatible string by 'omapdss'
- add tpo-td028 panel to dss_compat_conv_list
- add MODULE_ALIAS macro to properly probe panel when is compiled as module

Marek Belisko (3):
  omapdss: panel-tpo-td028ec1: Add DT support.
  ARM: dts: oma3-gta04: Add display support
  omapdss: panel-tpo-td028ec1: Add module alias

 .../bindings/video/toppoly,td028ttec1.txt          | 30 ++++++++
 arch/arm/boot/dts/omap3-gta04.dts                  | 87 ++++++++++++++++++++++
 arch/arm/mach-omap2/display.c                      |  1 +
 .../omap2/displays-new/panel-tpo-td028ttec1.c      | 33 +++++++-
 4 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt

-- 
1.9.1


^ permalink raw reply

* [PATCH v3 1/3] omapdss: panel-tpo-td028ec1: Add DT support.
From: Marek Belisko @ 2014-05-08 20:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1399580212-5183-1-git-send-email-marek@goldelico.com>

Signed-off-by: Marek Belisko <marek@goldelico.com>
---
 .../bindings/video/toppoly,td028ttec1.txt          | 30 ++++++++++++++++++++
 arch/arm/mach-omap2/display.c                      |  1 +
 .../omap2/displays-new/panel-tpo-td028ttec1.c      | 32 +++++++++++++++++++++-
 3 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt

diff --git a/Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt b/Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt
new file mode 100644
index 0000000..7175dc3
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt
@@ -0,0 +1,30 @@
+Toppoly TD028TTEC1 Panel
+============
+
+Required properties:
+- compatible: "toppoly,td028ttec1"
+
+Optional properties:
+- label: a symbolic name for the panel
+
+Required nodes:
+- Video port for DPI input
+
+Example
+-------
+
+lcd-panel: td028ttec1@0 {
+	compatible = "toppoly,td028ttec1";
+	reg = <0>;
+	spi-max-frequency = <100000>;
+	spi-cpol;
+	spi-cpha;
+
+	label = "lcd";
+	port {
+		lcd_in: endpoint {
+			remote-endpoint = <&dpi_out>;
+		};
+	};
+};
+
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 16d33d8..66a2ee0 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -566,6 +566,7 @@ static const char * const dss_compat_conv_list[] __initconst = {
 	"svideo-connector",
 	"ti,tfp410",
 	"ti,tpd12s015",
+	"toppoly,td028ttec1",
 };
 
 /* prepend compatible string with "omapdss," */
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
index fae6adc..5b3466e 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
@@ -206,7 +206,8 @@ static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
 	if (omapdss_device_is_enabled(dssdev))
 		return 0;
 
-	in->ops.dpi->set_data_lines(in, ddata->data_lines);
+	if (ddata->data_lines)
+		in->ops.dpi->set_data_lines(in, ddata->data_lines);
 	in->ops.dpi->set_timings(in, &ddata->videomode);
 
 	r = in->ops.dpi->enable(in);
@@ -389,6 +390,23 @@ static int td028ttec1_panel_probe_pdata(struct spi_device *spi)
 	return 0;
 }
 
+static int td028ttec1_probe_of(struct spi_device *spi)
+{
+	struct device_node *node = spi->dev.of_node;
+	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
+	struct omap_dss_device *in;
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&spi->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	return 0;
+}
+
 static int td028ttec1_panel_probe(struct spi_device *spi)
 {
 	struct panel_drv_data *ddata;
@@ -418,6 +436,10 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
 		r = td028ttec1_panel_probe_pdata(spi);
 		if (r)
 			return r;
+	} else if (spi->dev.of_node) {
+		r = td028ttec1_probe_of(spi);
+		if (r)
+			return r;
 	} else {
 		return -ENODEV;
 	}
@@ -463,6 +485,13 @@ static int td028ttec1_panel_remove(struct spi_device *spi)
 	return 0;
 }
 
+static const struct of_device_id td028ttec1_of_match[] = {
+	{ .compatible = "omapdss,toppoly,td028ttec1", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, td028ttec1_of_match);
+
 static struct spi_driver td028ttec1_spi_driver = {
 	.probe		= td028ttec1_panel_probe,
 	.remove		= td028ttec1_panel_remove,
@@ -470,6 +499,7 @@ static struct spi_driver td028ttec1_spi_driver = {
 	.driver         = {
 		.name   = "panel-tpo-td028ttec1",
 		.owner  = THIS_MODULE,
+		.of_match_table = td028ttec1_of_match,
 	},
 };
 
-- 
1.9.1


^ permalink raw reply related

* [PATCH v3 2/3] ARM: dts: oma3-gta04: Add display support
From: Marek Belisko @ 2014-05-08 20:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1399580212-5183-1-git-send-email-marek@goldelico.com>

This patch add support for lcd display on gta04 board. Display control
is connected to spi (used spi bitbang driver).

Signed-off-by: Marek Belisko <marek@goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dts | 87 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts
index f8ad125..eb9ab1a 100644
--- a/arch/arm/boot/dts/omap3-gta04.dts
+++ b/arch/arm/boot/dts/omap3-gta04.dts
@@ -44,6 +44,36 @@
 		ti,mcbsp = <&mcbsp2>;
 		ti,codec = <&twl_audio>;
 	};
+
+	spi_lcd {
+		compatible = "spi-gpio";
+		#address-cells = <0x1>;
+		#size-cells = <0x0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi_gpio_pins>;
+
+		gpio-sck = <&gpio1 12 0>;
+		gpio-miso = <&gpio1 18 0>;
+		gpio-mosi = <&gpio1 20 0>;
+		cs-gpios = <&gpio1 19 0>;
+		num-chipselects = <1>;
+
+		/* lcd panel */
+		lcd: td028ttec1@0 {
+			compatible = "toppoly,td028ttec1";
+			reg = <0>;
+			spi-max-frequency = <100000>;
+			spi-cpol;
+			spi-cpha;
+
+			label = "lcd";
+			port {
+				lcd_in: endpoint {
+					remote-endpoint = <&dpi_out>;
+				};
+			};
+		};
+	};
 };
 
 &omap3_pmx_core {
@@ -78,6 +108,47 @@
 			0x11e (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat3.sdmmc1_dat3 */
 		>;
 	};
+
+	dss_dpi_pins: pinmux_dss_dpi_pins {
+               pinctrl-single,pins = <
+                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
+                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
+                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
+                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
+                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
+                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+               >;
+       };
+
+	spi_gpio_pins: spi_gpio_pinmux {
+		pinctrl-single,pins = <0x5a8 (PIN_OUTPUT | MUX_MODE4) /* clk */
+			0x5b6 (PIN_OUTPUT | MUX_MODE4) /* cs */
+			0x5b8 (PIN_OUTPUT | MUX_MODE4) /* tx */
+			0x5b4 (PIN_INPUT | MUX_MODE4) /* rx */
+		>;
+	};
 };
 
 &i2c1 {
@@ -219,3 +290,19 @@
 	regulator-min-microvolt = <2800000>;
 	regulator-max-microvolt = <3150000>;
 };
+
+&dss {
+	pinctrl-names = "default";
+	pinctrl-0 = < &dss_dpi_pins >;
+
+	status = "okay";
+
+	vdds_dsi-supply = <&vpll2>;
+
+	port {
+		dpi_out: endpoint {
+			remote-endpoint = <&lcd_in>;
+			data-lines = <24>;
+		};
+	};
+};
-- 
1.9.1


^ permalink raw reply related

* [PATCH v3 3/3] omapdss: panel-tpo-td028ec1: Add module alias
From: Marek Belisko @ 2014-05-08 20:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1399580212-5183-1-git-send-email-marek@goldelico.com>

Add module alias string to make it working when panel is compiled as module.
Without this change panel module is not probed thus display is not working.

Signed-off-by: Marek Belisko <marek@goldelico.com>
---
 drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
index 5b3466e..728808b 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
@@ -505,6 +505,7 @@ static struct spi_driver td028ttec1_spi_driver = {
 
 module_spi_driver(td028ttec1_spi_driver);
 
+MODULE_ALIAS("spi:toppoly,td028ttec1");
 MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
 MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver");
 MODULE_LICENSE("GPL");
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH 13/13] video: omap: allow building on !MMU
From: Tony Lindgren @ 2014-05-08 21:53 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Peter Griffin, Arnd Bergmann, linux-kernel, linaro-kernel,
	Jean-Christophe Plagniol-Villard, linux-fbdev, linux-omap,
	Aaro Koskinen, Janusz Krzysztofik
In-Reply-To: <5369F973.10803@ti.com>

* Tomi Valkeinen <tomi.valkeinen@ti.com> [140507 02:15]:
> On 24/04/14 15:28, Peter Griffin wrote:
> > From: Arnd Bergmann <arnd@arndb.de>
> > 
> > The omap lcdc driver has an elaborate mmap_kern function
> > to map the frame buffer into kernel address space as
> > write-combined. This uses functions that are only available
> > on MMU-enabled builds.
> > 
> > It does seem equivalent to ioremap_wc though, so we should
> > be able to just use that instead.
> > 
> > This patch is build-tested only, it needs to be run on real
> > hardware before applying.
> 
> I don't have omap1 boards, and I don't know anyone that has. I don't
> even know if the omap1 fb is working or not...
> 
> Tony, any idea of omap1's fb? Are you able to test this?

I have three omap1 boards in my rack that I use for my boot
testing. Tried to enable framebuffer but so far no luck on
any of them. So I'm not much of a help here. Looks like the
patch should work though..

Aaro & Janusz, care to take a look at the patch in this
thread?

Regards,

Tony

^ 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