LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 0/8] Cleanup and add support for SSD1305
@ 2015-02-06 22:28 niederp
  2015-02-06 22:28 ` [PATCH 1/8] Documentation: dts: add missing Solomon Systech vendor prefix niederp
                   ` (12 more replies)
  0 siblings, 13 replies; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patch series is the result of making the ssd1307fb driver work with
a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
this the intialization code for the SSD1306 and the SSD1307 is merged
and based on device tree configuration. This gets rid of the magic bit
values that were used so far.
Based on these changes it was straight forward to add support for the
SSD1305 controller.

While working with the driver I realized that it was not possible to
correctly mmap the video memory from userspace since the memory
reserved by kzalloc is not page aligned. This problem is fixed by
using vmalloc as it is done inthe vfb driver.

Furthermore module parameters are added to set the bits per pixel
and the delay for the deferred io update. It makes sense to set
the bits per pixel for the video memory to 8 bits since there is
only very poor userspace support for 1 bit framebuffers.

Also sysfs handles are added to make the contrast settings and dim
mode setting available in userspace.

Thomas Niederprüm (8):
  Documentation: dts: add missing Solomon Systech vendor prefix.
  fbdev: ssd1307fb: Unify init code and make controller configurable
    from device tree
  fbdev: ssd1307fb: Add support for SSD1305
  fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  fbdev: ssd1307fb: Add module parameter bitsperpixel.
  fbdev: ssd1307fb: Add module parameter to set update delay of the 
    deffered io.
  fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting
    to userspace.
  fbdev: ssd1307fb: Turn off display on driver unload.

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../devicetree/bindings/video/ssd1307fb.txt        |  13 +-
 drivers/video/fbdev/ssd1307fb.c                    | 426 ++++++++++++++++-----
 3 files changed, 346 insertions(+), 94 deletions(-)

-- 
2.1.1


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

* [PATCH 1/8] Documentation: dts: add missing Solomon Systech vendor prefix.
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-06 22:28 ` [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree niederp
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patch adds the solomon prefix for Solomon Systech Limited.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a344ec2..b1d9470 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -143,6 +143,7 @@ sitronix	Sitronix Technology Corporation
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
+solomon	Solomon Systech Limited
 sony	Sony Corporation
 spansion	Spansion Inc.
 st	STMicroelectronics
-- 
2.1.1


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

* [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
  2015-02-06 22:28 ` [PATCH 1/8] Documentation: dts: add missing Solomon Systech vendor prefix niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-07 10:42   ` Maxime Ripard
  2015-02-06 22:28 ` [PATCH 3/8] fbdev: ssd1307fb: Add support for SSD1305 niederp
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patches unifies the init code for the ssd130X chips and
adds device tree bindings to describe the hardware configuration
of the used controller. This gets rid of the magic bit values
used in the init code so far.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
 drivers/video/fbdev/ssd1307fb.c                    | 243 ++++++++++++++-------
 2 files changed, 174 insertions(+), 80 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 7a12542..1230f68 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -15,6 +15,17 @@ Required properties:
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
+  - solomon,segment-remap: Invert the order of data column to segment mapping
+  - solomon,offset: Map the display start line to one of COM0 - COM63
+  - solomon,contrast: Set initial contrast of the display
+  - solomon,prechargep1: Set the duration of the precharge period phase1
+  - solomon,prechargep2: Set the duration of the precharge period phase2
+  - solomon,com-alt: Enable/disable alternate COM pin configuration
+  - solomon,com-lrremap: Enable/disable left-right remap of COM pins
+  - solomon,com-invdir: Invert COM scan direction
+  - solomon,vcomh: Set VCOMH regulator voltage
+  - solomon,dclk-div: Set display clock divider
+  - solomon,dclk-frq: Set display clock frequency
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 3d6611f..4f435aa 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -16,6 +16,9 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1306 6
+#define DEVID_SSD1307 7
+
 #define SSD1307FB_DATA			0x40
 #define SSD1307FB_COMMAND		0x80
 
@@ -40,20 +43,33 @@
 
 struct ssd1307fb_par;
 
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
+struct ssd1307fb_deviceinfo {
+	int device_id;
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
 };
 
 struct ssd1307fb_par {
+	u32 com_alt;
+	u32 com_invdir;
+	u32 com_lrremap;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	struct ssd1307fb_deviceinfo *device_info;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
+	u32 offset;
 	u32 page_offset;
+	u32 prechargep1;
+	u32 prechargep2;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 seg_remap;
+	u32 vcomh;
 	u32 width;
 };
 
@@ -254,127 +270,151 @@ static struct fb_deferred_io ssd1307fb_defio = {
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
+	u32 precharge, dclk, com_invdir, compins;
 
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		par->pwm = pwm_get(&par->client->dev, NULL);
+		if (IS_ERR(par->pwm)) {
+			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+			return PTR_ERR(par->pwm);
+		}
 
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
+		par->pwm_period = pwm_get_period(par->pwm);
+		/* Enable the PWM */
+		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+		pwm_enable(par->pwm);
 
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
+		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+			par->pwm->pwm, par->pwm_period);
+	};
 
 	/* Set initial contrast */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
 	if (ret < 0)
 		return ret;
 
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
 	if (ret < 0)
 		return ret;
 
 	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (par->seg_remap) {
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	};
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
+	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
 	if (ret < 0)
 		return ret;
 
 	/* Set multiplex ratio value */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO);
-	ret = ret & ssd1307fb_write_cmd(par->client, par->height - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, par->height - 1);
 	if (ret < 0)
 		return ret;
 
 	/* set display offset value */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET);
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, par->offset);
 	if (ret < 0)
 		return ret;
 
 	/* Set clock frequency */
+	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
 	if (ret < 0)
 		return ret;
 
-	/* Set precharge period in number of ticks from the internal clock */
+	ret = ssd1307fb_write_cmd(par->client, dclk);
+	if (ret < 0)
+		return ret;
+
+	/* Set precharge period in number of ticks from the internal clock*/
+	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, precharge);
 	if (ret < 0)
 		return ret;
 
 	/* Set COM pins configuration */
+	compins = 0x02 | (par->com_alt & 0x1) << 4
+				   | (par->com_lrremap & 0x1) << 5;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, compins);
 	if (ret < 0)
 		return ret;
 
 	/* Set VCOMH */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
 	if (ret < 0)
 		return ret;
 
-	/* Turn on the DC-DC Charge Pump */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
+	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
 	if (ret < 0)
 		return ret;
 
+	if (par->device_info->device_id == DEVID_SSD1306) {
+		/* Turn on the DC-DC Charge Pump */
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+		if (ret < 0)
+			return ret;
+
+		ret = ssd1307fb_write_cmd(par->client, 0x14);
+		if (ret < 0)
+			return ret;
+	};
+
 	/* Switch to horizontal addressing mode */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
-	ret = ret & ssd1307fb_write_cmd(par->client,
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client,
 					SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
 	if (ret < 0)
 		return ret;
 
+    /* Set column range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
-	ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
 	if (ret < 0)
 		return ret;
 
+	ret = ssd1307fb_write_cmd(par->client, 0x0);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, par->width - 1);
+	if (ret < 0)
+		return ret;
+
+    /* Set page range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
-	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
-	ret = ret & ssd1307fb_write_cmd(par->client,
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, 0x0);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client,
 					par->page_offset + (par->height / 8) - 1);
 	if (ret < 0)
 		return ret;
@@ -387,18 +427,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
+	.device_id  = DEVID_SSD1306,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 8,
+};
+
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
+	.device_id  = DEVID_SSD1307,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 12,
 };
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
 		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
+		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
 	{
 		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
+		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
 	},
 	{},
 };
@@ -429,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->info = info;
 	par->client = client;
 
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
+	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
+			ssd1307fb_of_match, &client->dev)->data;
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
@@ -449,8 +499,40 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		par->page_offset = 1;
 
 	vmem_size = par->width * par->height / 8;
+	if (of_property_read_u32(node, "solomon,segment-remap", &par->seg_remap))
+		par->seg_remap = 0;
+
+	if (of_property_read_u32(node, "solomon,offset", &par->offset))
+		par->offset = 0;
+
+	if (of_property_read_u32(node, "solomon,contrast", &par->contrast))
+		par->contrast = 128;
+
+	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
+		par->prechargep1 = 2;
+
+	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
+		par->prechargep2 = 2;
+
+	if (of_property_read_u32(node, "solomon,com-alt", &par->com_alt))
+		par->com_alt = 1;
+
+	if (of_property_read_u32(node, "solomon,com-lrremap", &par->com_lrremap))
+		par->com_lrremap = 0;
+
+	if (of_property_read_u32(node, "solomon,com-invdir", &par->com_invdir))
+		par->com_invdir = 0;
+
+	if (of_property_read_u32(node, "solomon,vcomh", &par->vcomh))
+		par->vcomh = par->device_info->default_vcomh;
 
 	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	if (of_property_read_u32(node, "solomon,dclk-div", &par->dclk_div))
+		par->dclk_div = par->device_info->default_dclk_div;
+
+	if (of_property_read_u32(node, "solomon,dclk-frq", &par->dclk_frq))
+		par->dclk_frq  = par->device_info->default_dclk_frq;
+
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -499,11 +581,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	gpio_set_value(par->reset, 1);
 	udelay(4);
 
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
+	ret = ssd1307fb_init(par);
+	if (ret)
+		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
 	if (ret) {
@@ -516,8 +596,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	return 0;
 
 panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 fb_alloc_error:
@@ -531,11 +613,12 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 	fb_deferred_io_cleanup(info);
 	framebuffer_release(info);
-
 	return 0;
 }
 
-- 
2.1.1


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

* [PATCH 3/8] fbdev: ssd1307fb: Add support for SSD1305
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
  2015-02-06 22:28 ` [PATCH 1/8] Documentation: dts: add missing Solomon Systech vendor prefix niederp
  2015-02-06 22:28 ` [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-06 22:28 ` [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory niederp
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patch adds support for the SSD1305 OLED controller.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/video/ssd1307fb.txt |  2 +-
 drivers/video/fbdev/ssd1307fb.c                       | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 1230f68..51fa263 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -2,7 +2,7 @@
 
 Required properties:
   - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
-    now is i2c, and the supported chips are ssd1306 and ssd1307.
+    now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307.
   - reg: Should contain address of the controller on the I2C bus. Most likely
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 4f435aa..01cfb46 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -16,6 +16,7 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1305 5
 #define DEVID_SSD1306 6
 #define DEVID_SSD1307 7
 
@@ -427,6 +428,13 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
+	.device_id  = DEVID_SSD1305,
+	.default_vcomh = 0x34,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 7,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
 	.device_id  = DEVID_SSD1306,
 	.default_vcomh = 0x20,
@@ -443,6 +451,10 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1305_deviceinfo,
+	},
+	{
 		.compatible = "solomon,ssd1306fb-i2c",
 		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
@@ -623,6 +635,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1305fb", 0 },
 	{ "ssd1306fb", 0 },
 	{ "ssd1307fb", 0 },
 	{ }
-- 
2.1.1


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

* [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (2 preceding siblings ...)
  2015-02-06 22:28 ` [PATCH 3/8] fbdev: ssd1307fb: Add support for SSD1305 niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-07 11:18   ` Maxime Ripard
  2015-02-06 22:28 ` [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel niederp
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

It makes sense to use vmalloc to allocate the video buffer since it has to be page aligned memory for using it with
mmap. Also deffered io seems buggy in combination with kmalloc'ed memory (crash on unloading the module).

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 43 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 01cfb46..945ded9 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/fb.h>
 #include <linux/uaccess.h>
+#include <linux/vmalloc.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/pwm.h>
@@ -93,6 +94,43 @@ static struct fb_var_screeninfo ssd1307fb_var = {
 	.bits_per_pixel	= 1,
 };
 
+static void *rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		SetPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		ClearPageReserved(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+
 static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
 {
 	struct ssd1307fb_array *array;
@@ -538,13 +576,13 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,vcomh", &par->vcomh))
 		par->vcomh = par->device_info->default_vcomh;
 
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
 	if (of_property_read_u32(node, "solomon,dclk-div", &par->dclk_div))
 		par->dclk_div = par->device_info->default_dclk_div;
 
 	if (of_property_read_u32(node, "solomon,dclk-frq", &par->dclk_frq))
 		par->dclk_frq  = par->device_info->default_dclk_frq;
 
+	vmem = rvmalloc(vmem_size);
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -570,7 +608,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
 	fb_deferred_io_init(info);
@@ -614,6 +652,7 @@ panel_init_error:
 	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
+	rvfree(vmem, vmem_size);
 fb_alloc_error:
 	framebuffer_release(info);
 	return ret;
-- 
2.1.1


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

* [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (3 preceding siblings ...)
  2015-02-06 22:28 ` [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-07 11:20   ` Maxime Ripard
  2015-02-06 22:28 ` [PATCH 6/8] fbdev: ssd1307fb: Add module parameter to set update delay of the deffered io niederp
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patch adds a module parameter 'bitsperpixel' to adjust the colordepth
of the framebuffer. All values >1 will result in memory map of the requested
color depth. However only the MSB of each pixel will be sent to the device.
The framebuffer identifies itself as a grayscale display with the specified
depth.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 945ded9..1d81877 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -43,6 +43,11 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define BITSPERPIXEL 1
+
+static u_int bitsperpixel = BITSPERPIXEL;
+module_param(bitsperpixel, uint, 0);
+
 struct ssd1307fb_par;
 
 struct ssd1307fb_deviceinfo {
@@ -91,7 +96,8 @@ static struct fb_fix_screeninfo ssd1307fb_fix = {
 };
 
 static struct fb_var_screeninfo ssd1307fb_var = {
-	.bits_per_pixel	= 1,
+	.bits_per_pixel	= BITSPERPIXEL,
+	.grayscale = 1,
 };
 
 static void *rvmalloc(unsigned long size)
@@ -223,10 +229,11 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
 			array->data[array_idx] = 0;
 			for (k = 0; k < 8; k++) {
 				u32 page_length = par->width * i;
-				u32 index = page_length + (par->width * k + j) / 8;
+				u32 index = page_length * bitsperpixel + (par->width * k + j) * bitsperpixel / 8;
 				u8 byte = *(vmem + index);
-				u8 bit = byte & (1 << (j % 8));
-				bit = bit >> (j % 8);
+				u8 bit = byte & (((1 << (bitsperpixel))-1) << (j % 8/bitsperpixel));
+
+				bit = (bit >> (j % 8/bitsperpixel)) >> (bitsperpixel-1);
 				array->data[array_idx] |= bit << k;
 			}
 		}
@@ -548,7 +555,6 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
 		par->page_offset = 1;
 
-	vmem_size = par->width * par->height / 8;
 	if (of_property_read_u32(node, "solomon,segment-remap", &par->seg_remap))
 		par->seg_remap = 0;
 
@@ -582,6 +588,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,dclk-frq", &par->dclk_frq))
 		par->dclk_frq  = par->device_info->default_dclk_frq;
 
+	vmem_size = par->width * par->height * bitsperpixel / 8;
+
 	vmem = rvmalloc(vmem_size);
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
@@ -591,20 +599,21 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
-	info->fix.line_length = par->width / 8;
+	info->fix.line_length = par->width * bitsperpixel / 8;
 	info->fbdefio = &ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
+	info->var.bits_per_pixel = bitsperpixel;
 	info->var.xres = par->width;
 	info->var.xres_virtual = par->width;
 	info->var.yres = par->height;
 	info->var.yres_virtual = par->height;
 
-	info->var.red.length = 1;
+	info->var.red.length = bitsperpixel;
 	info->var.red.offset = 0;
-	info->var.green.length = 1;
+	info->var.green.length = bitsperpixel;
 	info->var.green.offset = 0;
-	info->var.blue.length = 1;
+	info->var.blue.length = bitsperpixel;
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-- 
2.1.1


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

* [PATCH 6/8]  fbdev: ssd1307fb: Add module parameter to set update delay of the  deffered io.
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (4 preceding siblings ...)
  2015-02-06 22:28 ` [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-07 11:26   ` Maxime Ripard
  2015-02-06 22:28 ` [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace niederp
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patch adds the module parameter "delaydivider" to set delay for the
deferred io. Effectively this is setting the refresh rate for mmap access
to the framebuffer. The delay for the deferred io is HZ/delaydivider.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 1d81877..b38315d 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -44,10 +44,14 @@
 #define	SSD1307FB_SET_VCOMH		0xdb
 
 #define BITSPERPIXEL 1
+#define DELAYDIVIDER 20
 
 static u_int bitsperpixel = BITSPERPIXEL;
 module_param(bitsperpixel, uint, 0);
 
+static u_int delaydivider = DELAYDIVIDER;
+module_param(delaydivider, uint, 0);
+
 struct ssd1307fb_par;
 
 struct ssd1307fb_deviceinfo {
@@ -312,7 +316,7 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 }
 
 static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
+	.delay		= HZ/DELAYDIVIDER,
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
@@ -601,6 +605,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->fix = ssd1307fb_fix;
 	info->fix.line_length = par->width * bitsperpixel / 8;
 	info->fbdefio = &ssd1307fb_defio;
+	info->fbdefio->delay = HZ/delaydivider;
 
 	info->var = ssd1307fb_var;
 	info->var.bits_per_pixel = bitsperpixel;
-- 
2.1.1


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

* [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (5 preceding siblings ...)
  2015-02-06 22:28 ` [PATCH 6/8] fbdev: ssd1307fb: Add module parameter to set update delay of the deffered io niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-07 11:43   ` Maxime Ripard
  2015-02-06 22:28 ` [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload niederp
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

This patch adds sysfs handles to enable userspace control over the display
contrast as well as the dim mode. The handles are available as "contrast"
and "dim" in the framebuffers sysfs domain.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 88 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 87 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index b38315d..02931c7 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -33,6 +33,7 @@
 #define SSD1307FB_CONTRAST		0x81
 #define	SSD1307FB_CHARGE_PUMP		0x8d
 #define SSD1307FB_SEG_REMAP_ON		0xa1
+#define SSD1307FB_DISPLAY_DIM		0xac
 #define SSD1307FB_DISPLAY_OFF		0xae
 #define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
 #define SSD1307FB_DISPLAY_ON		0xaf
@@ -43,6 +44,9 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define MIN_CONTRAST 0
+#define MAX_CONTRAST 255
+
 #define BITSPERPIXEL 1
 #define DELAYDIVIDER 20
 
@@ -69,6 +73,7 @@ struct ssd1307fb_par {
 	u32 dclk_div;
 	u32 dclk_frq;
 	struct ssd1307fb_deviceinfo *device_info;
+	u32 dim;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
@@ -515,6 +520,79 @@ static const struct of_device_id ssd1307fb_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 
+static ssize_t show_contrast(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->contrast);
+}
+
+static ssize_t store_contrast(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+	unsigned long contrastval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &contrastval);
+	if (ret < 0)
+		return ret;
+
+	par->contrast = max(min(contrastval,
+		(ulong)MAX_CONTRAST), (ulong)MIN_CONTRAST);
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->contrast);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+
+static ssize_t show_dim(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->dim);
+}
+
+static ssize_t store_dim(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+	unsigned long dimval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &dimval);
+	if (ret < 0)
+		return ret;
+
+	par->dim = max(min(dimval, (ulong)1), (ulong)0);
+	if (par->dim)
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_DIM);
+	else
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static struct device_attribute device_attrs[] = {
+	__ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast, store_contrast),
+	__ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim),
+
+};
+
 static int ssd1307fb_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
@@ -523,7 +601,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
-	int ret;
+	int ret, i;
 
 	if (!node) {
 		dev_err(&client->dev, "No device tree data found!\n");
@@ -650,6 +728,14 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
+
+	for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+		ret = device_create_file(info->dev, &device_attrs[i]);
+
+	if (ret) {
+		dev_err(&client->dev, "Couldn't register sysfs nodes\n");
+	}
+
 	if (ret) {
 		dev_err(&client->dev, "Couldn't register the framebuffer\n");
 		goto panel_init_error;
-- 
2.1.1


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

* [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (6 preceding siblings ...)
  2015-02-06 22:28 ` [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace niederp
@ 2015-02-06 22:28 ` niederp
  2015-02-07 11:45   ` Maxime Ripard
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 138+ messages in thread
From: niederp @ 2015-02-06 22:28 UTC (permalink / raw)
  To: linux-fbdev, plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-kernel, Thomas Niederprüm

From: Thomas Niederprüm <niederp@physik.uni-kl.de>

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 02931c7..be91dfc 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -762,6 +762,11 @@ static int ssd1307fb_remove(struct i2c_client *client)
 {
 	struct fb_info *info = i2c_get_clientdata(client);
 	struct ssd1307fb_par *par = info->par;
+	int ret = 0;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+	if (ret < 0)
+		return ret;
 
 	unregister_framebuffer(info);
 	if (par->device_info->device_id == DEVID_SSD1307) {
-- 
2.1.1


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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-06 22:28 ` [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree niederp
@ 2015-02-07 10:42   ` Maxime Ripard
  2015-02-07 14:59     ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-07 10:42 UTC (permalink / raw)
  To: niederp; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

Hi,

On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de wrote:
> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> This patches unifies the init code for the ssd130X chips and
> adds device tree bindings to describe the hardware configuration
> of the used controller. This gets rid of the magic bit values
> used in the init code so far.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
>  drivers/video/fbdev/ssd1307fb.c                    | 243 ++++++++++++++-------
>  2 files changed, 174 insertions(+), 80 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> index 7a12542..1230f68 100644
> --- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> @@ -15,6 +15,17 @@ Required properties:
>  
>  Optional properties:
>    - reset-active-low: Is the reset gpio is active on physical low?
> +  - solomon,segment-remap: Invert the order of data column to segment mapping
> +  - solomon,offset: Map the display start line to one of COM0 - COM63
> +  - solomon,contrast: Set initial contrast of the display
> +  - solomon,prechargep1: Set the duration of the precharge period phase1
> +  - solomon,prechargep2: Set the duration of the precharge period phase2
> +  - solomon,com-alt: Enable/disable alternate COM pin configuration
> +  - solomon,com-lrremap: Enable/disable left-right remap of COM pins
> +  - solomon,com-invdir: Invert COM scan direction
> +  - solomon,vcomh: Set VCOMH regulator voltage
> +  - solomon,dclk-div: Set display clock divider
> +  - solomon,dclk-frq: Set display clock frequency

I'm sorry, but this is the wrong approach, for at least two reasons:
you broke all existing users of that driver, which is a clear no-go,
and the DT itself should not contain any direct mapping of the
registers.


>  
>  [0]: Documentation/devicetree/bindings/pwm/pwm.txt
>  
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 3d6611f..4f435aa 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -16,6 +16,9 @@
>  #include <linux/pwm.h>
>  #include <linux/delay.h>
>  
> +#define DEVID_SSD1306 6
> +#define DEVID_SSD1307 7
> +
>  #define SSD1307FB_DATA			0x40
>  #define SSD1307FB_COMMAND		0x80
>  
> @@ -40,20 +43,33 @@
>  
>  struct ssd1307fb_par;
>  
> -struct ssd1307fb_ops {
> -	int (*init)(struct ssd1307fb_par *);
> -	int (*remove)(struct ssd1307fb_par *);
> +struct ssd1307fb_deviceinfo {
> +	int device_id;
> +	u32 default_vcomh;
> +	u32 default_dclk_div;
> +	u32 default_dclk_frq;
>  };
>  
>  struct ssd1307fb_par {
> +	u32 com_alt;
> +	u32 com_invdir;
> +	u32 com_lrremap;
> +	u32 contrast;
> +	u32 dclk_div;
> +	u32 dclk_frq;
> +	struct ssd1307fb_deviceinfo *device_info;
>  	struct i2c_client *client;
>  	u32 height;
>  	struct fb_info *info;
> -	struct ssd1307fb_ops *ops;
> +	u32 offset;
>  	u32 page_offset;
> +	u32 prechargep1;
> +	u32 prechargep2;
>  	struct pwm_device *pwm;
>  	u32 pwm_period;
>  	int reset;
> +	u32 seg_remap;
> +	u32 vcomh;
>  	u32 width;
>  };
>  
> @@ -254,127 +270,151 @@ static struct fb_deferred_io ssd1307fb_defio = {
>  	.deferred_io	= ssd1307fb_deferred_io,
>  };
>  
> -static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
> +static int ssd1307fb_init(struct ssd1307fb_par *par)
>  {
>  	int ret;
> +	u32 precharge, dclk, com_invdir, compins;
>  
> -	par->pwm = pwm_get(&par->client->dev, NULL);
> -	if (IS_ERR(par->pwm)) {
> -		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
> -		return PTR_ERR(par->pwm);
> -	}
> -
> -	par->pwm_period = pwm_get_period(par->pwm);
> -	/* Enable the PWM */
> -	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> -	pwm_enable(par->pwm);
> -
> -	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
> -		par->pwm->pwm, par->pwm_period);
> -
> -	/* Map column 127 of the OLED to segment 0 */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Turn on the display */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
> -	if (ret < 0)
> -		return ret;
> -
> -	return 0;
> -}
> -
> -static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
> -{
> -	pwm_disable(par->pwm);
> -	pwm_put(par->pwm);
> -	return 0;
> -}
> +	if (par->device_info->device_id == DEVID_SSD1307) {
> +		par->pwm = pwm_get(&par->client->dev, NULL);
> +		if (IS_ERR(par->pwm)) {
> +			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
> +			return PTR_ERR(par->pwm);
> +		}
>  
> -static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
> -	.init	= ssd1307fb_ssd1307_init,
> -	.remove	= ssd1307fb_ssd1307_remove,
> -};
> +		par->pwm_period = pwm_get_period(par->pwm);
> +		/* Enable the PWM */
> +		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> +		pwm_enable(par->pwm);
>  
> -static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
> -{
> -	int ret;
> +		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
> +			par->pwm->pwm, par->pwm_period);
> +	};
>  
>  	/* Set initial contrast */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Set COM direction */
> -	ret = ssd1307fb_write_cmd(par->client, 0xc8);
> +	ret = ssd1307fb_write_cmd(par->client, par->contrast);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set segment re-map */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> +	if (par->seg_remap) {
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> +		if (ret < 0)
> +			return ret;
> +	};
> +
> +	/* Set COM direction */
> +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set multiplex ratio value */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO);
> -	ret = ret & ssd1307fb_write_cmd(par->client, par->height - 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client, par->height - 1);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* set display offset value */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET);
> -	ret = ssd1307fb_write_cmd(par->client, 0x20);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client, par->offset);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set clock frequency */
> +	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Set precharge period in number of ticks from the internal clock */
> +	ret = ssd1307fb_write_cmd(par->client, dclk);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Set precharge period in number of ticks from the internal clock*/
> +	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client, precharge);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set COM pins configuration */
> +	compins = 0x02 | (par->com_alt & 0x1) << 4
> +				   | (par->com_lrremap & 0x1) << 5;
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client, compins);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set VCOMH */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Turn on the DC-DC Charge Pump */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
> +	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
>  	if (ret < 0)
>  		return ret;
>  
> +	if (par->device_info->device_id == DEVID_SSD1306) {
> +		/* Turn on the DC-DC Charge Pump */
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
> +		if (ret < 0)
> +			return ret;
> +
> +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> +		if (ret < 0)
> +			return ret;
> +	};
> +
>  	/* Switch to horizontal addressing mode */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
> -	ret = ret & ssd1307fb_write_cmd(par->client,
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client,
>  					SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
>  	if (ret < 0)
>  		return ret;
>  
> +    /* Set column range */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
> -	ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
>  	if (ret < 0)
>  		return ret;
>  
> +	ret = ssd1307fb_write_cmd(par->client, 0x0);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client, par->width - 1);
> +	if (ret < 0)
> +		return ret;
> +
> +    /* Set page range */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
> -	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
> -	ret = ret & ssd1307fb_write_cmd(par->client,
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client, 0x0);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = ssd1307fb_write_cmd(par->client,
>  					par->page_offset + (par->height / 8) - 1);
>  	if (ret < 0)
>  		return ret;
> @@ -387,18 +427,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	return 0;
>  }
>  
> -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> -	.init	= ssd1307fb_ssd1306_init,
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> +	.device_id  = DEVID_SSD1306,
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 0,
> +	.default_dclk_frq = 8,
> +};
> +
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> +	.device_id  = DEVID_SSD1307,
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 1,
> +	.default_dclk_frq = 12,
>  };
>  
>  static const struct of_device_id ssd1307fb_of_match[] = {
>  	{
>  		.compatible = "solomon,ssd1306fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1306_ops,
> +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
>  	},
>  	{
>  		.compatible = "solomon,ssd1307fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1307_ops,
> +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
>  	},
>  	{},
>  };
> @@ -429,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	par->info = info;
>  	par->client = client;
>  
> -	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
> -							   &client->dev)->data;
> +	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
> +			ssd1307fb_of_match, &client->dev)->data;
>  
>  	par->reset = of_get_named_gpio(client->dev.of_node,
>  					 "reset-gpios", 0);
> @@ -449,8 +499,40 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  		par->page_offset = 1;
>  
>  	vmem_size = par->width * par->height / 8;
> +	if (of_property_read_u32(node, "solomon,segment-remap", &par->seg_remap))
> +		par->seg_remap = 0;
> +
> +	if (of_property_read_u32(node, "solomon,offset", &par->offset))
> +		par->offset = 0;
> +
> +	if (of_property_read_u32(node, "solomon,contrast", &par->contrast))
> +		par->contrast = 128;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
> +		par->prechargep1 = 2;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
> +		par->prechargep2 = 2;
> +
> +	if (of_property_read_u32(node, "solomon,com-alt", &par->com_alt))
> +		par->com_alt = 1;
> +
> +	if (of_property_read_u32(node, "solomon,com-lrremap", &par->com_lrremap))
> +		par->com_lrremap = 0;
> +
> +	if (of_property_read_u32(node, "solomon,com-invdir", &par->com_invdir))
> +		par->com_invdir = 0;
> +
> +	if (of_property_read_u32(node, "solomon,vcomh", &par->vcomh))
> +		par->vcomh = par->device_info->default_vcomh;
>  
>  	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
> +	if (of_property_read_u32(node, "solomon,dclk-div", &par->dclk_div))
> +		par->dclk_div = par->device_info->default_dclk_div;
> +
> +	if (of_property_read_u32(node, "solomon,dclk-frq", &par->dclk_frq))
> +		par->dclk_frq  = par->device_info->default_dclk_frq;
> +
>  	if (!vmem) {
>  		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
>  		ret = -ENOMEM;
> @@ -499,11 +581,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	gpio_set_value(par->reset, 1);
>  	udelay(4);
>  
> -	if (par->ops->init) {
> -		ret = par->ops->init(par);
> -		if (ret)
> -			goto reset_oled_error;
> -	}
> +	ret = ssd1307fb_init(par);
> +	if (ret)
> +		goto reset_oled_error;
>  
>  	ret = register_framebuffer(info);
>  	if (ret) {
> @@ -516,8 +596,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	return 0;
>  
>  panel_init_error:
> -	if (par->ops->remove)
> -		par->ops->remove(par);
> +	if (par->device_info->device_id == DEVID_SSD1307) {
> +		pwm_disable(par->pwm);
> +		pwm_put(par->pwm);
> +	};
>  reset_oled_error:
>  	fb_deferred_io_cleanup(info);
>  fb_alloc_error:
> @@ -531,11 +613,12 @@ static int ssd1307fb_remove(struct i2c_client *client)
>  	struct ssd1307fb_par *par = info->par;
>  
>  	unregister_framebuffer(info);
> -	if (par->ops->remove)
> -		par->ops->remove(par);
> +	if (par->device_info->device_id == DEVID_SSD1307) {
> +		pwm_disable(par->pwm);
> +		pwm_put(par->pwm);
> +	};
>  	fb_deferred_io_cleanup(info);
>  	framebuffer_release(info);
> -
>  	return 0;
>  }
>  
> -- 
> 2.1.1
> 

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-06 22:28 ` [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory niederp
@ 2015-02-07 11:18   ` Maxime Ripard
  2015-02-07 15:35     ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-07 11:18 UTC (permalink / raw)
  To: niederp; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

Hi,

On Fri, Feb 06, 2015 at 11:28:10PM +0100, niederp@physik.uni-kl.de wrote:
> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> It makes sense to use vmalloc to allocate the video buffer since it
> has to be page aligned memory for using it with mmap.

Please wrap your commit log at 80 chars.

It looks like there's numerous fbdev drivers using this (especially
since you copy pasted that code, without mentionning it).

That should be turned into an allocator so that drivers all get this
right.

> Also deffered io seems buggy in combination with kmalloc'ed memory
> (crash on unloading the module).

And maybe that's the real issue to fix.

> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 43 +++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 41 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 01cfb46..945ded9 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -11,6 +11,7 @@
>  #include <linux/i2c.h>
>  #include <linux/fb.h>
>  #include <linux/uaccess.h>
> +#include <linux/vmalloc.h>
>  #include <linux/of_device.h>
>  #include <linux/of_gpio.h>
>  #include <linux/pwm.h>
> @@ -93,6 +94,43 @@ static struct fb_var_screeninfo ssd1307fb_var = {
>  	.bits_per_pixel	= 1,
>  };
>  
> +static void *rvmalloc(unsigned long size)
> +{
> +	void *mem;
> +	unsigned long adr;
> +
> +	size = PAGE_ALIGN(size);

Isn't vmalloc already taking care of that?

> +	mem = vmalloc_32(size);

Why the 32 bits variant?

> +	if (!mem)
> +		return NULL;
> +
> +	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
> +	adr = (unsigned long) mem;
> +	while (size > 0) {
> +		SetPageReserved(vmalloc_to_page((void *)adr));

I'm not really sure it makes sense to mark all pages reserved if we're
not even sure we're going to use mmap.

And why do you need to mark these pages reserved in the first place?

> +		adr += PAGE_SIZE;
> +		size -= PAGE_SIZE;
> +	}
> +
> +	return mem;
> +}
> +
> +static void rvfree(void *mem, unsigned long size)
> +{
> +	unsigned long adr;
> +
> +	if (!mem)
> +		return;
> +
> +	adr = (unsigned long) mem;
> +	while ((long) size > 0) {
> +		ClearPageReserved(vmalloc_to_page((void *)adr));
> +		adr += PAGE_SIZE;
> +		size -= PAGE_SIZE;
> +	}
> +	vfree(mem);
> +}
> +
>  static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
>  {
>  	struct ssd1307fb_array *array;
> @@ -538,13 +576,13 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	if (of_property_read_u32(node, "solomon,vcomh", &par->vcomh))
>  		par->vcomh = par->device_info->default_vcomh;
>  
> -	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
>  	if (of_property_read_u32(node, "solomon,dclk-div", &par->dclk_div))
>  		par->dclk_div = par->device_info->default_dclk_div;
>  
>  	if (of_property_read_u32(node, "solomon,dclk-frq", &par->dclk_frq))
>  		par->dclk_frq  = par->device_info->default_dclk_frq;
>  
> +	vmem = rvmalloc(vmem_size);
>  	if (!vmem) {
>  		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
>  		ret = -ENOMEM;
> @@ -570,7 +608,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	info->var.blue.offset = 0;
>  
>  	info->screen_base = (u8 __force __iomem *)vmem;
> -	info->fix.smem_start = (unsigned long)vmem;
> +	info->fix.smem_start = __pa(vmem);

Why are you changing from virtual to physical address here?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-02-06 22:28 ` [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel niederp
@ 2015-02-07 11:20   ` Maxime Ripard
  2015-02-07 16:05     ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-07 11:20 UTC (permalink / raw)
  To: niederp; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de wrote:
> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> This patch adds a module parameter 'bitsperpixel' to adjust the colordepth
> of the framebuffer. All values >1 will result in memory map of the requested
> color depth. However only the MSB of each pixel will be sent to the device.
> The framebuffer identifies itself as a grayscale display with the specified
> depth.

I'm not sure this is the right thing to do.

The bits per pixel for this display is rightfully defined, used and
reported to the userspace, why would you want to change that?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 6/8]  fbdev: ssd1307fb: Add module parameter to set update delay of the  deffered io.
  2015-02-06 22:28 ` [PATCH 6/8] fbdev: ssd1307fb: Add module parameter to set update delay of the deffered io niederp
@ 2015-02-07 11:26   ` Maxime Ripard
  2015-02-07 16:12     ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-07 11:26 UTC (permalink / raw)
  To: niederp; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Fri, Feb 06, 2015 at 11:28:12PM +0100, niederp@physik.uni-kl.de wrote:
> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> This patch adds the module parameter "delaydivider" to set delay for the
> deferred io. Effectively this is setting the refresh rate for mmap access
> to the framebuffer. The delay for the deferred io is HZ/delaydivider.

So this is actually a refresh rate?

Maybe you could expose it as such, and pass a frequency in Hz as an
argument.

Exposing the divider directly has some issues, since the bootloader
that set the parameter won't know the HZ value, you'll end up with
different rates for different configurations, without any way to do
something about it.

> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 1d81877..b38315d 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -44,10 +44,14 @@
>  #define	SSD1307FB_SET_VCOMH		0xdb
>  
>  #define BITSPERPIXEL 1
> +#define DELAYDIVIDER 20
>  
>  static u_int bitsperpixel = BITSPERPIXEL;
>  module_param(bitsperpixel, uint, 0);
>  
> +static u_int delaydivider = DELAYDIVIDER;
> +module_param(delaydivider, uint, 0);
> +

You're breaking the existing behaviour.

>  struct ssd1307fb_par;
>  
>  struct ssd1307fb_deviceinfo {
> @@ -312,7 +316,7 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
>  }
>  
>  static struct fb_deferred_io ssd1307fb_defio = {
> -	.delay		= HZ,
> +	.delay		= HZ/DELAYDIVIDER,
>  	.deferred_io	= ssd1307fb_deferred_io,
>  };
>  
> @@ -601,6 +605,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	info->fix = ssd1307fb_fix;
>  	info->fix.line_length = par->width * bitsperpixel / 8;
>  	info->fbdefio = &ssd1307fb_defio;
> +	info->fbdefio->delay = HZ/delaydivider;

That won't work with multiple instances of the same driver
unfortunately.

>  
>  	info->var = ssd1307fb_var;
>  	info->var.bits_per_pixel = bitsperpixel;
> -- 
> 2.1.1
> 

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-02-06 22:28 ` [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace niederp
@ 2015-02-07 11:43   ` Maxime Ripard
  2015-02-07 16:42     ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-07 11:43 UTC (permalink / raw)
  To: niederp; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Fri, Feb 06, 2015 at 11:28:13PM +0100, niederp@physik.uni-kl.de wrote:
> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> This patch adds sysfs handles to enable userspace control over the display
> contrast as well as the dim mode. The handles are available as "contrast"
> and "dim" in the framebuffers sysfs domain.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 88 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 87 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index b38315d..02931c7 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -33,6 +33,7 @@
>  #define SSD1307FB_CONTRAST		0x81
>  #define	SSD1307FB_CHARGE_PUMP		0x8d
>  #define SSD1307FB_SEG_REMAP_ON		0xa1
> +#define SSD1307FB_DISPLAY_DIM		0xac
>  #define SSD1307FB_DISPLAY_OFF		0xae
>  #define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
>  #define SSD1307FB_DISPLAY_ON		0xaf
> @@ -43,6 +44,9 @@
>  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
>  #define	SSD1307FB_SET_VCOMH		0xdb
>  
> +#define MIN_CONTRAST 0
> +#define MAX_CONTRAST 255
> +
>  #define BITSPERPIXEL 1
>  #define DELAYDIVIDER 20
>  
> @@ -69,6 +73,7 @@ struct ssd1307fb_par {
>  	u32 dclk_div;
>  	u32 dclk_frq;
>  	struct ssd1307fb_deviceinfo *device_info;
> +	u32 dim;
>  	struct i2c_client *client;
>  	u32 height;
>  	struct fb_info *info;
> @@ -515,6 +520,79 @@ static const struct of_device_id ssd1307fb_of_match[] = {
>  };
>  MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
>  
> +static ssize_t show_contrast(struct device *device,
> +			   struct device_attribute *attr, char *buf)
> +{
> +	struct fb_info *info = dev_get_drvdata(device);
> +	struct ssd1307fb_par *par = info->par;
> +
> +	return snprintf(buf, PAGE_SIZE, "%d\n", par->contrast);
> +}
> +
> +static ssize_t store_contrast(struct device *device,
> +			    struct device_attribute *attr,
> +			    const char *buf, size_t count)
> +{
> +	struct fb_info *info = dev_get_drvdata(device);
> +	struct ssd1307fb_par *par = info->par;
> +	unsigned long contrastval;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &contrastval);
> +	if (ret < 0)
> +		return ret;
> +
> +	par->contrast = max(min(contrastval,
> +		(ulong)MAX_CONTRAST), (ulong)MIN_CONTRAST);
> +
> +	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
> +	ret = ret & ssd1307fb_write_cmd(par->client, par->contrast);
> +	if (ret < 0)
> +		return ret;
> +
> +	return count;
> +}
> +
> +
> +static ssize_t show_dim(struct device *device,
> +			   struct device_attribute *attr, char *buf)
> +{
> +	struct fb_info *info = dev_get_drvdata(device);
> +	struct ssd1307fb_par *par = info->par;
> +
> +	return snprintf(buf, PAGE_SIZE, "%d\n", par->dim);
> +}
> +
> +static ssize_t store_dim(struct device *device,
> +			    struct device_attribute *attr,
> +			    const char *buf, size_t count)
> +{
> +	struct fb_info *info = dev_get_drvdata(device);
> +	struct ssd1307fb_par *par = info->par;
> +	unsigned long dimval;
> +	int ret;
> +
> +	ret = kstrtoul(buf, 0, &dimval);
> +	if (ret < 0)
> +		return ret;
> +
> +	par->dim = max(min(dimval, (ulong)1), (ulong)0);
> +	if (par->dim)
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_DIM);
> +	else
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
> +	if (ret < 0)
> +		return ret;
> +
> +	return count;
> +}
> +
> +static struct device_attribute device_attrs[] = {
> +	__ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast, store_contrast),
> +	__ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim),
> +
> +};
> +

I would have thought this was something accessible through the
framebuffer ioctl.

Apparently it's not, at least for the contrast, so maybe it should be
added there, instead of doing it for a single driver?

(oh, and btw, every sysfs file should be documented in
Documentation/ABI)

>  static int ssd1307fb_probe(struct i2c_client *client,
>  			   const struct i2c_device_id *id)
>  {
> @@ -523,7 +601,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	u32 vmem_size;
>  	struct ssd1307fb_par *par;
>  	u8 *vmem;
> -	int ret;
> +	int ret, i;
>  
>  	if (!node) {
>  		dev_err(&client->dev, "No device tree data found!\n");
> @@ -650,6 +728,14 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  		goto reset_oled_error;
>  
>  	ret = register_framebuffer(info);
> +
> +	for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
> +		ret = device_create_file(info->dev, &device_attrs[i]);
> +
> +	if (ret) {
> +		dev_err(&client->dev, "Couldn't register sysfs nodes\n");
> +	}
> +

sysfs_create_groups does pretty much that already.

And don't forget to remove these files in the .remove()

>  	if (ret) {
>  		dev_err(&client->dev, "Couldn't register the framebuffer\n");
>  		goto panel_init_error;
> -- 
> 2.1.1
> 

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-02-06 22:28 ` [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload niederp
@ 2015-02-07 11:45   ` Maxime Ripard
  2015-02-07 16:49     ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-07 11:45 UTC (permalink / raw)
  To: niederp; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Fri, Feb 06, 2015 at 11:28:14PM +0100, niederp@physik.uni-kl.de wrote:
> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 

A commit log is always nice :)

> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 02931c7..be91dfc 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -762,6 +762,11 @@ static int ssd1307fb_remove(struct i2c_client *client)
>  {
>  	struct fb_info *info = i2c_get_clientdata(client);
>  	struct ssd1307fb_par *par = info->par;
> +	int ret = 0;
> +
> +	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
> +	if (ret < 0)
> +		return ret;

I don't think we really care about the return value here.

It might be even worse actually, since you'll end up in a intermediate
state, where you won't have freed everything, but your remove method
has been called still.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-07 10:42   ` Maxime Ripard
@ 2015-02-07 14:59     ` Thomas Niederprüm
  2015-02-07 15:19       ` Noralf Trønnes
  2015-02-12 16:41       ` Maxime Ripard
  0 siblings, 2 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-07 14:59 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Sat, 7 Feb 2015 11:42:25 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> Hi,
> 
> On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de
> wrote:
> > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > 
> > This patches unifies the init code for the ssd130X chips and
> > adds device tree bindings to describe the hardware configuration
> > of the used controller. This gets rid of the magic bit values
> > used in the init code so far.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
> >  drivers/video/fbdev/ssd1307fb.c                    | 243
> > ++++++++++++++------- 2 files changed, 174 insertions(+), 80
> > deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > 7a12542..1230f68 100644 ---
> > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
> > +15,17 @@ Required properties: 
> >  Optional properties:
> >    - reset-active-low: Is the reset gpio is active on physical low?
> > +  - solomon,segment-remap: Invert the order of data column to
> > segment mapping
> > +  - solomon,offset: Map the display start line to one of COM0 -
> > COM63
> > +  - solomon,contrast: Set initial contrast of the display
> > +  - solomon,prechargep1: Set the duration of the precharge period
> > phase1
> > +  - solomon,prechargep2: Set the duration of the precharge period
> > phase2
> > +  - solomon,com-alt: Enable/disable alternate COM pin configuration
> > +  - solomon,com-lrremap: Enable/disable left-right remap of COM
> > pins
> > +  - solomon,com-invdir: Invert COM scan direction
> > +  - solomon,vcomh: Set VCOMH regulator voltage
> > +  - solomon,dclk-div: Set display clock divider
> > +  - solomon,dclk-frq: Set display clock frequency
> 
> I'm sorry, but this is the wrong approach, for at least two reasons:
> you broke all existing users of that driver, which is a clear no-go,

Unfortunately this is true. The problem is that the SSD130X controllers
allow for a very versatile wiring of the display to the controller.
It's over to the manufacturer of the OLED module (disp+controller) to
decide how it's actually wired and during device initialization the
driver has to take care to configure the SSD130X controller according
to that wiring. If the driver fails to do so you will end up having
your display showing garbage. Unfortunately the current sate of the
initialization code of the ssd1307fb driver is not very flexible in that
respect. Taking a look at the initialization code for the ssd1306 shows
that it was written with one very special display module in mind. Most
of the magic bit values set there are non-default values according to
the datasheet. The result is that the driver works with that one
particular display module but many other (differently wired) display
modules using a ssd1306 controller won't work without changing the
hardcoded magic bit values.

My idea here was to set all configuration to the default values (as
given in the datasheet) unless it is overwritten by DT. Of course,
without a change in DT, this breaks the driver for all existing users.
The only alternative would be to set the current values as default.
Somehow this feels wrong to me as these values look arbitrary when you
don't know what exact display module they were set for. But if you
insist, I will change the default values.

> and the DT itself should not contain any direct mapping of the
> registers.
> 

I think I don't get what you mean here. Is it because I do no sanity
checks of the numbers set in DT? I was just looking for a way to hand
over the information about the wiring of display to the driver. How
would you propose to solve this?

> 
> >  
> >  [0]: Documentation/devicetree/bindings/pwm/pwm.txt
> >  
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 3d6611f..4f435aa 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -16,6 +16,9 @@
> >  #include <linux/pwm.h>
> >  #include <linux/delay.h>
> >  
> > +#define DEVID_SSD1306 6
> > +#define DEVID_SSD1307 7
> > +
> >  #define SSD1307FB_DATA			0x40
> >  #define SSD1307FB_COMMAND		0x80
> >  
> > @@ -40,20 +43,33 @@
> >  
> >  struct ssd1307fb_par;
> >  
> > -struct ssd1307fb_ops {
> > -	int (*init)(struct ssd1307fb_par *);
> > -	int (*remove)(struct ssd1307fb_par *);
> > +struct ssd1307fb_deviceinfo {
> > +	int device_id;
> > +	u32 default_vcomh;
> > +	u32 default_dclk_div;
> > +	u32 default_dclk_frq;
> >  };
> >  
> >  struct ssd1307fb_par {
> > +	u32 com_alt;
> > +	u32 com_invdir;
> > +	u32 com_lrremap;
> > +	u32 contrast;
> > +	u32 dclk_div;
> > +	u32 dclk_frq;
> > +	struct ssd1307fb_deviceinfo *device_info;
> >  	struct i2c_client *client;
> >  	u32 height;
> >  	struct fb_info *info;
> > -	struct ssd1307fb_ops *ops;
> > +	u32 offset;
> >  	u32 page_offset;
> > +	u32 prechargep1;
> > +	u32 prechargep2;
> >  	struct pwm_device *pwm;
> >  	u32 pwm_period;
> >  	int reset;
> > +	u32 seg_remap;
> > +	u32 vcomh;
> >  	u32 width;
> >  };
> >  
> > @@ -254,127 +270,151 @@ static struct fb_deferred_io
> > ssd1307fb_defio = { .deferred_io	= ssd1307fb_deferred_io,
> >  };
> >  
> > -static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
> > +static int ssd1307fb_init(struct ssd1307fb_par *par)
> >  {
> >  	int ret;
> > +	u32 precharge, dclk, com_invdir, compins;
> >  
> > -	par->pwm = pwm_get(&par->client->dev, NULL);
> > -	if (IS_ERR(par->pwm)) {
> > -		dev_err(&par->client->dev, "Could not get PWM from
> > device tree!\n");
> > -		return PTR_ERR(par->pwm);
> > -	}
> > -
> > -	par->pwm_period = pwm_get_period(par->pwm);
> > -	/* Enable the PWM */
> > -	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> > -	pwm_enable(par->pwm);
> > -
> > -	dev_dbg(&par->client->dev, "Using PWM%d with a %dns
> > period.\n",
> > -		par->pwm->pwm, par->pwm_period);
> > -
> > -	/* Map column 127 of the OLED to segment 0 */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	/* Turn on the display */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_ON);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	return 0;
> > -}
> > -
> > -static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
> > -{
> > -	pwm_disable(par->pwm);
> > -	pwm_put(par->pwm);
> > -	return 0;
> > -}
> > +	if (par->device_info->device_id == DEVID_SSD1307) {
> > +		par->pwm = pwm_get(&par->client->dev, NULL);
> > +		if (IS_ERR(par->pwm)) {
> > +			dev_err(&par->client->dev, "Could not get
> > PWM from device tree!\n");
> > +			return PTR_ERR(par->pwm);
> > +		}
> >  
> > -static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
> > -	.init	= ssd1307fb_ssd1307_init,
> > -	.remove	= ssd1307fb_ssd1307_remove,
> > -};
> > +		par->pwm_period = pwm_get_period(par->pwm);
> > +		/* Enable the PWM */
> > +		pwm_config(par->pwm, par->pwm_period / 2,
> > par->pwm_period);
> > +		pwm_enable(par->pwm);
> >  
> > -static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
> > -{
> > -	int ret;
> > +		dev_dbg(&par->client->dev, "Using PWM%d with a
> > %dns period.\n",
> > +			par->pwm->pwm, par->pwm_period);
> > +	};
> >  
> >  	/* Set initial contrast */
> >  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	/* Set COM direction */
> > -	ret = ssd1307fb_write_cmd(par->client, 0xc8);
> > +	ret = ssd1307fb_write_cmd(par->client, par->contrast);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set segment re-map */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > +	if (par->seg_remap) {
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> > +
> > +	/* Set COM direction */
> > +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> > +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set multiplex ratio value */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_MULTIPLEX_RATIO);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, par->height -
> > 1);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, par->height - 1);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* set display offset value */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_DISPLAY_OFFSET);
> > -	ret = ssd1307fb_write_cmd(par->client, 0x20);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, par->offset);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set clock frequency */
> > +	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_CLOCK_FREQ);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	/* Set precharge period in number of ticks from the
> > internal clock */
> > +	ret = ssd1307fb_write_cmd(par->client, dclk);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	/* Set precharge period in number of ticks from the
> > internal clock*/
> > +	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 &
> > 0xf) << 4; ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_PRECHARGE_PERIOD);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, precharge);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set COM pins configuration */
> > +	compins = 0x02 | (par->com_alt & 0x1) << 4
> > +				   | (par->com_lrremap & 0x1) << 5;
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_COM_PINS_CONFIG);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, compins);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set VCOMH */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_VCOMH);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	/* Turn on the DC-DC Charge Pump */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_CHARGE_PUMP);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
> > +	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > +	if (par->device_info->device_id == DEVID_SSD1306) {
> > +		/* Turn on the DC-DC Charge Pump */
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_CHARGE_PUMP);
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> > +
> >  	/* Switch to horizontal addressing mode */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_ADDRESS_MODE);
> > -	ret = ret & ssd1307fb_write_cmd(par->client,
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client,
> >  					SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > +    /* Set column range */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_COL_RANGE);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, par->width -
> > 1); if (ret < 0)
> >  		return ret;
> >  
> > +	ret = ssd1307fb_write_cmd(par->client, 0x0);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, par->width - 1);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +    /* Set page range */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_PAGE_RANGE);
> > -	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
> > -	ret = ret & ssd1307fb_write_cmd(par->client,
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, 0x0);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client,
> >  					par->page_offset +
> > (par->height / 8) - 1); if (ret < 0)
> >  		return ret;
> > @@ -387,18 +427,28 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) return 0;
> >  }
> >  
> > -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> > -	.init	= ssd1307fb_ssd1306_init,
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> > +	.device_id  = DEVID_SSD1306,
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 0,
> > +	.default_dclk_frq = 8,
> > +};
> > +
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> > +	.device_id  = DEVID_SSD1307,
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 1,
> > +	.default_dclk_frq = 12,
> >  };
> >  
> >  static const struct of_device_id ssd1307fb_of_match[] = {
> >  	{
> >  		.compatible = "solomon,ssd1306fb-i2c",
> > -		.data = (void *)&ssd1307fb_ssd1306_ops,
> > +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
> >  	},
> >  	{
> >  		.compatible = "solomon,ssd1307fb-i2c",
> > -		.data = (void *)&ssd1307fb_ssd1307_ops,
> > +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
> >  	},
> >  	{},
> >  };
> > @@ -429,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, par->info = info;
> >  	par->client = client;
> >  
> > -	par->ops = (struct ssd1307fb_ops
> > *)of_match_device(ssd1307fb_of_match,
> > -
> > &client->dev)->data;
> > +	par->device_info = (struct ssd1307fb_deviceinfo
> > *)of_match_device(
> > +			ssd1307fb_of_match, &client->dev)->data;
> >  
> >  	par->reset = of_get_named_gpio(client->dev.of_node,
> >  					 "reset-gpios", 0);
> > @@ -449,8 +499,40 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, par->page_offset = 1;
> >  
> >  	vmem_size = par->width * par->height / 8;
> > +	if (of_property_read_u32(node, "solomon,segment-remap",
> > &par->seg_remap))
> > +		par->seg_remap = 0;
> > +
> > +	if (of_property_read_u32(node, "solomon,offset",
> > &par->offset))
> > +		par->offset = 0;
> > +
> > +	if (of_property_read_u32(node, "solomon,contrast",
> > &par->contrast))
> > +		par->contrast = 128;
> > +
> > +	if (of_property_read_u32(node, "solomon,prechargep1",
> > &par->prechargep1))
> > +		par->prechargep1 = 2;
> > +
> > +	if (of_property_read_u32(node, "solomon,prechargep2",
> > &par->prechargep2))
> > +		par->prechargep2 = 2;
> > +
> > +	if (of_property_read_u32(node, "solomon,com-alt",
> > &par->com_alt))
> > +		par->com_alt = 1;
> > +
> > +	if (of_property_read_u32(node, "solomon,com-lrremap",
> > &par->com_lrremap))
> > +		par->com_lrremap = 0;
> > +
> > +	if (of_property_read_u32(node, "solomon,com-invdir",
> > &par->com_invdir))
> > +		par->com_invdir = 0;
> > +
> > +	if (of_property_read_u32(node, "solomon,vcomh",
> > &par->vcomh))
> > +		par->vcomh = par->device_info->default_vcomh;
> >  
> >  	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
> > +	if (of_property_read_u32(node, "solomon,dclk-div",
> > &par->dclk_div))
> > +		par->dclk_div = par->device_info->default_dclk_div;
> > +
> > +	if (of_property_read_u32(node, "solomon,dclk-frq",
> > &par->dclk_frq))
> > +		par->dclk_frq  =
> > par->device_info->default_dclk_frq; +
> >  	if (!vmem) {
> >  		dev_err(&client->dev, "Couldn't allocate graphical
> > memory.\n"); ret = -ENOMEM;
> > @@ -499,11 +581,9 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, gpio_set_value(par->reset, 1);
> >  	udelay(4);
> >  
> > -	if (par->ops->init) {
> > -		ret = par->ops->init(par);
> > -		if (ret)
> > -			goto reset_oled_error;
> > -	}
> > +	ret = ssd1307fb_init(par);
> > +	if (ret)
> > +		goto reset_oled_error;
> >  
> >  	ret = register_framebuffer(info);
> >  	if (ret) {
> > @@ -516,8 +596,10 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, return 0;
> >  
> >  panel_init_error:
> > -	if (par->ops->remove)
> > -		par->ops->remove(par);
> > +	if (par->device_info->device_id == DEVID_SSD1307) {
> > +		pwm_disable(par->pwm);
> > +		pwm_put(par->pwm);
> > +	};
> >  reset_oled_error:
> >  	fb_deferred_io_cleanup(info);
> >  fb_alloc_error:
> > @@ -531,11 +613,12 @@ static int ssd1307fb_remove(struct i2c_client
> > *client) struct ssd1307fb_par *par = info->par;
> >  
> >  	unregister_framebuffer(info);
> > -	if (par->ops->remove)
> > -		par->ops->remove(par);
> > +	if (par->device_info->device_id == DEVID_SSD1307) {
> > +		pwm_disable(par->pwm);
> > +		pwm_put(par->pwm);
> > +	};
> >  	fb_deferred_io_cleanup(info);
> >  	framebuffer_release(info);
> > -
> >  	return 0;
> >  }
> >  
> > -- 
> > 2.1.1
> > 
> 


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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-07 14:59     ` Thomas Niederprüm
@ 2015-02-07 15:19       ` Noralf Trønnes
  2015-02-09 10:37         ` Thomas Niederprüm
  2015-02-12 16:58         ` Maxime Ripard
  2015-02-12 16:41       ` Maxime Ripard
  1 sibling, 2 replies; 138+ messages in thread
From: Noralf Trønnes @ 2015-02-07 15:19 UTC (permalink / raw)
  To: Thomas Niederprüm, Maxime Ripard
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Hi,

Den 07.02.2015 15:59, skrev Thomas Niederprüm:
> Am Sat, 7 Feb 2015 11:42:25 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
>
>> Hi,
>>
>> On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de
>> wrote:
>>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
>>>
>>> This patches unifies the init code for the ssd130X chips and
>>> adds device tree bindings to describe the hardware configuration
>>> of the used controller. This gets rid of the magic bit values
>>> used in the init code so far.
>>>
>>> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
>>> ---
>>>   .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
>>>   drivers/video/fbdev/ssd1307fb.c                    | 243
>>> ++++++++++++++------- 2 files changed, 174 insertions(+), 80
>>> deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
>>> b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
>>> 7a12542..1230f68 100644 ---
>>> a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
>>> b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
>>> +15,17 @@ Required properties:
>>>   Optional properties:
>>>     - reset-active-low: Is the reset gpio is active on physical low?
>>> +  - solomon,segment-remap: Invert the order of data column to
>>> segment mapping
>>> +  - solomon,offset: Map the display start line to one of COM0 -
>>> COM63
>>> +  - solomon,contrast: Set initial contrast of the display
>>> +  - solomon,prechargep1: Set the duration of the precharge period
>>> phase1
>>> +  - solomon,prechargep2: Set the duration of the precharge period
>>> phase2
>>> +  - solomon,com-alt: Enable/disable alternate COM pin configuration
>>> +  - solomon,com-lrremap: Enable/disable left-right remap of COM
>>> pins
>>> +  - solomon,com-invdir: Invert COM scan direction
>>> +  - solomon,vcomh: Set VCOMH regulator voltage
>>> +  - solomon,dclk-div: Set display clock divider
>>> +  - solomon,dclk-frq: Set display clock frequency
>> I'm sorry, but this is the wrong approach, for at least two reasons:
>> you broke all existing users of that driver, which is a clear no-go,
> Unfortunately this is true. The problem is that the SSD130X controllers
> allow for a very versatile wiring of the display to the controller.
> It's over to the manufacturer of the OLED module (disp+controller) to
> decide how it's actually wired and during device initialization the
> driver has to take care to configure the SSD130X controller according
> to that wiring. If the driver fails to do so you will end up having
> your display showing garbage. Unfortunately the current sate of the
> initialization code of the ssd1307fb driver is not very flexible in that
> respect. Taking a look at the initialization code for the ssd1306 shows
> that it was written with one very special display module in mind. Most
> of the magic bit values set there are non-default values according to
> the datasheet. The result is that the driver works with that one
> particular display module but many other (differently wired) display
> modules using a ssd1306 controller won't work without changing the
> hardcoded magic bit values.
>
> My idea here was to set all configuration to the default values (as
> given in the datasheet) unless it is overwritten by DT. Of course,
> without a change in DT, this breaks the driver for all existing users.
> The only alternative would be to set the current values as default.
> Somehow this feels wrong to me as these values look arbitrary when you
> don't know what exact display module they were set for. But if you
> insist, I will change the default values.
>
>> and the DT itself should not contain any direct mapping of the
>> registers.
>>
> I think I don't get what you mean here. Is it because I do no sanity
> checks of the numbers set in DT? I was just looking for a way to hand
> over the information about the wiring of display to the driver. How
> would you propose to solve this?

I have the exact same challenge with the staging/fbtft drivers.
I have asked about this on the DT list a couple of days ago, but no 
answer yet:

Can I do register initialization from Device Tree?
http://www.spinics.net/lists/devicetree/msg68174.html


Regards,
Noralf Trønnes


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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-07 11:18   ` Maxime Ripard
@ 2015-02-07 15:35     ` Thomas Niederprüm
  2015-02-12 15:11       ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-07 15:35 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Sat, 7 Feb 2015 12:18:21 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> Hi,
> 
> On Fri, Feb 06, 2015 at 11:28:10PM +0100, niederp@physik.uni-kl.de
> wrote:
> > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > 
> > It makes sense to use vmalloc to allocate the video buffer since it
> > has to be page aligned memory for using it with mmap.
> 
> Please wrap your commit log at 80 chars.

I'll try to do so in future, sorry for that.

> 
> It looks like there's numerous fbdev drivers using this (especially
> since you copy pasted that code, without mentionning it).

Yes, I should have mentioned that in the commit message. As
implicitly indicated in the cover letter the rvmalloc() and rvfree() are
copy pasted from the vfb driver. Honestly, I didn't give this one too
much thought. It seemed a viable solution to the mmap problem. For a
bit more history on that, see my comment below.

> 
> That should be turned into an allocator so that drivers all get this
> right.
> 
> > Also deffered io seems buggy in combination with kmalloc'ed memory
> > (crash on unloading the module).
> 
> And maybe that's the real issue to fix.

The problem is solved by using vmalloc ;)

> 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  drivers/video/fbdev/ssd1307fb.c | 43
> > +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41
> > insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 01cfb46..945ded9 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -11,6 +11,7 @@
> >  #include <linux/i2c.h>
> >  #include <linux/fb.h>
> >  #include <linux/uaccess.h>
> > +#include <linux/vmalloc.h>
> >  #include <linux/of_device.h>
> >  #include <linux/of_gpio.h>
> >  #include <linux/pwm.h>
> > @@ -93,6 +94,43 @@ static struct fb_var_screeninfo ssd1307fb_var = {
> >  	.bits_per_pixel	= 1,
> >  };
> >  
> > +static void *rvmalloc(unsigned long size)
> > +{
> > +	void *mem;
> > +	unsigned long adr;
> > +
> > +	size = PAGE_ALIGN(size);
> 
> Isn't vmalloc already taking care of that?
> 
> > +	mem = vmalloc_32(size);
> 
> Why the 32 bits variant?
> 
> > +	if (!mem)
> > +		return NULL;
> > +
> > +	memset(mem, 0, size); /* Clear the ram out, no junk to the
> > user */
> > +	adr = (unsigned long) mem;
> > +	while (size > 0) {
> > +		SetPageReserved(vmalloc_to_page((void *)adr));
> 
> I'm not really sure it makes sense to mark all pages reserved if we're
> not even sure we're going to use mmap.
> 
> And why do you need to mark these pages reserved in the first place?
> 
> > +		adr += PAGE_SIZE;
> > +		size -= PAGE_SIZE;
> > +	}
> > +
> > +	return mem;
> > +}
> > +
> > +static void rvfree(void *mem, unsigned long size)
> > +{
> > +	unsigned long adr;
> > +
> > +	if (!mem)
> > +		return;
> > +
> > +	adr = (unsigned long) mem;
> > +	while ((long) size > 0) {
> > +		ClearPageReserved(vmalloc_to_page((void *)adr));
> > +		adr += PAGE_SIZE;
> > +		size -= PAGE_SIZE;
> > +	}
> > +	vfree(mem);
> > +}
> > +
> >  static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8
> > type) {
> >  	struct ssd1307fb_array *array;
> > @@ -538,13 +576,13 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, if (of_property_read_u32(node, "solomon,vcomh",
> > &par->vcomh)) par->vcomh = par->device_info->default_vcomh;
> >  
> > -	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
> >  	if (of_property_read_u32(node, "solomon,dclk-div",
> > &par->dclk_div)) par->dclk_div = par->device_info->default_dclk_div;
> >  
> >  	if (of_property_read_u32(node, "solomon,dclk-frq",
> > &par->dclk_frq)) par->dclk_frq  =
> > par->device_info->default_dclk_frq; 
> > +	vmem = rvmalloc(vmem_size);
> >  	if (!vmem) {
> >  		dev_err(&client->dev, "Couldn't allocate graphical
> > memory.\n"); ret = -ENOMEM;
> > @@ -570,7 +608,7 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, info->var.blue.offset = 0;
> >  
> >  	info->screen_base = (u8 __force __iomem *)vmem;
> > -	info->fix.smem_start = (unsigned long)vmem;
> > +	info->fix.smem_start = __pa(vmem);
> 
> Why are you changing from virtual to physical address here?

Oh, good catch! This is still a residual of my attempts to get this
working with kmalloc'ed memory. In the current state the driver is
presenting a completely wrong memory address upon mmap. As reported in
[0] info->fix.smem_start has to hold the physical address of the video
memory if it was allocated using kmalloc. Correcting this let me run
into the problem that the kmalloc'ed memory was not page aligned but,
the memory address handed to userspace mmap was aligned to the next
full page, resulting in an inaccessable display region. At that point I
just copied the vmalloc approach from the vfb driver.

[0] http://stackoverflow.com/questions/22285151/kernel-panic-using-deferred-io-on-kmalloced-buffer

> 
> Maxime
> 


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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-02-07 11:20   ` Maxime Ripard
@ 2015-02-07 16:05     ` Thomas Niederprüm
  2015-02-14 15:54       ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-07 16:05 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Sat, 7 Feb 2015 12:20:43 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de
> wrote:
> > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > 
> > This patch adds a module parameter 'bitsperpixel' to adjust the
> > colordepth of the framebuffer. All values >1 will result in memory
> > map of the requested color depth. However only the MSB of each
> > pixel will be sent to the device. The framebuffer identifies itself
> > as a grayscale display with the specified depth.
> 
> I'm not sure this is the right thing to do.
> 
> The bits per pixel for this display is rightfully defined, used and
> reported to the userspace, why would you want to change that?
> 

You are right of course. The display is 1bpp and it reports to be 1
bpp. The problem is that there is almost no userspace library that can
handle 1 bit framebuffers correctly. So it is nice if the framebuffer
(optionally) can expose itself as 8 bits per pixel grayscale to the
userspace program. As an example this allows to run DirectFB on the
framebuffer, which is not possible out of the box for 1bpp.

Also note that if do not set the module parameter at load time
the framebuffer will be 1bpp. So you have to actively set that module
parameter to make the framebuffer pretend to be more than 1bpp.

In any case I don't cling to that patch, I just thought it was a nice
feature.

> Maxime
> 


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

* Re: [PATCH 6/8]  fbdev: ssd1307fb: Add module parameter to set update delay of the  deffered io.
  2015-02-07 11:26   ` Maxime Ripard
@ 2015-02-07 16:12     ` Thomas Niederprüm
  2015-02-09  9:03       ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-07 16:12 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Sat, 7 Feb 2015 12:26:27 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Fri, Feb 06, 2015 at 11:28:12PM +0100, niederp@physik.uni-kl.de
> wrote:
> > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > 
> > This patch adds the module parameter "delaydivider" to set delay
> > for the deferred io. Effectively this is setting the refresh rate
> > for mmap access to the framebuffer. The delay for the deferred io
> > is HZ/delaydivider.
> 
> So this is actually a refresh rate?
> 
> Maybe you could expose it as such, and pass a frequency in Hz as an
> argument.

Good idea! I'll try to do it that way.

> 
> Exposing the divider directly has some issues, since the bootloader
> that set the parameter won't know the HZ value, you'll end up with
> different rates for different configurations, without any way to do
> something about it.
> 
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  drivers/video/fbdev/ssd1307fb.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 1d81877..b38315d 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -44,10 +44,14 @@
> >  #define	SSD1307FB_SET_VCOMH		0xdb
> >  
> >  #define BITSPERPIXEL 1
> > +#define DELAYDIVIDER 20
> >  
> >  static u_int bitsperpixel = BITSPERPIXEL;
> >  module_param(bitsperpixel, uint, 0);
> >  
> > +static u_int delaydivider = DELAYDIVIDER;
> > +module_param(delaydivider, uint, 0);
> > +
> 
> You're breaking the existing behaviour.

True! I'll try to keep the existing behaviour when rewriting this to
use the refresh rate.

> 
> >  struct ssd1307fb_par;
> >  
> >  struct ssd1307fb_deviceinfo {
> > @@ -312,7 +316,7 @@ static void ssd1307fb_deferred_io(struct
> > fb_info *info, }
> >  
> >  static struct fb_deferred_io ssd1307fb_defio = {
> > -	.delay		= HZ,
> > +	.delay		= HZ/DELAYDIVIDER,
> >  	.deferred_io	= ssd1307fb_deferred_io,
> >  };
> >  
> > @@ -601,6 +605,7 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, info->fix = ssd1307fb_fix;
> >  	info->fix.line_length = par->width * bitsperpixel / 8;
> >  	info->fbdefio = &ssd1307fb_defio;
> > +	info->fbdefio->delay = HZ/delaydivider;
> 
> That won't work with multiple instances of the same driver
> unfortunately.

Could you please elaborate why? I'm not seeing it...

> 
> >  
> >  	info->var = ssd1307fb_var;
> >  	info->var.bits_per_pixel = bitsperpixel;
> > -- 
> > 2.1.1
> > 
> 


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

* Re: [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-02-07 11:43   ` Maxime Ripard
@ 2015-02-07 16:42     ` Thomas Niederprüm
  2015-02-09  8:52       ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-07 16:42 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Sat, 7 Feb 2015 12:43:29 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Fri, Feb 06, 2015 at 11:28:13PM +0100, niederp@physik.uni-kl.de
> wrote:
> > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > 
> > This patch adds sysfs handles to enable userspace control over the
> > display contrast as well as the dim mode. The handles are available
> > as "contrast" and "dim" in the framebuffers sysfs domain.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  drivers/video/fbdev/ssd1307fb.c | 88
> > ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87
> > insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index b38315d..02931c7 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -33,6 +33,7 @@
> >  #define SSD1307FB_CONTRAST		0x81
> >  #define	SSD1307FB_CHARGE_PUMP		0x8d
> >  #define SSD1307FB_SEG_REMAP_ON		0xa1
> > +#define SSD1307FB_DISPLAY_DIM		0xac
> >  #define SSD1307FB_DISPLAY_OFF		0xae
> >  #define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
> >  #define SSD1307FB_DISPLAY_ON		0xaf
> > @@ -43,6 +44,9 @@
> >  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
> >  #define	SSD1307FB_SET_VCOMH		0xdb
> >  
> > +#define MIN_CONTRAST 0
> > +#define MAX_CONTRAST 255
> > +
> >  #define BITSPERPIXEL 1
> >  #define DELAYDIVIDER 20
> >  
> > @@ -69,6 +73,7 @@ struct ssd1307fb_par {
> >  	u32 dclk_div;
> >  	u32 dclk_frq;
> >  	struct ssd1307fb_deviceinfo *device_info;
> > +	u32 dim;
> >  	struct i2c_client *client;
> >  	u32 height;
> >  	struct fb_info *info;
> > @@ -515,6 +520,79 @@ static const struct of_device_id
> > ssd1307fb_of_match[] = { };
> >  MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
> >  
> > +static ssize_t show_contrast(struct device *device,
> > +			   struct device_attribute *attr, char
> > *buf) +{
> > +	struct fb_info *info = dev_get_drvdata(device);
> > +	struct ssd1307fb_par *par = info->par;
> > +
> > +	return snprintf(buf, PAGE_SIZE, "%d\n", par->contrast);
> > +}
> > +
> > +static ssize_t store_contrast(struct device *device,
> > +			    struct device_attribute *attr,
> > +			    const char *buf, size_t count)
> > +{
> > +	struct fb_info *info = dev_get_drvdata(device);
> > +	struct ssd1307fb_par *par = info->par;
> > +	unsigned long contrastval;
> > +	int ret;
> > +
> > +	ret = kstrtoul(buf, 0, &contrastval);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	par->contrast = max(min(contrastval,
> > +		(ulong)MAX_CONTRAST), (ulong)MIN_CONTRAST);
> > +
> > +	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
> > +	ret = ret & ssd1307fb_write_cmd(par->client,
> > par->contrast);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	return count;
> > +}
> > +
> > +
> > +static ssize_t show_dim(struct device *device,
> > +			   struct device_attribute *attr, char
> > *buf) +{
> > +	struct fb_info *info = dev_get_drvdata(device);
> > +	struct ssd1307fb_par *par = info->par;
> > +
> > +	return snprintf(buf, PAGE_SIZE, "%d\n", par->dim);
> > +}
> > +
> > +static ssize_t store_dim(struct device *device,
> > +			    struct device_attribute *attr,
> > +			    const char *buf, size_t count)
> > +{
> > +	struct fb_info *info = dev_get_drvdata(device);
> > +	struct ssd1307fb_par *par = info->par;
> > +	unsigned long dimval;
> > +	int ret;
> > +
> > +	ret = kstrtoul(buf, 0, &dimval);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	par->dim = max(min(dimval, (ulong)1), (ulong)0);
> > +	if (par->dim)
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_DIM);
> > +	else
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_ON);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	return count;
> > +}
> > +
> > +static struct device_attribute device_attrs[] = {
> > +	__ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast,
> > store_contrast),
> > +	__ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim),
> > +
> > +};
> > +
> 
> I would have thought this was something accessible through the
> framebuffer ioctl.
> 
> Apparently it's not, at least for the contrast, so maybe it should be
> added there, instead of doing it for a single driver?

I think the contrast setting for an OLED display is much like the
backlight setting for LCD panel. Since there is also no ioctl to set
the backlight of an LCD I wonder if the contrast of an OLED should have
one.

> 
> (oh, and btw, every sysfs file should be documented in
> Documentation/ABI)
> 
> >  static int ssd1307fb_probe(struct i2c_client *client,
> >  			   const struct i2c_device_id *id)
> >  {
> > @@ -523,7 +601,7 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, u32 vmem_size;
> >  	struct ssd1307fb_par *par;
> >  	u8 *vmem;
> > -	int ret;
> > +	int ret, i;
> >  
> >  	if (!node) {
> >  		dev_err(&client->dev, "No device tree data
> > found!\n"); @@ -650,6 +728,14 @@ static int ssd1307fb_probe(struct
> > i2c_client *client, goto reset_oled_error;
> >  
> >  	ret = register_framebuffer(info);
> > +
> > +	for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
> > +		ret = device_create_file(info->dev,
> > &device_attrs[i]); +
> > +	if (ret) {
> > +		dev_err(&client->dev, "Couldn't register sysfs
> > nodes\n");
> > +	}
> > +
> 
> sysfs_create_groups does pretty much that already.

I'll have a look at it.

> 
> And don't forget to remove these files in the .remove()

Good point! :)

> 
> >  	if (ret) {
> >  		dev_err(&client->dev, "Couldn't register the
> > framebuffer\n"); goto panel_init_error;
> > -- 
> > 2.1.1
> > 
> 
> Maxime
> 


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

* Re: [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-02-07 11:45   ` Maxime Ripard
@ 2015-02-07 16:49     ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-07 16:49 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Sat, 7 Feb 2015 12:45:34 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Fri, Feb 06, 2015 at 11:28:14PM +0100, niederp@physik.uni-kl.de
> wrote:
> > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > 
> 
> A commit log is always nice :)

Will be added.

> 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  drivers/video/fbdev/ssd1307fb.c | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 02931c7..be91dfc 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -762,6 +762,11 @@ static int ssd1307fb_remove(struct i2c_client
> > *client) {
> >  	struct fb_info *info = i2c_get_clientdata(client);
> >  	struct ssd1307fb_par *par = info->par;
> > +	int ret = 0;
> > +
> > +	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_OFF);
> > +	if (ret < 0)
> > +		return ret;
> 
> I don't think we really care about the return value here.
> 
> It might be even worse actually, since you'll end up in a intermediate
> state, where you won't have freed everything, but your remove method
> has been called still.

I agree. I will remove the check for the return statement.

> 
> Maxime
> 


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

* Re: [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-02-07 16:42     ` Thomas Niederprüm
@ 2015-02-09  8:52       ` Maxime Ripard
  2015-03-10 10:49         ` Tomi Valkeinen
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-09  8:52 UTC (permalink / raw)
  To: tomi.valkeinen, Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, linux-kernel

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

On Sat, Feb 07, 2015 at 05:42:44PM +0100, Thomas Niederprüm wrote:
> > > +static struct device_attribute device_attrs[] = {
> > > +	__ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast,
> > > store_contrast),
> > > +	__ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim),
> > > +
> > > +};
> > > +
> > 
> > I would have thought this was something accessible through the
> > framebuffer ioctl.
> > 
> > Apparently it's not, at least for the contrast, so maybe it should be
> > added there, instead of doing it for a single driver?
> 
> I think the contrast setting for an OLED display is much like the
> backlight setting for LCD panel. Since there is also no ioctl to set
> the backlight of an LCD I wonder if the contrast of an OLED should have
> one.

It's too much of framebuffer interface debate for me here. Tomi?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 6/8]  fbdev: ssd1307fb: Add module parameter to set update delay of the  deffered io.
  2015-02-07 16:12     ` Thomas Niederprüm
@ 2015-02-09  9:03       ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-02-09  9:03 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Sat, Feb 07, 2015 at 05:12:11PM +0100, Thomas Niederprüm wrote:
> Am Sat, 7 Feb 2015 12:26:27 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
> > On Fri, Feb 06, 2015 at 11:28:12PM +0100, niederp@physik.uni-kl.de
> > wrote:
> > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > 
> > > This patch adds the module parameter "delaydivider" to set delay
> > > for the deferred io. Effectively this is setting the refresh rate
> > > for mmap access to the framebuffer. The delay for the deferred io
> > > is HZ/delaydivider.
> > 
> > So this is actually a refresh rate?
> > 
> > Maybe you could expose it as such, and pass a frequency in Hz as an
> > argument.
> 
> Good idea! I'll try to do it that way.
> 
> > 
> > Exposing the divider directly has some issues, since the bootloader
> > that set the parameter won't know the HZ value, you'll end up with
> > different rates for different configurations, without any way to do
> > something about it.
> > 
> > > 
> > > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > ---
> > >  drivers/video/fbdev/ssd1307fb.c | 7 ++++++-
> > >  1 file changed, 6 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > > b/drivers/video/fbdev/ssd1307fb.c index 1d81877..b38315d 100644
> > > --- a/drivers/video/fbdev/ssd1307fb.c
> > > +++ b/drivers/video/fbdev/ssd1307fb.c
> > > @@ -44,10 +44,14 @@
> > >  #define	SSD1307FB_SET_VCOMH		0xdb
> > >  
> > >  #define BITSPERPIXEL 1
> > > +#define DELAYDIVIDER 20
> > >  
> > >  static u_int bitsperpixel = BITSPERPIXEL;
> > >  module_param(bitsperpixel, uint, 0);
> > >  
> > > +static u_int delaydivider = DELAYDIVIDER;
> > > +module_param(delaydivider, uint, 0);
> > > +
> > 
> > You're breaking the existing behaviour.
> 
> True! I'll try to keep the existing behaviour when rewriting this to
> use the refresh rate.
> 
> > 
> > >  struct ssd1307fb_par;
> > >  
> > >  struct ssd1307fb_deviceinfo {
> > > @@ -312,7 +316,7 @@ static void ssd1307fb_deferred_io(struct
> > > fb_info *info, }
> > >  
> > >  static struct fb_deferred_io ssd1307fb_defio = {
> > > -	.delay		= HZ,
> > > +	.delay		= HZ/DELAYDIVIDER,
> > >  	.deferred_io	= ssd1307fb_deferred_io,
> > >  };
> > >  
> > > @@ -601,6 +605,7 @@ static int ssd1307fb_probe(struct i2c_client
> > > *client, info->fix = ssd1307fb_fix;
> > >  	info->fix.line_length = par->width * bitsperpixel / 8;
> > >  	info->fbdefio = &ssd1307fb_defio;
> > > +	info->fbdefio->delay = HZ/delaydivider;
> > 
> > That won't work with multiple instances of the same driver
> > unfortunately.
> 
> Could you please elaborate why? I'm not seeing it...

On a general basis, because the structure is shared by all the
instances of the driver, so it's usually not such a good idea to mix
the static declaration of the structure and the dynamic one.

From a more fundamental point of view, because this parameter will
most likely be different from one instance to another?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-07 15:19       ` Noralf Trønnes
@ 2015-02-09 10:37         ` Thomas Niederprüm
  2015-02-12 16:58         ` Maxime Ripard
  1 sibling, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-09 10:37 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: Maxime Ripard, linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Samstag, den 07.02.2015, 16:19 +0100 schrieb Noralf Trønnes:
> Hi,
> 
> Den 07.02.2015 15:59, skrev Thomas Niederprüm:
> > Am Sat, 7 Feb 2015 11:42:25 +0100
> > schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> >
> >> Hi,
> >>
> >> On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de
> >> wrote:
> >>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> >>>
> >>> This patches unifies the init code for the ssd130X chips and
> >>> adds device tree bindings to describe the hardware configuration
> >>> of the used controller. This gets rid of the magic bit values
> >>> used in the init code so far.
> >>>
> >>> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> >>> ---
> >>>   .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
> >>>   drivers/video/fbdev/ssd1307fb.c                    | 243
> >>> ++++++++++++++------- 2 files changed, 174 insertions(+), 80
> >>> deletions(-)
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> >>> b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> >>> 7a12542..1230f68 100644 ---
> >>> a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> >>> b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
> >>> +15,17 @@ Required properties:
> >>>   Optional properties:
> >>>     - reset-active-low: Is the reset gpio is active on physical low?
> >>> +  - solomon,segment-remap: Invert the order of data column to
> >>> segment mapping
> >>> +  - solomon,offset: Map the display start line to one of COM0 -
> >>> COM63
> >>> +  - solomon,contrast: Set initial contrast of the display
> >>> +  - solomon,prechargep1: Set the duration of the precharge period
> >>> phase1
> >>> +  - solomon,prechargep2: Set the duration of the precharge period
> >>> phase2
> >>> +  - solomon,com-alt: Enable/disable alternate COM pin configuration
> >>> +  - solomon,com-lrremap: Enable/disable left-right remap of COM
> >>> pins
> >>> +  - solomon,com-invdir: Invert COM scan direction
> >>> +  - solomon,vcomh: Set VCOMH regulator voltage
> >>> +  - solomon,dclk-div: Set display clock divider
> >>> +  - solomon,dclk-frq: Set display clock frequency
> >> I'm sorry, but this is the wrong approach, for at least two reasons:
> >> you broke all existing users of that driver, which is a clear no-go,
> > Unfortunately this is true. The problem is that the SSD130X controllers
> > allow for a very versatile wiring of the display to the controller.
> > It's over to the manufacturer of the OLED module (disp+controller) to
> > decide how it's actually wired and during device initialization the
> > driver has to take care to configure the SSD130X controller according
> > to that wiring. If the driver fails to do so you will end up having
> > your display showing garbage. Unfortunately the current sate of the
> > initialization code of the ssd1307fb driver is not very flexible in that
> > respect. Taking a look at the initialization code for the ssd1306 shows
> > that it was written with one very special display module in mind. Most
> > of the magic bit values set there are non-default values according to
> > the datasheet. The result is that the driver works with that one
> > particular display module but many other (differently wired) display
> > modules using a ssd1306 controller won't work without changing the
> > hardcoded magic bit values.
> >
> > My idea here was to set all configuration to the default values (as
> > given in the datasheet) unless it is overwritten by DT. Of course,
> > without a change in DT, this breaks the driver for all existing users.
> > The only alternative would be to set the current values as default.
> > Somehow this feels wrong to me as these values look arbitrary when you
> > don't know what exact display module they were set for. But if you
> > insist, I will change the default values.
> >
> >> and the DT itself should not contain any direct mapping of the
> >> registers.
> >>
> > I think I don't get what you mean here. Is it because I do no sanity
> > checks of the numbers set in DT? I was just looking for a way to hand
> > over the information about the wiring of display to the driver. How
> > would you propose to solve this?
> 
> I have the exact same challenge with the staging/fbtft drivers.

Even though we are facing the same problem here, yours is much harder
than mine, since I have much more knowledge about the controller.
Therefor I have no need to completely expose the registers for
initialization. I just define all configurable options that the
controller has in DT and let the driver take care to write the
corresponding register values during initialization. Of course this
needs the exact knowledge of the configuration options of the controller
as well as register addresses of these options in the driver. So I have
the fear that this approach does not scale for a driver handling
different controllers.

> I have asked about this on the DT list a couple of days ago, but no 
> answer yet:
> 
> Can I do register initialization from Device Tree?
> http://www.spinics.net/lists/devicetree/msg68174.html
> 
> 
> Regards,
> Noralf Trønnes
> 

-- 
Thomas Niederprüm
TU Kaiserslautern
FB Physik (AG Ott)
Erwin-Schrödinger-Str. 46/431
67663 Kaiserslautern
Tel.: 0631 205 2387
Fax: 0631 205 3906


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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-07 15:35     ` Thomas Niederprüm
@ 2015-02-12 15:11       ` Maxime Ripard
  2015-02-14 14:22         ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-12 15:11 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Sat, Feb 07, 2015 at 04:35:41PM +0100, Thomas Niederprüm wrote:
> Am Sat, 7 Feb 2015 12:18:21 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
> > Hi,
> > 
> > On Fri, Feb 06, 2015 at 11:28:10PM +0100, niederp@physik.uni-kl.de
> > wrote:
> > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > 
> > > It makes sense to use vmalloc to allocate the video buffer since it
> > > has to be page aligned memory for using it with mmap.
> > 
> > Please wrap your commit log at 80 chars.
> 
> I'll try to do so in future, sorry for that.
> 
> > 
> > It looks like there's numerous fbdev drivers using this (especially
> > since you copy pasted that code, without mentionning it).
> 
> Yes, I should have mentioned that in the commit message. As
> implicitly indicated in the cover letter the rvmalloc() and rvfree() are
> copy pasted from the vfb driver. Honestly, I didn't give this one too
> much thought. It seemed a viable solution to the mmap problem. For a
> bit more history on that, see my comment below.
> 
> > 
> > That should be turned into an allocator so that drivers all get this
> > right.
> > 
> > > Also deffered io seems buggy in combination with kmalloc'ed memory
> > > (crash on unloading the module).
> > 
> > And maybe that's the real issue to fix.
> 
> The problem is solved by using vmalloc ;)

Yep, but why do you need to mark the reserved pages?

...

> > > @@ -570,7 +608,7 @@ static int ssd1307fb_probe(struct i2c_client
> > > *client, info->var.blue.offset = 0;
> > >  
> > >  	info->screen_base = (u8 __force __iomem *)vmem;
> > > -	info->fix.smem_start = (unsigned long)vmem;
> > > +	info->fix.smem_start = __pa(vmem);
> > 
> > Why are you changing from virtual to physical address here?
> 
> Oh, good catch! This is still a residual of my attempts to get this
> working with kmalloc'ed memory. In the current state the driver is
> presenting a completely wrong memory address upon mmap. As reported in
> [0] info->fix.smem_start has to hold the physical address of the video
> memory if it was allocated using kmalloc. Correcting this let me run
> into the problem that the kmalloc'ed memory was not page aligned but,
> the memory address handed to userspace mmap was aligned to the next
> full page, resulting in an inaccessable display region. At that point I
> just copied the vmalloc approach from the vfb driver.
> 
> [0] http://stackoverflow.com/questions/22285151/kernel-panic-using-deferred-io-on-kmalloced-buffer

And the documentation of fb_fix_screeninfo indeed state that this
should be the physical address:
http://lxr.free-electrons.com/source/include/uapi/linux/fb.h#L158

Could you make that a separate patch?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-07 14:59     ` Thomas Niederprüm
  2015-02-07 15:19       ` Noralf Trønnes
@ 2015-02-12 16:41       ` Maxime Ripard
  2015-02-14 16:12         ` Thomas Niederprüm
  1 sibling, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-12 16:41 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Sat, Feb 07, 2015 at 03:59:33PM +0100, Thomas Niederprüm wrote:
> Am Sat, 7 Feb 2015 11:42:25 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
> > Hi,
> > 
> > On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de
> > wrote:
> > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > 
> > > This patches unifies the init code for the ssd130X chips and
> > > adds device tree bindings to describe the hardware configuration
> > > of the used controller. This gets rid of the magic bit values
> > > used in the init code so far.
> > > 
> > > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > ---
> > >  .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
> > >  drivers/video/fbdev/ssd1307fb.c                    | 243
> > > ++++++++++++++------- 2 files changed, 174 insertions(+), 80
> > > deletions(-)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > > 7a12542..1230f68 100644 ---
> > > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
> > > +15,17 @@ Required properties: 
> > >  Optional properties:
> > >    - reset-active-low: Is the reset gpio is active on physical low?
> > > +  - solomon,segment-remap: Invert the order of data column to
> > > segment mapping
> > > +  - solomon,offset: Map the display start line to one of COM0 -
> > > COM63
> > > +  - solomon,contrast: Set initial contrast of the display
> > > +  - solomon,prechargep1: Set the duration of the precharge period
> > > phase1
> > > +  - solomon,prechargep2: Set the duration of the precharge period
> > > phase2
> > > +  - solomon,com-alt: Enable/disable alternate COM pin configuration
> > > +  - solomon,com-lrremap: Enable/disable left-right remap of COM
> > > pins
> > > +  - solomon,com-invdir: Invert COM scan direction
> > > +  - solomon,vcomh: Set VCOMH regulator voltage
> > > +  - solomon,dclk-div: Set display clock divider
> > > +  - solomon,dclk-frq: Set display clock frequency
> > 
> > I'm sorry, but this is the wrong approach, for at least two reasons:
> > you broke all existing users of that driver, which is a clear no-go,
> 
> Unfortunately this is true. The problem is that the SSD130X
> controllers allow for a very versatile wiring of the display to the
> controller.  It's over to the manufacturer of the OLED module
> (disp+controller) to decide how it's actually wired and during
> device initialization the driver has to take care to configure the
> SSD130X controller according to that wiring. If the driver fails to
> do so you will end up having your display showing
> garbage.

How so?

Does it depend on the X, or can it change from one same controller to
another? to what extent?

The 1306 for example seems to not be using these values at all, while
the 1307 does.

> Unfortunately the current sate of the initialization code of the
> ssd1307fb driver is not very flexible in that respect. Taking a look
> at the initialization code for the ssd1306 shows that it was written
> with one very special display module in mind. Most of the magic bit
> values set there are non-default values according to the
> datasheet. The result is that the driver works with that one
> particular display module but many other (differently wired) display
> modules using a ssd1306 controller won't work without changing the
> hardcoded magic bit values.
> 
> My idea here was to set all configuration to the default values (as
> given in the datasheet) unless it is overwritten by DT. Of course,
> without a change in DT, this breaks the driver for all existing users.
> The only alternative would be to set the current values as default.
> Somehow this feels wrong to me as these values look arbitrary when you
> don't know what exact display module they were set for. But if you
> insist, I will change the default values.

Unfortunately, the DT bindings are to be considered an ABI, and we
should support booting with older DTs (not that I personally care
about it, but that's another issue). So we really don't have much
choice here.

Moreover, that issue left aside, modifying bindings like this without
fixing up the in-tree users is considered quite rude :)

> > and the DT itself should not contain any direct mapping of the
> > registers.
> > 
> 
> I think I don't get what you mean here. Is it because I do no sanity
> checks of the numbers set in DT? I was just looking for a way to hand
> over the information about the wiring of display to the driver. How
> would you propose to solve this?

What I meant was that replicating direct registers value is usually a
recipe for a later failure, especially if we can have the information
under a generic and easy to understand manner.

For example, replacing the solomon,dclk-div and solomon,dclk-frq
properties by a clock-frequency property in Hz, and computing the
divider and that register in your driver is usually better, also
because it allows to have different requirements / algorithms to
compute that if some other chip needs it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-07 15:19       ` Noralf Trønnes
  2015-02-09 10:37         ` Thomas Niederprüm
@ 2015-02-12 16:58         ` Maxime Ripard
  1 sibling, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-02-12 16:58 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: Thomas Niederprüm, linux-fbdev, plagnioj, tomi.valkeinen,
	linux-kernel

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

On Sat, Feb 07, 2015 at 04:19:37PM +0100, Noralf Trønnes wrote:
> >>and the DT itself should not contain any direct mapping of the
> >>registers.
> >>
> >I think I don't get what you mean here. Is it because I do no sanity
> >checks of the numbers set in DT? I was just looking for a way to hand
> >over the information about the wiring of display to the driver. How
> >would you propose to solve this?
> 
> I have the exact same challenge with the staging/fbtft drivers.
> I have asked about this on the DT list a couple of days ago, but no answer
> yet:
> 
> Can I do register initialization from Device Tree?
> http://www.spinics.net/lists/devicetree/msg68174.html

The DT is just an hardware representation, and should not contain any
logic. Any attempts at doing so have been failures, mostly because
that kind of construct are really fragile.

What would happen if at some point some new controller pops up and
need to poke a GPIO before every write?

Every driver should contain all the needed code to initialise properly
its hardware. The only exception being stuff that are volatile by
essence, like bus addresses, GPIOs, etc.

In your case, using (and maybe extending) the generic panel bindings
look like a better way forward.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-12 15:11       ` Maxime Ripard
@ 2015-02-14 14:22         ` Thomas Niederprüm
  2015-02-14 15:36           ` Maxime Ripard
  2015-03-10 11:28           ` Tomi Valkeinen
  0 siblings, 2 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-14 14:22 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Thu, 12 Feb 2015 16:11:21 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Sat, Feb 07, 2015 at 04:35:41PM +0100, Thomas Niederprüm wrote:
> > Am Sat, 7 Feb 2015 12:18:21 +0100
> > schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> > 
> > > Hi,
> > > 
> > > On Fri, Feb 06, 2015 at 11:28:10PM +0100, niederp@physik.uni-kl.de
> > > wrote:
> > > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > > 
> > > > It makes sense to use vmalloc to allocate the video buffer
> > > > since it has to be page aligned memory for using it with mmap.
> > > 
> > > Please wrap your commit log at 80 chars.
> > 
> > I'll try to do so in future, sorry for that.
> > 
> > > 
> > > It looks like there's numerous fbdev drivers using this
> > > (especially since you copy pasted that code, without mentionning
> > > it).
> > 
> > Yes, I should have mentioned that in the commit message. As
> > implicitly indicated in the cover letter the rvmalloc() and
> > rvfree() are copy pasted from the vfb driver. Honestly, I didn't
> > give this one too much thought. It seemed a viable solution to the
> > mmap problem. For a bit more history on that, see my comment below.
> > 
> > > 
> > > That should be turned into an allocator so that drivers all get
> > > this right.
> > > 
> > > > Also deffered io seems buggy in combination with kmalloc'ed
> > > > memory (crash on unloading the module).
> > > 
> > > And maybe that's the real issue to fix.
> > 
> > The problem is solved by using vmalloc ;)
> 
> Yep, but why do you need to mark the reserved pages?
> 
> ...

As far as I understood mmaped memory is marked as userspace memory in
the page table and is therefore subject to swapping. The pages are
marked reserved to make clear that this memory can not be swapped and
thus lock the pages in memory. See discussions [0,1,2]. 

[0]http://stackoverflow.com/questions/10760479/mmap-kernel-buffer-to-user-space
[1]http://www.linuxquestions.org/questions/linux-kernel-70/why-why-setpagereserved-is-needed-when-map-a-kernel-space-to-user-space-885176/
[2]https://sites.google.com/site/skartikeyan/mmap.html

> 
> > > > @@ -570,7 +608,7 @@ static int ssd1307fb_probe(struct i2c_client
> > > > *client, info->var.blue.offset = 0;
> > > >  
> > > >  	info->screen_base = (u8 __force __iomem *)vmem;
> > > > -	info->fix.smem_start = (unsigned long)vmem;
> > > > +	info->fix.smem_start = __pa(vmem);
> > > 
> > > Why are you changing from virtual to physical address here?
> > 
> > Oh, good catch! This is still a residual of my attempts to get this
> > working with kmalloc'ed memory. In the current state the driver is
> > presenting a completely wrong memory address upon mmap. As reported
> > in [0] info->fix.smem_start has to hold the physical address of the
> > video memory if it was allocated using kmalloc. Correcting this let
> > me run into the problem that the kmalloc'ed memory was not page
> > aligned but, the memory address handed to userspace mmap was
> > aligned to the next full page, resulting in an inaccessable display
> > region. At that point I just copied the vmalloc approach from the
> > vfb driver.
> > 
> > [0]
> > http://stackoverflow.com/questions/22285151/kernel-panic-using-deferred-io-on-kmalloced-buffer
> 
> And the documentation of fb_fix_screeninfo indeed state that this
> should be the physical address:
> http://lxr.free-electrons.com/source/include/uapi/linux/fb.h#L158
> 
> Could you make that a separate patch?

Will be a separate patch in v2.

> 
> Thanks,
> Maxime
> 

Thomas


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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-14 14:22         ` Thomas Niederprüm
@ 2015-02-14 15:36           ` Maxime Ripard
  2015-03-10 11:28           ` Tomi Valkeinen
  1 sibling, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-02-14 15:36 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Sat, Feb 14, 2015 at 03:22:12PM +0100, Thomas Niederprüm wrote:
> Am Thu, 12 Feb 2015 16:11:21 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
> > On Sat, Feb 07, 2015 at 04:35:41PM +0100, Thomas Niederprüm wrote:
> > > Am Sat, 7 Feb 2015 12:18:21 +0100
> > > schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> > > 
> > > > Hi,
> > > > 
> > > > On Fri, Feb 06, 2015 at 11:28:10PM +0100, niederp@physik.uni-kl.de
> > > > wrote:
> > > > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > > > 
> > > > > It makes sense to use vmalloc to allocate the video buffer
> > > > > since it has to be page aligned memory for using it with mmap.
> > > > 
> > > > Please wrap your commit log at 80 chars.
> > > 
> > > I'll try to do so in future, sorry for that.
> > > 
> > > > 
> > > > It looks like there's numerous fbdev drivers using this
> > > > (especially since you copy pasted that code, without mentionning
> > > > it).
> > > 
> > > Yes, I should have mentioned that in the commit message. As
> > > implicitly indicated in the cover letter the rvmalloc() and
> > > rvfree() are copy pasted from the vfb driver. Honestly, I didn't
> > > give this one too much thought. It seemed a viable solution to the
> > > mmap problem. For a bit more history on that, see my comment below.
> > > 
> > > > 
> > > > That should be turned into an allocator so that drivers all get
> > > > this right.
> > > > 
> > > > > Also deffered io seems buggy in combination with kmalloc'ed
> > > > > memory (crash on unloading the module).
> > > > 
> > > > And maybe that's the real issue to fix.
> > > 
> > > The problem is solved by using vmalloc ;)
> > 
> > Yep, but why do you need to mark the reserved pages?
> > 
> > ...
> 
> As far as I understood mmaped memory is marked as userspace memory in
> the page table and is therefore subject to swapping. The pages are
> marked reserved to make clear that this memory can not be swapped and
> thus lock the pages in memory. See discussions [0,1,2]. 
> 
> [0]http://stackoverflow.com/questions/10760479/mmap-kernel-buffer-to-user-space
> [1]http://www.linuxquestions.org/questions/linux-kernel-70/why-why-setpagereserved-is-needed-when-map-a-kernel-space-to-user-space-885176/
> [2]https://sites.google.com/site/skartikeyan/mmap.html

Hmmm, both https://lwn.net/Articles/28746/ and
http://linux-mm.org/DeviceDriverMmap tell otherwise :)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-02-07 16:05     ` Thomas Niederprüm
@ 2015-02-14 15:54       ` Maxime Ripard
  2015-03-10 10:45         ` Tomi Valkeinen
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-02-14 15:54 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Sat, Feb 07, 2015 at 05:05:03PM +0100, Thomas Niederprüm wrote:
> Am Sat, 7 Feb 2015 12:20:43 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
> > On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de
> > wrote:
> > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > 
> > > This patch adds a module parameter 'bitsperpixel' to adjust the
> > > colordepth of the framebuffer. All values >1 will result in memory
> > > map of the requested color depth. However only the MSB of each
> > > pixel will be sent to the device. The framebuffer identifies itself
> > > as a grayscale display with the specified depth.
> > 
> > I'm not sure this is the right thing to do.
> > 
> > The bits per pixel for this display is rightfully defined, used and
> > reported to the userspace, why would you want to change that?
> 
> You are right of course. The display is 1bpp and it reports to be 1
> bpp. The problem is that there is almost no userspace library that can
> handle 1 bit framebuffers correctly. So it is nice if the framebuffer
> (optionally) can expose itself as 8 bits per pixel grayscale to the
> userspace program. As an example this allows to run DirectFB on the
> framebuffer, which is not possible out of the box for 1bpp.
> 
> Also note that if do not set the module parameter at load time
> the framebuffer will be 1bpp. So you have to actively set that module
> parameter to make the framebuffer pretend to be more than 1bpp.
> 
> In any case I don't cling to that patch, I just thought it was a nice
> feature.

I'd say that the right fix would be to patch DirectFB, instead of
faking that in the kernel.

But again, that's probably Tomi's call, not mine.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-12 16:41       ` Maxime Ripard
@ 2015-02-14 16:12         ` Thomas Niederprüm
  2015-02-23  9:43           ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-02-14 16:12 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

Am Thu, 12 Feb 2015 17:41:47 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Sat, Feb 07, 2015 at 03:59:33PM +0100, Thomas Niederprüm wrote:
> > Am Sat, 7 Feb 2015 11:42:25 +0100
> > schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> > 
> > > Hi,
> > > 
> > > On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de
> > > wrote:
> > > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > > 
> > > > This patches unifies the init code for the ssd130X chips and
> > > > adds device tree bindings to describe the hardware configuration
> > > > of the used controller. This gets rid of the magic bit values
> > > > used in the init code so far.
> > > > 
> > > > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > > ---
> > > >  .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
> > > >  drivers/video/fbdev/ssd1307fb.c                    | 243
> > > > ++++++++++++++------- 2 files changed, 174 insertions(+), 80
> > > > deletions(-)
> > > > 
> > > > diff --git
> > > > a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > > > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > > > 7a12542..1230f68 100644 ---
> > > > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > > > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@
> > > > -15,6 +15,17 @@ Required properties: Optional properties:
> > > >    - reset-active-low: Is the reset gpio is active on physical
> > > > low?
> > > > +  - solomon,segment-remap: Invert the order of data column to
> > > > segment mapping
> > > > +  - solomon,offset: Map the display start line to one of COM0 -
> > > > COM63
> > > > +  - solomon,contrast: Set initial contrast of the display
> > > > +  - solomon,prechargep1: Set the duration of the precharge
> > > > period phase1
> > > > +  - solomon,prechargep2: Set the duration of the precharge
> > > > period phase2
> > > > +  - solomon,com-alt: Enable/disable alternate COM pin
> > > > configuration
> > > > +  - solomon,com-lrremap: Enable/disable left-right remap of COM
> > > > pins
> > > > +  - solomon,com-invdir: Invert COM scan direction
> > > > +  - solomon,vcomh: Set VCOMH regulator voltage
> > > > +  - solomon,dclk-div: Set display clock divider
> > > > +  - solomon,dclk-frq: Set display clock frequency
> > > 
> > > I'm sorry, but this is the wrong approach, for at least two
> > > reasons: you broke all existing users of that driver, which is a
> > > clear no-go,
> > 
> > Unfortunately this is true. The problem is that the SSD130X
> > controllers allow for a very versatile wiring of the display to the
> > controller.  It's over to the manufacturer of the OLED module
> > (disp+controller) to decide how it's actually wired and during
> > device initialization the driver has to take care to configure the
> > SSD130X controller according to that wiring. If the driver fails to
> > do so you will end up having your display showing
> > garbage.
> 
> How so?

One good example is the segment remap. It basically allows to invert the
order of the output pins connecting to the oled panel. This gives the
manufacturer of the module the freedom wire it the one way or the
other, depending on the PCB restrictions/panel layout (Section 10.1.12
of [0], 10.1.8 in [1], 9.1.8 in [2]). However, once the panel is
connected to the controller it's determined whether the segment remap
is needed or not. Setting the segment remap as done in the current
initialization code for ssd1306 and ssd1307 makes my display module
show it's contents mirrored left to right, probably since the
manufacturer decided not to connect the panel in an inverted order.

The same applies to the com-alt, com-lrremap and com-invdir values,
which define different possibilities for the COM signals pin
configuration (Section 10.1.26 of [0], 10.1.18 in [1], 9.1.18 in [2])
and readout direction of the video memory (Section 10.1.21 of [0],
10.1.14 in [1], 9.1.14 in [2]). Setting com-alt incorrectly leaves
every other line of the display blank. Setting com-lrremap incorrectly
produces a very distorted image. Setting com-invdir incorrectly flips
the image upside down.

IMHO at least these four hardware-specific properties need to be known
to the driver in order to initialize the hardware correctly.

> 
> Does it depend on the X, or can it change from one same controller to
> another? to what extent?

Unfortunately I do not posses any hardware utilizing a ssd1306 or
ssd1307 controller. My primary and only target device is a Newhaven
NHD-3.12-25664UCB2 OLED display module using an SSD1305 controller. I
just inferred from the datasheets of ssd1306/7 [1,2] that they should
behave the same since the registers are bit to bit identical (except
for the VHCOM register). Maybe that was a bit too naive :/

> 
> The 1306 for example seems to not be using these values at all, while
> the 1307 does.

That is surprising. In that case I would like to ask the guys from
Solomon why they describe all these options in the SSD1306 datasheet
[1]. But in any case, isn't that good news for the problem of setting
the default values. When the 1306 isn't using these values anyway we can
not break the initialization by setting different default values. In
this case the problem of the default values boils down to the segment
remap only since this is set in the init code of the 1307, while the
default would be to leave it off.

> 
> > Unfortunately the current sate of the initialization code of the
> > ssd1307fb driver is not very flexible in that respect. Taking a look
> > at the initialization code for the ssd1306 shows that it was written
> > with one very special display module in mind. Most of the magic bit
> > values set there are non-default values according to the
> > datasheet. The result is that the driver works with that one
> > particular display module but many other (differently wired) display
> > modules using a ssd1306 controller won't work without changing the
> > hardcoded magic bit values.
> > 
> > My idea here was to set all configuration to the default values (as
> > given in the datasheet) unless it is overwritten by DT. Of course,
> > without a change in DT, this breaks the driver for all existing
> > users. The only alternative would be to set the current values as
> > default. Somehow this feels wrong to me as these values look
> > arbitrary when you don't know what exact display module they were
> > set for. But if you insist, I will change the default values.
> 
> Unfortunately, the DT bindings are to be considered an ABI, and we
> should support booting with older DTs (not that I personally care
> about it, but that's another issue). So we really don't have much
> choice here.
> 
> Moreover, that issue left aside, modifying bindings like this without
> fixing up the in-tree users is considered quite rude :)

I didn't intend to be rude, sorry. A quick search revealed that there
is luckily only one in-tree user, which is imx28-cfa10036.dts. In case
it will be necessary I will include a patch to fix this.

> > > and the DT itself should not contain any direct mapping of the
> > > registers.
> > > 
> > 
> > I think I don't get what you mean here. Is it because I do no sanity
> > checks of the numbers set in DT? I was just looking for a way to
> > hand over the information about the wiring of display to the
> > driver. How would you propose to solve this?
> 
> What I meant was that replicating direct registers value is usually a
> recipe for a later failure, especially if we can have the information
> under a generic and easy to understand manner.
> 
> For example, replacing the solomon,dclk-div and solomon,dclk-frq
> properties by a clock-frequency property in Hz, and computing the
> divider and that register in your driver is usually better, also
> because it allows to have different requirements / algorithms to
> compute that if some other chip needs it.

I'll give that a try, even though that particular one is not trivial
since the documentation on the actual frequency that is set by the
dclk-freq is very poor (not present for 1306/1307 [1,2], just a graph
for 1305 [0]).

For the properties describing the hardware pin configuration (see above)
I see no real alternative. Maybe they can all be covered by one DT
property like:
solomon,com-cfg = PINCFG_SEGREMAP | PINCFG_COMALT | PINCFG_COMINV |
PINCFG_COMLRRM
each PINCFG_* setting one bit. The driver will then translate this into
the correct settings for the 130X registers. The only problem here is
that this implicitly assumes the default values of each bit to be 0.

> 
> Maxime
> 

[0]http://www.newhavendisplay.com/app_notes/SSD1305.pdf
[1]http://www.adafruit.com/datasheets/SSD1306.pdf
[2]http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf

Thomas

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

* Re: [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree
  2015-02-14 16:12         ` Thomas Niederprüm
@ 2015-02-23  9:43           ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-02-23  9:43 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: linux-fbdev, plagnioj, tomi.valkeinen, linux-kernel

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

On Sat, Feb 14, 2015 at 05:12:32PM +0100, Thomas Niederprüm wrote:
> Am Thu, 12 Feb 2015 17:41:47 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
> > On Sat, Feb 07, 2015 at 03:59:33PM +0100, Thomas Niederprüm wrote:
> > > Am Sat, 7 Feb 2015 11:42:25 +0100
> > > schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> > > 
> > > > Hi,
> > > > 
> > > > On Fri, Feb 06, 2015 at 11:28:08PM +0100, niederp@physik.uni-kl.de
> > > > wrote:
> > > > > From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > > > 
> > > > > This patches unifies the init code for the ssd130X chips and
> > > > > adds device tree bindings to describe the hardware configuration
> > > > > of the used controller. This gets rid of the magic bit values
> > > > > used in the init code so far.
> > > > > 
> > > > > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > > > ---
> > > > >  .../devicetree/bindings/video/ssd1307fb.txt        |  11 +
> > > > >  drivers/video/fbdev/ssd1307fb.c                    | 243
> > > > > ++++++++++++++------- 2 files changed, 174 insertions(+), 80
> > > > > deletions(-)
> > > > > 
> > > > > diff --git
> > > > > a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > > > > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > > > > 7a12542..1230f68 100644 ---
> > > > > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > > > > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@
> > > > > -15,6 +15,17 @@ Required properties: Optional properties:
> > > > >    - reset-active-low: Is the reset gpio is active on physical
> > > > > low?
> > > > > +  - solomon,segment-remap: Invert the order of data column to
> > > > > segment mapping
> > > > > +  - solomon,offset: Map the display start line to one of COM0 -
> > > > > COM63
> > > > > +  - solomon,contrast: Set initial contrast of the display
> > > > > +  - solomon,prechargep1: Set the duration of the precharge
> > > > > period phase1
> > > > > +  - solomon,prechargep2: Set the duration of the precharge
> > > > > period phase2
> > > > > +  - solomon,com-alt: Enable/disable alternate COM pin
> > > > > configuration
> > > > > +  - solomon,com-lrremap: Enable/disable left-right remap of COM
> > > > > pins
> > > > > +  - solomon,com-invdir: Invert COM scan direction
> > > > > +  - solomon,vcomh: Set VCOMH regulator voltage
> > > > > +  - solomon,dclk-div: Set display clock divider
> > > > > +  - solomon,dclk-frq: Set display clock frequency
> > > > 
> > > > I'm sorry, but this is the wrong approach, for at least two
> > > > reasons: you broke all existing users of that driver, which is a
> > > > clear no-go,
> > > 
> > > Unfortunately this is true. The problem is that the SSD130X
> > > controllers allow for a very versatile wiring of the display to the
> > > controller.  It's over to the manufacturer of the OLED module
> > > (disp+controller) to decide how it's actually wired and during
> > > device initialization the driver has to take care to configure the
> > > SSD130X controller according to that wiring. If the driver fails to
> > > do so you will end up having your display showing
> > > garbage.
> > 
> > How so?
> 
> One good example is the segment remap. It basically allows to invert the
> order of the output pins connecting to the oled panel. This gives the
> manufacturer of the module the freedom wire it the one way or the
> other, depending on the PCB restrictions/panel layout (Section 10.1.12
> of [0], 10.1.8 in [1], 9.1.8 in [2]). However, once the panel is
> connected to the controller it's determined whether the segment remap
> is needed or not. Setting the segment remap as done in the current
> initialization code for ssd1306 and ssd1307 makes my display module
> show it's contents mirrored left to right, probably since the
> manufacturer decided not to connect the panel in an inverted order.
> 
> The same applies to the com-alt, com-lrremap and com-invdir values,
> which define different possibilities for the COM signals pin
> configuration (Section 10.1.26 of [0], 10.1.18 in [1], 9.1.18 in [2])
> and readout direction of the video memory (Section 10.1.21 of [0],
> 10.1.14 in [1], 9.1.14 in [2]). Setting com-alt incorrectly leaves
> every other line of the display blank. Setting com-lrremap incorrectly
> produces a very distorted image. Setting com-invdir incorrectly flips
> the image upside down.
> 
> IMHO at least these four hardware-specific properties need to be known
> to the driver in order to initialize the hardware correctly.

I'd agree then.

> > Does it depend on the X, or can it change from one same controller to
> > another? to what extent?
> 
> Unfortunately I do not posses any hardware utilizing a ssd1306 or
> ssd1307 controller. My primary and only target device is a Newhaven
> NHD-3.12-25664UCB2 OLED display module using an SSD1305 controller. I
> just inferred from the datasheets of ssd1306/7 [1,2] that they should
> behave the same since the registers are bit to bit identical (except
> for the VHCOM register). Maybe that was a bit too naive :/

I would guess it's a rather safe assumption.

> > The 1306 for example seems to not be using these values at all, while
> > the 1307 does.
> 
> That is surprising. In that case I would like to ask the guys from
> Solomon why they describe all these options in the SSD1306 datasheet
> [1]. But in any case, isn't that good news for the problem of setting
> the default values. When the 1306 isn't using these values anyway we can
> not break the initialization by setting different default values. In
> this case the problem of the default values boils down to the segment
> remap only since this is set in the init code of the 1307, while the
> default would be to leave it off.

Indeed.

> > > Unfortunately the current sate of the initialization code of the
> > > ssd1307fb driver is not very flexible in that respect. Taking a look
> > > at the initialization code for the ssd1306 shows that it was written
> > > with one very special display module in mind. Most of the magic bit
> > > values set there are non-default values according to the
> > > datasheet. The result is that the driver works with that one
> > > particular display module but many other (differently wired) display
> > > modules using a ssd1306 controller won't work without changing the
> > > hardcoded magic bit values.
> > > 
> > > My idea here was to set all configuration to the default values (as
> > > given in the datasheet) unless it is overwritten by DT. Of course,
> > > without a change in DT, this breaks the driver for all existing
> > > users. The only alternative would be to set the current values as
> > > default. Somehow this feels wrong to me as these values look
> > > arbitrary when you don't know what exact display module they were
> > > set for. But if you insist, I will change the default values.
> > 
> > Unfortunately, the DT bindings are to be considered an ABI, and we
> > should support booting with older DTs (not that I personally care
> > about it, but that's another issue). So we really don't have much
> > choice here.
> > 
> > Moreover, that issue left aside, modifying bindings like this without
> > fixing up the in-tree users is considered quite rude :)
> 
> I didn't intend to be rude, sorry. A quick search revealed that there
> is luckily only one in-tree user, which is imx28-cfa10036.dts. In case
> it will be necessary I will include a patch to fix this.

Please do (and fix the bindings Documentation too).

> > > > and the DT itself should not contain any direct mapping of the
> > > > registers.
> > > > 
> > > 
> > > I think I don't get what you mean here. Is it because I do no sanity
> > > checks of the numbers set in DT? I was just looking for a way to
> > > hand over the information about the wiring of display to the
> > > driver. How would you propose to solve this?
> > 
> > What I meant was that replicating direct registers value is usually a
> > recipe for a later failure, especially if we can have the information
> > under a generic and easy to understand manner.
> > 
> > For example, replacing the solomon,dclk-div and solomon,dclk-frq
> > properties by a clock-frequency property in Hz, and computing the
> > divider and that register in your driver is usually better, also
> > because it allows to have different requirements / algorithms to
> > compute that if some other chip needs it.
> 
> I'll give that a try, even though that particular one is not trivial
> since the documentation on the actual frequency that is set by the
> dclk-freq is very poor (not present for 1306/1307 [1,2], just a graph
> for 1305 [0]).
> 
> For the properties describing the hardware pin configuration (see above)
> I see no real alternative. Maybe they can all be covered by one DT
> property like:
> solomon,com-cfg = PINCFG_SEGREMAP | PINCFG_COMALT | PINCFG_COMINV |
> PINCFG_COMLRRM
> each PINCFG_* setting one bit. The driver will then translate this into
> the correct settings for the 130X registers. The only problem here is
> that this implicitly assumes the default values of each bit to be 0.

A property that would be here or not is better. You can have all the
defaults you want, it's more clear in the DT, and you don't need the
macros.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (7 preceding siblings ...)
  2015-02-06 22:28 ` [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload niederp
@ 2015-03-01 22:27 ` Thomas Niederprüm
  2015-03-01 22:27   ` [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
                     ` (9 more replies)
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                   ` (3 subsequent siblings)
  12 siblings, 10 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch series is the result of making the ssd1307fb driver work with
a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
this the intialization code for the SSD1306 and the SSD1307 is merged
and based on DT configuration to reflect to various possible wirings
of the SSD130X controller (04/10). Based on these changes it is straight
forward to add support for the SSD1305 controller (05/10).

While working on the driver I realized that it was not possible to
correctly mmap the video memory from userspace since the address handed
to the userspace app is a virtual one where it should be a physical one.
Patch 01/10 fixes this. Furthermore the memory reserved by kzalloc is
not page aligned while the address handed to userspace is aligned to the
next page frame. This problem is fixed by using vmalloc in 02/10.

Furthermore module parameters are added to set the bits per pixel
and the delay for the deferred io update. It makes sense to set
the bits per pixel for the video memory to 8 bits since there is
only very poor userspace support for 1 bit framebuffers.

Also sysfs handles are added to make the contrast settings and dim
mode setting available in userspace.

changes since v1 (thanks to Maxime for the feedback):
- dedicated patch for fixing smem_start address
- remove page reserve upon vmalloc
- remove return value check upon display turn-off at module unload
- use a module parameter refreshrate rather than delaydivider
- allocate fbdefio dynamically
- use sysfs_create_groups to create sysfs entries
- remove contrast, vhcom and dclk properties from DT since they are
  not part of hw description. The contrast module parameter was added
  to set contrast at load time. vhcom and dclk stays at it's default
  values for now.
- add new DT properties to in tree users of ssd130X
- rebased to apply on top of linux-nextThis patch series is the result of making the ssd1307fb driver work with

Thomas Niederprüm (10):
  fbdev: ssd1307fb: fix memory address smem_start.
  fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  Documentation: dts: add missing Solomon Systech vendor prefix.
  fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  fbdev: ssd1307fb: fix in tree users of ssd1306
  fbdev: ssd1307fb: Add support for SSD1305
  fbdev: ssd1307fb: Add module parameter to set refresh rate of the
    display
  fbdev: ssd1307fb: Add module parameter bitsperpixel.
  fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting
    to userspace.
  fbdev: ssd1307fb: Turn off display on driver unload.

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../devicetree/bindings/video/ssd1307fb.txt        |  24 +-
 arch/arm/boot/dts/imx28-cfa10036.dts               |   4 +
 drivers/video/fbdev/ssd1307fb.c                    | 354 +++++++++++++++------
 4 files changed, 286 insertions(+), 97 deletions(-)

-- 
2.3.0


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

* [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start.
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-01 22:27   ` Thomas Niederprüm
  2015-03-03  7:17     ` Maxime Ripard
  2015-03-01 22:27   ` [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

the smem_start pointer of the framebuffer info struct needs to hold the
physical address rather than the virtual address. This patch fixes a
driver crash on mmaping the framebuffer memory due to an access to the
memory address.

Note however that the memory allocated by kzalloc is not page aligned,
while the address presented on a mmap call is aligned to the next page
boudary.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f7ed6d9..61e0ce8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -515,7 +515,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
 	fb_deferred_io_init(info);
-- 
2.3.0


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

* [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-01 22:27   ` [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
@ 2015-03-01 22:27   ` Thomas Niederprüm
  2015-03-03  8:52     ` Maxime Ripard
  2015-03-01 22:27   ` [PATCHv2 03/10] Documentation: dts: add missing Solomon Systech vendor prefix Thomas Niederprüm
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

It makes sense to use vmalloc to allocate the video buffer since it has to be
page aligned memory for using it with mmap. Also deffered io seems buggy in
combination with kmalloc'ed memory (crash on unloading the module).

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 61e0ce8..25dd08d 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/fb.h>
 #include <linux/uaccess.h>
+#include <linux/vmalloc.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/pwm.h>
@@ -489,7 +490,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	vmem_size = par->width * par->height / 8;
 
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	vmem = vzalloc(vmem_size);
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -559,6 +560,7 @@ panel_init_error:
 		par->ops->remove(par);
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
+	vfree(vmem);
 fb_alloc_error:
 	framebuffer_release(info);
 	return ret;
-- 
2.3.0


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

* [PATCHv2 03/10] Documentation: dts: add missing Solomon Systech vendor prefix.
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-01 22:27   ` [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
  2015-03-01 22:27   ` [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
@ 2015-03-01 22:27   ` Thomas Niederprüm
  2015-03-01 22:27   ` [PATCHv2 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the solomon prefix for Solomon Systech Limited.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d3f4809..933c8f5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -169,6 +169,7 @@ sitronix	Sitronix Technology Corporation
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
+solomon        Solomon Systech Limited
 sony	Sony Corporation
 spansion	Spansion Inc.
 sprd	Spreadtrum Communications Inc.
-- 
2.3.0


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

* [PATCHv2 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (2 preceding siblings ...)
  2015-03-01 22:27   ` [PATCHv2 03/10] Documentation: dts: add missing Solomon Systech vendor prefix Thomas Niederprüm
@ 2015-03-01 22:27   ` Thomas Niederprüm
  2015-03-05 21:49     ` Maxime Ripard
  2015-03-01 22:27   ` [PATCHv2 05/10] fbdev: ssd1307fb: fix in tree users of ssd1306 Thomas Niederprüm
                     ` (5 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The SSD130X controllers are very similar from the configuration point of view.
The configuration registers for the SSD1305/6/7 are bit identical (except the
the VHCOM register and the the default values for clock setup register). This
patch unifies the init code of the controller and adds hardware specific
properties to DT that are needed to correctly initialize the device.

The SSD130X can be wired to the OLED panel in various ways. Even for the
same controller this wiring can differ from one display module to another
and can not be probed by software. The added DT properties reflect these
hardware decisions of the display module manufacturer.
The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
possibilities for the COM signals pin configuration and readout direction
of the video memory. The 'segment-remap' allows the inversion of the memory-
to-pin mapping ultimately inverting the order of the controllers output pins.
The 'prechargepX' values need to be adapted according the capacitance of the
OLEDs pixel cells.

So far these hardware specific bits are hard coded in the init code, making
the driver usable only for one certain wiring of the controller. This patch
makes the driver usable with all possible hardware setups, given a valid hw
description in DT. If the values are not set in DT the default values
according to the controllers datasheet are assumed. This implies that this
patch changes the existing behaviour with respect to the segment remap for
the SSD1307 when the corresponding property is not present in DT. The example
in the DT bindings documentation is updated to reflect this change.

Note that the SSD1306 does not seem to be using the configuration written to
the registers at all. Nevertheless an example is added to the DT bindings
documentation that would lead to the same configuration as the current init
code.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 .../devicetree/bindings/video/ssd1307fb.txt        |  22 +++
 drivers/video/fbdev/ssd1307fb.c                    | 195 ++++++++++++---------
 2 files changed, 138 insertions(+), 79 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 7a12542..6bdd69b 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -15,6 +15,15 @@ Required properties:
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
+  - solomon,segment-remap: Display needs inverted data column to segment mapping
+  - solomon,com-sequential: Display uses sequential COM pin configuration
+  - solomon,com-lrremap: Display uses left-right COM pin remap
+  - solomon,com-invdir: Display uses inverted COM pin scan direction
+  - solomon,com-offset: Offset of the first COM pin wired to the panel
+  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
+  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
+                         This needs to be the higher, the higher the capacitance
+                         of the OLED's pixels is
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -25,4 +34,17 @@ ssd1307: oled@3c {
         pwms = <&pwm 4 3000>;
         reset-gpios = <&gpio2 7>;
         reset-active-low;
+        solomon,segment-remap;
+};
+
+ssd1306: oled@3c {
+        compatible = "solomon,ssd1306fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+        solomon,segment-remap;
+        solomon,com-lrremap;
+        solomon,com-invdir;
+        solomon,com-offset = <32>;
 };
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 25dd08d..b4880c0 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -17,6 +17,9 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1306 6
+#define DEVID_SSD1307 7
+
 #define SSD1307FB_DATA			0x40
 #define SSD1307FB_COMMAND		0x80
 
@@ -39,22 +42,38 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+static u_int contrast = 128;
+module_param(contrast, uint, S_IRUGO);
+
 struct ssd1307fb_par;
 
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
+struct ssd1307fb_deviceinfo {
+	int device_id;
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
 };
 
 struct ssd1307fb_par {
+	u32 com_invdir;
+	u32 com_lrremap;
+	u32 com_offset;
+	u32 com_seq;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	struct ssd1307fb_deviceinfo *device_info;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
 	u32 page_offset;
+	u32 prechargep1;
+	u32 prechargep2;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 seg_remap;
+	u32 vcomh;
 	u32 width;
 };
 
@@ -255,69 +274,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
+	u32 precharge, dclk, com_invdir, compins;
 
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		par->pwm = pwm_get(&par->client->dev, NULL);
+		if (IS_ERR(par->pwm)) {
+			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+			return PTR_ERR(par->pwm);
+		}
 
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
+		par->pwm_period = pwm_get_period(par->pwm);
+		/* Enable the PWM */
+		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+		pwm_enable(par->pwm);
 
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
+		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+			par->pwm->pwm, par->pwm_period);
+	};
 
 	/* Set initial contrast */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x7f);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
 	if (ret < 0)
 		return ret;
 
 	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (par->seg_remap) {
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	};
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
+	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
 	if (ret < 0)
 		return ret;
 
@@ -335,34 +331,38 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
 	if (ret < 0)
 		return ret;
 
 	/* Set clock frequency */
+	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0xf0);
+	ret = ssd1307fb_write_cmd(par->client, dclk);
 	if (ret < 0)
 		return ret;
 
 	/* Set precharge period in number of ticks from the internal clock */
+	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	ret = ssd1307fb_write_cmd(par->client, precharge);
 	if (ret < 0)
 		return ret;
 
 	/* Set COM pins configuration */
+	compins = 0x02 | (!par->com_seq & 0x1) << 4
+				   | (par->com_lrremap & 0x1) << 5;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	ret = ssd1307fb_write_cmd(par->client, compins);
 	if (ret < 0)
 		return ret;
 
@@ -371,18 +371,20 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x49);
+	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
 	if (ret < 0)
 		return ret;
 
-	/* Turn on the DC-DC Charge Pump */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
-	if (ret < 0)
-		return ret;
+	if (par->device_info->device_id == DEVID_SSD1306) {
+		/* Turn on the DC-DC Charge Pump */
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+		if (ret < 0)
+			return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x14);
-	if (ret < 0)
-		return ret;
+		ret = ssd1307fb_write_cmd(par->client, 0x14);
+		if (ret < 0)
+			return ret;
+	};
 
 	/* Switch to horizontal addressing mode */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
@@ -394,6 +396,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+    /* Set column range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
 	if (ret < 0)
 		return ret;
@@ -406,6 +409,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+    /* Set page range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
 	if (ret < 0)
 		return ret;
@@ -427,18 +431,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
+	.device_id  = DEVID_SSD1306,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 8,
+};
+
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
+	.device_id  = DEVID_SSD1307,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 12,
 };
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
 		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
+		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
 	{
 		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
+		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
 	},
 	{},
 };
@@ -469,8 +483,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->info = info;
 	par->client = client;
 
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
+	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
+			ssd1307fb_of_match, &client->dev)->data;
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
@@ -488,6 +502,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
 		par->page_offset = 1;
 
+	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
+		par->com_offset = 0;
+
+	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
+		par->prechargep1 = 2;
+
+	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
+		par->prechargep2 = 0;
+
+	par->seg_remap = of_property_read_bool(node, "solomon,segment-remap");
+	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
+	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
+	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
+
+	par->contrast = contrast;
+	par->vcomh = par->device_info->default_vcomh;
+
+	/* Setup display timing */
+	par->dclk_div = par->device_info->default_dclk_div;
+	par->dclk_frq = par->device_info->default_dclk_frq;
+
 	vmem_size = par->width * par->height / 8;
 
 	vmem = vzalloc(vmem_size);
@@ -539,11 +574,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	gpio_set_value(par->reset, 1);
 	udelay(4);
 
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
+	ret = ssd1307fb_init(par);
+	if (ret)
+		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
 	if (ret) {
@@ -556,8 +589,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	return 0;
 
 panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 	vfree(vmem);
@@ -572,8 +607,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 	fb_deferred_io_cleanup(info);
 	framebuffer_release(info);
 
-- 
2.3.0


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

* [PATCHv2 05/10] fbdev: ssd1307fb: fix in tree users of ssd1306
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (3 preceding siblings ...)
  2015-03-01 22:27   ` [PATCHv2 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-01 22:27   ` Thomas Niederprüm
  2015-03-03  9:31     ` Maxime Ripard
  2015-03-01 22:27   ` [PATCHv2 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
                     ` (4 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

introducing the new DT properties the in tree users of the SSD1306
controller are updated to be up to date.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 arch/arm/boot/dts/imx28-cfa10036.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index b04b6b8..faeaa2e 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -99,6 +99,10 @@
 					solomon,height = <32>;
 					solomon,width = <128>;
 					solomon,page-offset = <0>;
+					solomon,segment-remap;
+					solomon,com-lrremap;
+					solomon,com-invdir;
+					solomon,com-offset = <32>;
 				};
 			};
 
-- 
2.3.0


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

* [PATCHv2 06/10] fbdev: ssd1307fb: Add support for SSD1305
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (4 preceding siblings ...)
  2015-03-01 22:27   ` [PATCHv2 05/10] fbdev: ssd1307fb: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-03-01 22:27   ` Thomas Niederprüm
  2015-03-01 22:28   ` [PATCHv2 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds support for the SSD1305 OLED controller.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/video/ssd1307fb.txt |  2 +-
 drivers/video/fbdev/ssd1307fb.c                       | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 6bdd69b..115cd43 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -2,7 +2,7 @@
 
 Required properties:
   - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
-    now is i2c, and the supported chips are ssd1306 and ssd1307.
+    now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307.
   - reg: Should contain address of the controller on the I2C bus. Most likely
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index b4880c0..c7ed287 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -17,6 +17,7 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1305 5
 #define DEVID_SSD1306 6
 #define DEVID_SSD1307 7
 
@@ -431,6 +432,13 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
+	.device_id  = DEVID_SSD1305,
+	.default_vcomh = 0x34,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 7,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
 	.device_id  = DEVID_SSD1306,
 	.default_vcomh = 0x20,
@@ -447,6 +455,10 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1305_deviceinfo,
+	},
+	{
 		.compatible = "solomon,ssd1306fb-i2c",
 		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
@@ -618,6 +630,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1305fb", 0 },
 	{ "ssd1306fb", 0 },
 	{ "ssd1307fb", 0 },
 	{ }
-- 
2.3.0


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

* [PATCHv2 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (5 preceding siblings ...)
  2015-03-01 22:27   ` [PATCHv2 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
@ 2015-03-01 22:28   ` Thomas Niederprüm
  2015-03-05 22:12     ` Maxime Ripard
  2015-03-01 22:28   ` [PATCHv2 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel Thomas Niederprüm
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:28 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the module parameter "refreshrate" to set delay for the
deferred io. The refresh rate is given in units of Hertz. The default
refresh rate is 1 Hz.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index c7ed287..ea58e87 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -43,6 +43,11 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define REFRASHRATE 1
+
+static u_int refreshrate = REFRASHRATE;
+module_param(refreshrate, uint, 0);
+
 static u_int contrast = 128;
 module_param(contrast, uint, S_IRUGO);
 
@@ -270,11 +275,6 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 	ssd1307fb_update_display(info->par);
 }
 
-static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
-	.deferred_io	= ssd1307fb_deferred_io,
-};
-
 static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
@@ -475,6 +475,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 {
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
+	struct fb_deferred_io *ssd1307fb_defio;
 	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
@@ -544,10 +545,20 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto fb_alloc_error;
 	}
 
+	ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
+	if (!ssd1307fb_defio) {
+		dev_err(&client->dev, "Couldn't allocate deferred io.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	ssd1307fb_defio->delay = HZ/refreshrate;
+	ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io;
+
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
 	info->fix.line_length = par->width / 8;
-	info->fbdefio = &ssd1307fb_defio;
+	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
 	info->var.xres = par->width;
-- 
2.3.0


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

* [PATCHv2 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (6 preceding siblings ...)
  2015-03-01 22:28   ` [PATCHv2 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
@ 2015-03-01 22:28   ` Thomas Niederprüm
  2015-03-01 22:28   ` [PATCHv2 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace Thomas Niederprüm
  2015-03-01 22:28   ` [PATCHv2 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:28 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds a module parameter 'bitsperpixel' to adjust the colordepth
of the framebuffer. All values >1 will result in memory map of the requested
color depth. However only the MSB of each pixel will be sent to the device.
The framebuffer identifies itself as a grayscale display with the specified
depth.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index ea58e87..5bf570b 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -44,6 +44,10 @@
 #define	SSD1307FB_SET_VCOMH		0xdb
 
 #define REFRASHRATE 1
+#define BITSPERPIXEL 1
+
+static u_int bitsperpixel = BITSPERPIXEL;
+module_param(bitsperpixel, uint, 0);
 
 static u_int refreshrate = REFRASHRATE;
 module_param(refreshrate, uint, 0);
@@ -99,7 +103,8 @@ static struct fb_fix_screeninfo ssd1307fb_fix = {
 };
 
 static struct fb_var_screeninfo ssd1307fb_var = {
-	.bits_per_pixel	= 1,
+	.bits_per_pixel	= BITSPERPIXEL,
+	.grayscale = 1,
 };
 
 static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
@@ -194,10 +199,11 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
 			array->data[array_idx] = 0;
 			for (k = 0; k < 8; k++) {
 				u32 page_length = par->width * i;
-				u32 index = page_length + (par->width * k + j) / 8;
+				u32 index = page_length * bitsperpixel + (par->width * k + j) * bitsperpixel / 8;
 				u8 byte = *(vmem + index);
-				u8 bit = byte & (1 << (j % 8));
-				bit = bit >> (j % 8);
+				u8 bit = byte & (((1 << (bitsperpixel))-1) << (j % 8/bitsperpixel));
+
+				bit = (bit >> (j % 8/bitsperpixel)) >> (bitsperpixel-1);
 				array->data[array_idx] |= bit << k;
 			}
 		}
@@ -536,7 +542,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->dclk_div = par->device_info->default_dclk_div;
 	par->dclk_frq = par->device_info->default_dclk_frq;
 
-	vmem_size = par->width * par->height / 8;
+	vmem_size = par->width * par->height * bitsperpixel / 8;
 
 	vmem = vzalloc(vmem_size);
 	if (!vmem) {
@@ -557,20 +563,21 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
-	info->fix.line_length = par->width / 8;
+	info->fix.line_length = par->width * bitsperpixel / 8;
 	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
+	info->var.bits_per_pixel = bitsperpixel;
 	info->var.xres = par->width;
 	info->var.xres_virtual = par->width;
 	info->var.yres = par->height;
 	info->var.yres_virtual = par->height;
 
-	info->var.red.length = 1;
+	info->var.red.length = bitsperpixel;
 	info->var.red.offset = 0;
-	info->var.green.length = 1;
+	info->var.green.length = bitsperpixel;
 	info->var.green.offset = 0;
-	info->var.blue.length = 1;
+	info->var.blue.length = bitsperpixel;
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-- 
2.3.0


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

* [PATCHv2 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (7 preceding siblings ...)
  2015-03-01 22:28   ` [PATCHv2 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel Thomas Niederprüm
@ 2015-03-01 22:28   ` Thomas Niederprüm
  2015-03-01 22:28   ` [PATCHv2 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:28 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds sysfs handles to enable userspace control over the display
contrast as well as the dim mode. The handles are available as "contrast"
and "dim" in the brightness group of the framebuffers sysfs domain.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 90 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 5bf570b..2a2e7c3 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -33,6 +33,7 @@
 #define SSD1307FB_CONTRAST		0x81
 #define	SSD1307FB_CHARGE_PUMP		0x8d
 #define SSD1307FB_SEG_REMAP_ON		0xa1
+#define SSD1307FB_DISPLAY_DIM		0xac
 #define SSD1307FB_DISPLAY_OFF		0xae
 #define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
 #define SSD1307FB_DISPLAY_ON		0xaf
@@ -43,6 +44,9 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define MIN_CONTRAST 0
+#define MAX_CONTRAST 255
+
 #define REFRASHRATE 1
 #define BITSPERPIXEL 1
 
@@ -73,6 +77,7 @@ struct ssd1307fb_par {
 	u32 dclk_div;
 	u32 dclk_frq;
 	struct ssd1307fb_deviceinfo *device_info;
+	u32 dim;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
@@ -476,6 +481,87 @@ static const struct of_device_id ssd1307fb_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 
+static ssize_t show_contrast(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->contrast);
+}
+
+static ssize_t store_contrast(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+	unsigned long contrastval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &contrastval);
+	if (ret < 0)
+		return ret;
+
+	par->contrast = max_t(ulong, min_t(ulong, contrastval,
+		(ulong)MAX_CONTRAST), (ulong)MIN_CONTRAST);
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->contrast);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+
+static ssize_t show_dim(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->dim);
+}
+
+static ssize_t store_dim(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+	unsigned long dimval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &dimval);
+	if (ret < 0)
+		return ret;
+
+	par->dim = max_t(ulong, min_t(ulong, dimval, (ulong)1), (ulong)0);
+	if (par->dim)
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_DIM);
+	else
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast, store_contrast);
+static DEVICE_ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim);
+
+static struct attribute *panel_attrs[] = {
+		&dev_attr_contrast.attr,
+		&dev_attr_dim.attr,
+		NULL,
+};
+
+static struct attribute_group brightness_attr_grp = {
+		.name  = "brightness",
+		.attrs = panel_attrs,
+};
+
 static int ssd1307fb_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
@@ -614,6 +700,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto panel_init_error;
 	}
 
+	ret = sysfs_create_group(&info->dev->kobj, &brightness_attr_grp);
+	if (ret)
+		dev_err(&client->dev, "Couldn't register sysfs nodes\n");
+
 	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
 
 	return 0;
-- 
2.3.0


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

* [PATCHv2 10/10] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (8 preceding siblings ...)
  2015-03-01 22:28   ` [PATCHv2 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace Thomas Niederprüm
@ 2015-03-01 22:28   ` Thomas Niederprüm
  2015-03-03  9:40     ` Maxime Ripard
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-01 22:28 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch turns off the display when the driver is unloaded.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 2a2e7c3..3b7a69f 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -726,6 +726,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct fb_info *info = i2c_get_clientdata(client);
 	struct ssd1307fb_par *par = info->par;
 
+	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+
 	unregister_framebuffer(info);
 	if (par->device_info->device_id == DEVID_SSD1307) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* Re: [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start.
  2015-03-01 22:27   ` [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
@ 2015-03-03  7:17     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-03  7:17 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

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

On Sun, Mar 01, 2015 at 11:27:54PM +0100, Thomas Niederprüm wrote:
> the smem_start pointer of the framebuffer info struct needs to hold the
> physical address rather than the virtual address. This patch fixes a
> driver crash on mmaping the framebuffer memory due to an access to the
> memory address.
> 
> Note however that the memory allocated by kzalloc is not page aligned,
> while the address presented on a mmap call is aligned to the next page
> boudary.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-01 22:27   ` [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
@ 2015-03-03  8:52     ` Maxime Ripard
  2015-03-03 19:04       ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-03-03  8:52 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

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

Hi,

On Sun, Mar 01, 2015 at 11:27:55PM +0100, Thomas Niederprüm wrote:
> It makes sense to use vmalloc to allocate the video buffer since it has to be
> page aligned memory for using it with mmap. Also deffered io seems buggy in
> combination with kmalloc'ed memory (crash on unloading the module).
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 61e0ce8..25dd08d 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -11,6 +11,7 @@
>  #include <linux/i2c.h>
>  #include <linux/fb.h>
>  #include <linux/uaccess.h>
> +#include <linux/vmalloc.h>
>  #include <linux/of_device.h>
>  #include <linux/of_gpio.h>
>  #include <linux/pwm.h>
> @@ -489,7 +490,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  
>  	vmem_size = par->width * par->height / 8;
>  
> -	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
> +	vmem = vzalloc(vmem_size);
>  	if (!vmem) {
>  		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
>  		ret = -ENOMEM;
> @@ -559,6 +560,7 @@ panel_init_error:
>  		par->ops->remove(par);
>  reset_oled_error:
>  	fb_deferred_io_cleanup(info);
> +	vfree(vmem);
>  fb_alloc_error:
>  	framebuffer_release(info);
>  	return ret;

Don't you need the vfree in the remove too?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv2 05/10] fbdev: ssd1307fb: fix in tree users of ssd1306
  2015-03-01 22:27   ` [PATCHv2 05/10] fbdev: ssd1307fb: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-03-03  9:31     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-03  9:31 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

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

On Sun, Mar 01, 2015 at 11:27:58PM +0100, Thomas Niederprüm wrote:
> introducing the new DT properties the in tree users of the SSD1306
> controller are updated to be up to date.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

This should be prefixed by "ARM: mxs:", and sent to the MXS
maintainers.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv2 10/10] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-03-01 22:28   ` [PATCHv2 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
@ 2015-03-03  9:40     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-03  9:40 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

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

On Sun, Mar 01, 2015 at 11:28:03PM +0100, Thomas Niederprüm wrote:
> This patch turns off the display when the driver is unloaded.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-03  8:52     ` Maxime Ripard
@ 2015-03-03 19:04       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-03 19:04 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

Am Tue, 3 Mar 2015 09:52:55 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> Hi,
> 
> On Sun, Mar 01, 2015 at 11:27:55PM +0100, Thomas Niederprüm wrote:
> > It makes sense to use vmalloc to allocate the video buffer since it
> > has to be page aligned memory for using it with mmap. Also deffered
> > io seems buggy in combination with kmalloc'ed memory (crash on
> > unloading the module).
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  drivers/video/fbdev/ssd1307fb.c | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 61e0ce8..25dd08d 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -11,6 +11,7 @@
> >  #include <linux/i2c.h>
> >  #include <linux/fb.h>
> >  #include <linux/uaccess.h>
> > +#include <linux/vmalloc.h>
> >  #include <linux/of_device.h>
> >  #include <linux/of_gpio.h>
> >  #include <linux/pwm.h>
> > @@ -489,7 +490,7 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, 
> >  	vmem_size = par->width * par->height / 8;
> >  
> > -	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
> > +	vmem = vzalloc(vmem_size);
> >  	if (!vmem) {
> >  		dev_err(&client->dev, "Couldn't allocate graphical
> > memory.\n"); ret = -ENOMEM;
> > @@ -559,6 +560,7 @@ panel_init_error:
> >  		par->ops->remove(par);
> >  reset_oled_error:
> >  	fb_deferred_io_cleanup(info);
> > +	vfree(vmem);
> >  fb_alloc_error:
> >  	framebuffer_release(info);
> >  	return ret;
> 
> Don't you need the vfree in the remove too?

Yes, of course. Memory will be freed in v3

> 
> Maxime
> 


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

* Re: [PATCHv2 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-01 22:27   ` [PATCHv2 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-05 21:49     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-05 21:49 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

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

On Sun, Mar 01, 2015 at 11:27:57PM +0100, Thomas Niederprüm wrote:
> The SSD130X controllers are very similar from the configuration point of view.
> The configuration registers for the SSD1305/6/7 are bit identical (except the
> the VHCOM register and the the default values for clock setup register). This
> patch unifies the init code of the controller and adds hardware specific
> properties to DT that are needed to correctly initialize the device.
> 
> The SSD130X can be wired to the OLED panel in various ways. Even for the
> same controller this wiring can differ from one display module to another
> and can not be probed by software. The added DT properties reflect these
> hardware decisions of the display module manufacturer.
> The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
> possibilities for the COM signals pin configuration and readout direction
> of the video memory. The 'segment-remap' allows the inversion of the memory-
> to-pin mapping ultimately inverting the order of the controllers output pins.
> The 'prechargepX' values need to be adapted according the capacitance of the
> OLEDs pixel cells.
> 
> So far these hardware specific bits are hard coded in the init code, making
> the driver usable only for one certain wiring of the controller. This patch
> makes the driver usable with all possible hardware setups, given a valid hw
> description in DT. If the values are not set in DT the default values
> according to the controllers datasheet are assumed.

Unfortunately, this is not a reasonable thing to do, even if you fix
the existing user, there's still the case where you have an older DT
with a newer kernel.

Keeping (and documenting) the previous defaults is the only easy way
to support this.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv2 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display
  2015-03-01 22:28   ` [PATCHv2 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
@ 2015-03-05 22:12     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-05 22:12 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, linux-fbdev, linux-kernel

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

On Sun, Mar 01, 2015 at 11:28:00PM +0100, Thomas Niederprüm wrote:
> This patch adds the module parameter "refreshrate" to set delay for the
> deferred io. The refresh rate is given in units of Hertz. The default
> refresh rate is 1 Hz.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index c7ed287..ea58e87 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -43,6 +43,11 @@
>  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
>  #define	SSD1307FB_SET_VCOMH		0xdb
>  
> +#define REFRASHRATE 1
> +
> +static u_int refreshrate = REFRASHRATE;
> +module_param(refreshrate, uint, 0);
> +
>  static u_int contrast = 128;
>  module_param(contrast, uint, S_IRUGO);
>  
> @@ -270,11 +275,6 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
>  	ssd1307fb_update_display(info->par);
>  }
>  
> -static struct fb_deferred_io ssd1307fb_defio = {
> -	.delay		= HZ,
> -	.deferred_io	= ssd1307fb_deferred_io,
> -};
> -
>  static int ssd1307fb_init(struct ssd1307fb_par *par)
>  {
>  	int ret;
> @@ -475,6 +475,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  {
>  	struct fb_info *info;
>  	struct device_node *node = client->dev.of_node;
> +	struct fb_deferred_io *ssd1307fb_defio;
>  	u32 vmem_size;
>  	struct ssd1307fb_par *par;
>  	u8 *vmem;
> @@ -544,10 +545,20 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  		goto fb_alloc_error;
>  	}
>  
> +	ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
> +	if (!ssd1307fb_defio) {
> +		dev_err(&client->dev, "Couldn't allocate deferred io.\n");
> +		ret = -ENOMEM;
> +		goto fb_alloc_error;
> +	}
> +
> +	ssd1307fb_defio->delay = HZ/refreshrate;

a space around the operator.

I'm not so sure this is a good solution, since you might perfectly
want to have an SSD1305 with a refreshrate of 1Hz, and an SSD1306 with
a refreshrate of 20Hz.

Unfortunately, beside sysfs, I don't really have a better suggestion.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (8 preceding siblings ...)
  2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-09 22:22 ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
                     ` (9 more replies)
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                   ` (2 subsequent siblings)
  12 siblings, 10 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch series is the result of making the ssd1307fb driver work with
a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
this the intialization code for the SSD1306 and the SSD1307 is merged
and based on DT configuration to reflect the various possible wirings
of the SSD130X controller (04/10). Based on these changes it is straight
forward to add support for the SSD1305 controller (06/10).

While working on the driver I realized that it was not possible to
correctly mmap the video memory from userspace since the address handed
to the userspace app is a virtual one where it should be a physical one.
Patch 01/10 fixes this. Furthermore the memory reserved by kzalloc is
not page aligned while the address handed to userspace is aligned to the
next page frame. This problem is fixed by using vmalloc in 02/10.

Furthermore module parameters are added to set the bits per pixel
and the delay for the deferred io update. It makes sense to set
the bits per pixel for the video memory to 8 bits since there is
only very poor userspace support for 1 bit framebuffers.

Also sysfs handles are added to make the contrast settings and dim
mode setting available in userspace.

changes since v1 (thanks to Maxime for the feedback):
- dedicated patch for fixing smem_start address
- remove page reserve upon vmalloc
- remove return value check upon display turn-off at module unload
- use a module parameter refreshrate rather than delaydivider
- allocate fbdefio dynamically
- use sysfs_create_groups to create sysfs entries
- remove contrast, vhcom and dclk properties from DT since they are
  not part of hw description. The contrast module parameter was added
  to set contrast at load time. vhcom and dclk stays at it's default
  values for now.
- add new DT properties to in tree users of ssd130X
- rebased to apply on top of linux-next

changes since v2 (thanks to Maxime again):
- free memory allocated by vmalloc on driver unload
- set default values in the init code to the ones of the existing ssd1307
  init code
- added two ACKs (Maxime Ripard)

Thomas Niederprüm (10):
  fbdev: ssd1307fb: fix memory address smem_start.
  fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  of: Add Solomon Systech vendor prefix.
  fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  ARM: mxs: fix in tree users of ssd1306
  fbdev: ssd1307fb: Add support for SSD1305
  fbdev: ssd1307fb: Add module parameter to set refresh rate of the
    display
  fbdev: ssd1307fb: Add module parameter bitsperpixel.
  fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting
    to userspace.
  fbdev: ssd1307fb: Turn off display on driver unload.

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../devicetree/bindings/video/ssd1307fb.txt        |  23 +-
 arch/arm/boot/dts/imx28-cfa10036.dts               |   4 +
 drivers/video/fbdev/ssd1307fb.c                    | 355 +++++++++++++++------
 4 files changed, 286 insertions(+), 97 deletions(-)

-- 
2.3.0


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

* [PATCHv3 01/10] fbdev: ssd1307fb: fix memory address smem_start.
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

the smem_start pointer of the framebuffer info struct needs to hold the
physical address rather than the virtual address. This patch fixes a
driver crash on mmaping the framebuffer memory due to an access to the
memory address.

Note however that the memory allocated by kzalloc is not page aligned,
while the address presented on a mmap call is aligned to the next page
boudary.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f7ed6d9..61e0ce8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -515,7 +515,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
 	fb_deferred_io_init(info);
-- 
2.3.0


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

* [PATCHv3 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

It makes sense to use vmalloc to allocate the video buffer since it has to be
page aligned memory for using it with mmap. Also deffered io seems buggy in
combination with kmalloc'ed memory (crash on unloading the module).

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 61e0ce8..310474a 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/fb.h>
 #include <linux/uaccess.h>
+#include <linux/vmalloc.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/pwm.h>
@@ -489,7 +490,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	vmem_size = par->width * par->height / 8;
 
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	vmem = vzalloc(vmem_size);
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -559,6 +560,7 @@ panel_init_error:
 		par->ops->remove(par);
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
+	vfree(vmem);
 fb_alloc_error:
 	framebuffer_release(info);
 	return ret;
@@ -573,6 +575,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	if (par->ops->remove)
 		par->ops->remove(par);
 	fb_deferred_io_cleanup(info);
+	vfree(__va(info->fix.smem_start));
 	framebuffer_release(info);
 
 	return 0;
-- 
2.3.0


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

* [PATCHv3 03/10] of: Add Solomon Systech vendor prefix.
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the solomon prefix for Solomon Systech Limited.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d3f4809..933c8f5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -169,6 +169,7 @@ sitronix	Sitronix Technology Corporation
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
+solomon        Solomon Systech Limited
 sony	Sony Corporation
 spansion	Spansion Inc.
 sprd	Spreadtrum Communications Inc.
-- 
2.3.0


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

* [PATCHv3 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (2 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The 130X controllers are very similar from the configuration point of view.
The configuration registers for the SSD1305/6/7 are bit identical (except the
the VHCOM register and the the default values for clock setup register). This
patch unifies the init code of the controller and adds hardware specific
properties to DT that are needed to correctly initialize the device.

The SSD130X can be wired to the OLED panel in various ways. Even for the
same controller this wiring can differ from one display module to another
and can not be probed by software. The added DT properties reflect these
hardware decisions of the display module manufacturer.
The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
possibilities for the COM signals pin configuration and readout direction
of the video memory. The 'segment-no-remap' allows the inversion of the
memory-to-pin mapping ultimately inverting the order of the controllers
output pins. The 'prechargepX' values need to be adapted according the
capacitance of the OLEDs pixel cells.

So far these hardware specific bits are hard coded in the init code, making
the driver usable only for one certain wiring of the controller. This patch
makes the driver usable with all possible hardware setups, given a valid hw
description in DT. If these values are not set in DT the default values,
as they are set in the ssd1307 init code right now, are used. This implies
that without the corresponding DT property "segment-no-remap" the segment
remap of the ssd130X controller gets activated. Even though this is not the
default behaviour according to the datasheet it maintains backward
compatibility with older DTBs.

Note that the SSD1306 does not seem to be using the configuration written to
the registers at all. Therefore this patch does not try to maintain these
values without changes in DT. For reference an example is added to the DT
bindings documentation that reproduces the configuration that is set in the
current init code.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
 drivers/video/fbdev/ssd1307fb.c                    | 195 ++++++++++++---------
 2 files changed, 137 insertions(+), 79 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 7a12542..be27562 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -15,6 +15,16 @@ Required properties:
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
+  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
+                              to segment mapping
+  - solomon,com-sequential: Display uses sequential COM pin configuration
+  - solomon,com-lrremap: Display uses left-right COM pin remap
+  - solomon,com-invdir: Display uses inverted COM pin scan direction
+  - solomon,com-offset: Offset of the first COM pin wired to the panel
+  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
+  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
+                         This needs to be the higher, the higher the capacitance
+                         of the OLED's pixels is
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -26,3 +36,14 @@ ssd1307: oled@3c {
         reset-gpios = <&gpio2 7>;
         reset-active-low;
 };
+
+ssd1306: oled@3c {
+        compatible = "solomon,ssd1306fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+        solomon,com-lrremap;
+        solomon,com-invdir;
+        solomon,com-offset = <32>;
+};
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 310474a..b451361 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -17,6 +17,9 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1306 6
+#define DEVID_SSD1307 7
+
 #define SSD1307FB_DATA			0x40
 #define SSD1307FB_COMMAND		0x80
 
@@ -39,22 +42,38 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+static u_int contrast = 128;
+module_param(contrast, uint, S_IRUGO);
+
 struct ssd1307fb_par;
 
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
+struct ssd1307fb_deviceinfo {
+	int device_id;
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
 };
 
 struct ssd1307fb_par {
+	u32 com_invdir;
+	u32 com_lrremap;
+	u32 com_offset;
+	u32 com_seq;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	struct ssd1307fb_deviceinfo *device_info;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
 	u32 page_offset;
+	u32 prechargep1;
+	u32 prechargep2;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 seg_remap;
+	u32 vcomh;
 	u32 width;
 };
 
@@ -255,69 +274,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
+	u32 precharge, dclk, com_invdir, compins;
 
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		par->pwm = pwm_get(&par->client->dev, NULL);
+		if (IS_ERR(par->pwm)) {
+			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+			return PTR_ERR(par->pwm);
+		}
 
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
+		par->pwm_period = pwm_get_period(par->pwm);
+		/* Enable the PWM */
+		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+		pwm_enable(par->pwm);
 
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
+		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+			par->pwm->pwm, par->pwm_period);
+	};
 
 	/* Set initial contrast */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x7f);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
 	if (ret < 0)
 		return ret;
 
 	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (par->seg_remap) {
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	};
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
+	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
 	if (ret < 0)
 		return ret;
 
@@ -335,34 +331,38 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
 	if (ret < 0)
 		return ret;
 
 	/* Set clock frequency */
+	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0xf0);
+	ret = ssd1307fb_write_cmd(par->client, dclk);
 	if (ret < 0)
 		return ret;
 
 	/* Set precharge period in number of ticks from the internal clock */
+	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	ret = ssd1307fb_write_cmd(par->client, precharge);
 	if (ret < 0)
 		return ret;
 
 	/* Set COM pins configuration */
+	compins = 0x02 | (!par->com_seq & 0x1) << 4
+				   | (par->com_lrremap & 0x1) << 5;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	ret = ssd1307fb_write_cmd(par->client, compins);
 	if (ret < 0)
 		return ret;
 
@@ -371,18 +371,20 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x49);
+	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
 	if (ret < 0)
 		return ret;
 
-	/* Turn on the DC-DC Charge Pump */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
-	if (ret < 0)
-		return ret;
+	if (par->device_info->device_id == DEVID_SSD1306) {
+		/* Turn on the DC-DC Charge Pump */
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+		if (ret < 0)
+			return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x14);
-	if (ret < 0)
-		return ret;
+		ret = ssd1307fb_write_cmd(par->client, 0x14);
+		if (ret < 0)
+			return ret;
+	};
 
 	/* Switch to horizontal addressing mode */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
@@ -394,6 +396,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+    /* Set column range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
 	if (ret < 0)
 		return ret;
@@ -406,6 +409,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+    /* Set page range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
 	if (ret < 0)
 		return ret;
@@ -427,18 +431,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
+	.device_id  = DEVID_SSD1306,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 8,
+};
+
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
+	.device_id  = DEVID_SSD1307,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 12,
 };
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
 		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
+		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
 	{
 		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
+		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
 	},
 	{},
 };
@@ -469,8 +483,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->info = info;
 	par->client = client;
 
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
+	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
+			ssd1307fb_of_match, &client->dev)->data;
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
@@ -488,6 +502,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
 		par->page_offset = 1;
 
+	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
+		par->com_offset = 0;
+
+	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
+		par->prechargep1 = 2;
+
+	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
+		par->prechargep2 = 0;
+
+	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
+	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
+	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
+	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
+
+	par->contrast = contrast;
+	par->vcomh = par->device_info->default_vcomh;
+
+	/* Setup display timing */
+	par->dclk_div = par->device_info->default_dclk_div;
+	par->dclk_frq = par->device_info->default_dclk_frq;
+
 	vmem_size = par->width * par->height / 8;
 
 	vmem = vzalloc(vmem_size);
@@ -539,11 +574,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	gpio_set_value(par->reset, 1);
 	udelay(4);
 
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
+	ret = ssd1307fb_init(par);
+	if (ret)
+		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
 	if (ret) {
@@ -556,8 +589,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	return 0;
 
 panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 	vfree(vmem);
@@ -572,8 +607,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 	fb_deferred_io_cleanup(info);
 	vfree(__va(info->fix.smem_start));
 	framebuffer_release(info);
-- 
2.3.0


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

* [PATCHv3 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (3 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch updates the in tree-users of the SSD1306 controller for using
the newly introduced DT properties.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 arch/arm/boot/dts/imx28-cfa10036.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index b04b6b8..faeaa2e 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -99,6 +99,10 @@
 					solomon,height = <32>;
 					solomon,width = <128>;
 					solomon,page-offset = <0>;
+					solomon,segment-remap;
+					solomon,com-lrremap;
+					solomon,com-invdir;
+					solomon,com-offset = <32>;
 				};
 			};
 
-- 
2.3.0


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

* [PATCHv3 06/10] fbdev: ssd1307fb: Add support for SSD1305
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (4 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds support for the SSD1305 OLED controller.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/video/ssd1307fb.txt |  2 +-
 drivers/video/fbdev/ssd1307fb.c                       | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index be27562..a878fd2 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -2,7 +2,7 @@
 
 Required properties:
   - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
-    now is i2c, and the supported chips are ssd1306 and ssd1307.
+    now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307.
   - reg: Should contain address of the controller on the I2C bus. Most likely
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index b451361..08720be 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -17,6 +17,7 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1305 5
 #define DEVID_SSD1306 6
 #define DEVID_SSD1307 7
 
@@ -431,6 +432,13 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
+	.device_id  = DEVID_SSD1305,
+	.default_vcomh = 0x34,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 7,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
 	.device_id  = DEVID_SSD1306,
 	.default_vcomh = 0x20,
@@ -447,6 +455,10 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1305_deviceinfo,
+	},
+	{
 		.compatible = "solomon,ssd1306fb-i2c",
 		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
@@ -619,6 +631,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1305fb", 0 },
 	{ "ssd1306fb", 0 },
 	{ "ssd1307fb", 0 },
 	{ }
-- 
2.3.0


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

* [PATCHv3 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (5 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel Thomas Niederprüm
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the module parameter "refreshrate" to set delay for the
deferred io. The refresh rate is given in units of Hertz. The default
refresh rate is 1 Hz.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 08720be..7c8e627 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -43,6 +43,11 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define REFRASHRATE 1
+
+static u_int refreshrate = REFRASHRATE;
+module_param(refreshrate, uint, 0);
+
 static u_int contrast = 128;
 module_param(contrast, uint, S_IRUGO);
 
@@ -270,11 +275,6 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 	ssd1307fb_update_display(info->par);
 }
 
-static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
-	.deferred_io	= ssd1307fb_deferred_io,
-};
-
 static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
@@ -475,6 +475,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 {
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
+	struct fb_deferred_io *ssd1307fb_defio;
 	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
@@ -544,10 +545,20 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto fb_alloc_error;
 	}
 
+	ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
+	if (!ssd1307fb_defio) {
+		dev_err(&client->dev, "Couldn't allocate deferred io.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	ssd1307fb_defio->delay = HZ / refreshrate;
+	ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io;
+
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
 	info->fix.line_length = par->width / 8;
-	info->fbdefio = &ssd1307fb_defio;
+	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
 	info->var.xres = par->width;
-- 
2.3.0


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

* [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (6 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds a module parameter 'bitsperpixel' to adjust the colordepth
of the framebuffer. All values >1 will result in memory map of the requested
color depth. However only the MSB of each pixel will be sent to the device.
The framebuffer identifies itself as a grayscale display with the specified
depth.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 7c8e627..3cf4da1 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -44,6 +44,10 @@
 #define	SSD1307FB_SET_VCOMH		0xdb
 
 #define REFRASHRATE 1
+#define BITSPERPIXEL 1
+
+static u_int bitsperpixel = BITSPERPIXEL;
+module_param(bitsperpixel, uint, 0);
 
 static u_int refreshrate = REFRASHRATE;
 module_param(refreshrate, uint, 0);
@@ -99,7 +103,8 @@ static struct fb_fix_screeninfo ssd1307fb_fix = {
 };
 
 static struct fb_var_screeninfo ssd1307fb_var = {
-	.bits_per_pixel	= 1,
+	.bits_per_pixel	= BITSPERPIXEL,
+	.grayscale = 1,
 };
 
 static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
@@ -194,10 +199,11 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
 			array->data[array_idx] = 0;
 			for (k = 0; k < 8; k++) {
 				u32 page_length = par->width * i;
-				u32 index = page_length + (par->width * k + j) / 8;
+				u32 index = page_length * bitsperpixel + (par->width * k + j) * bitsperpixel / 8;
 				u8 byte = *(vmem + index);
-				u8 bit = byte & (1 << (j % 8));
-				bit = bit >> (j % 8);
+				u8 bit = byte & (((1 << (bitsperpixel))-1) << (j % 8/bitsperpixel));
+
+				bit = (bit >> (j % 8/bitsperpixel)) >> (bitsperpixel-1);
 				array->data[array_idx] |= bit << k;
 			}
 		}
@@ -536,7 +542,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->dclk_div = par->device_info->default_dclk_div;
 	par->dclk_frq = par->device_info->default_dclk_frq;
 
-	vmem_size = par->width * par->height / 8;
+	vmem_size = par->width * par->height * bitsperpixel / 8;
 
 	vmem = vzalloc(vmem_size);
 	if (!vmem) {
@@ -557,20 +563,21 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
-	info->fix.line_length = par->width / 8;
+	info->fix.line_length = par->width * bitsperpixel / 8;
 	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
+	info->var.bits_per_pixel = bitsperpixel;
 	info->var.xres = par->width;
 	info->var.xres_virtual = par->width;
 	info->var.yres = par->height;
 	info->var.yres_virtual = par->height;
 
-	info->var.red.length = 1;
+	info->var.red.length = bitsperpixel;
 	info->var.red.offset = 0;
-	info->var.green.length = 1;
+	info->var.green.length = bitsperpixel;
 	info->var.green.offset = 0;
-	info->var.blue.length = 1;
+	info->var.blue.length = bitsperpixel;
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-- 
2.3.0


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

* [PATCHv3 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (7 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  2015-03-09 22:22   ` [PATCHv3 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds sysfs handles to enable userspace control over the display
contrast as well as the dim mode. The handles are available as "contrast"
and "dim" in the framebuffers sysfs domain.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 90 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 3cf4da1..fee6324 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -33,6 +33,7 @@
 #define SSD1307FB_CONTRAST		0x81
 #define	SSD1307FB_CHARGE_PUMP		0x8d
 #define SSD1307FB_SEG_REMAP_ON		0xa1
+#define SSD1307FB_DISPLAY_DIM		0xac
 #define SSD1307FB_DISPLAY_OFF		0xae
 #define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
 #define SSD1307FB_DISPLAY_ON		0xaf
@@ -43,6 +44,9 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define MIN_CONTRAST 0
+#define MAX_CONTRAST 255
+
 #define REFRASHRATE 1
 #define BITSPERPIXEL 1
 
@@ -73,6 +77,7 @@ struct ssd1307fb_par {
 	u32 dclk_div;
 	u32 dclk_frq;
 	struct ssd1307fb_deviceinfo *device_info;
+	u32 dim;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
@@ -476,6 +481,87 @@ static const struct of_device_id ssd1307fb_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 
+static ssize_t show_contrast(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->contrast);
+}
+
+static ssize_t store_contrast(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+	unsigned long contrastval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &contrastval);
+	if (ret < 0)
+		return ret;
+
+	par->contrast = max_t(ulong, min_t(ulong, contrastval,
+		(ulong)MAX_CONTRAST), (ulong)MIN_CONTRAST);
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->contrast);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+
+static ssize_t show_dim(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", par->dim);
+}
+
+static ssize_t store_dim(struct device *device,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+	struct ssd1307fb_par *par = info->par;
+	unsigned long dimval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &dimval);
+	if (ret < 0)
+		return ret;
+
+	par->dim = max_t(ulong, min_t(ulong, dimval, (ulong)1), (ulong)0);
+	if (par->dim)
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_DIM);
+	else
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast, store_contrast);
+static DEVICE_ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim);
+
+static struct attribute *panel_attrs[] = {
+		&dev_attr_contrast.attr,
+		&dev_attr_dim.attr,
+		NULL,
+};
+
+static struct attribute_group brightness_attr_grp = {
+		.name  = "brightness",
+		.attrs = panel_attrs,
+};
+
 static int ssd1307fb_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
@@ -614,6 +700,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto panel_init_error;
 	}
 
+	ret = sysfs_create_group(&info->dev->kobj, &brightness_attr_grp);
+	if (ret)
+		dev_err(&client->dev, "Couldn't register sysfs nodes\n");
+
 	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
 
 	return 0;
-- 
2.3.0


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

* [PATCHv3 10/10] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (8 preceding siblings ...)
  2015-03-09 22:22   ` [PATCHv3 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace Thomas Niederprüm
@ 2015-03-09 22:22   ` Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-09 22:22 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch turns off the display when the driver is unloaded.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index fee6324..5efed67 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -726,6 +726,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct fb_info *info = i2c_get_clientdata(client);
 	struct ssd1307fb_par *par = info->par;
 
+	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+
 	unregister_framebuffer(info);
 	if (par->device_info->device_id == DEVID_SSD1307) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-02-14 15:54       ` Maxime Ripard
@ 2015-03-10 10:45         ` Tomi Valkeinen
  2015-03-13 19:25           ` Thomas Niederprüm
  2015-03-25 10:56           ` Olliver Schinagl
  0 siblings, 2 replies; 138+ messages in thread
From: Tomi Valkeinen @ 2015-03-10 10:45 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Niederprüm; +Cc: linux-fbdev, plagnioj, linux-kernel

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

On 14/02/15 17:54, Maxime Ripard wrote:
> On Sat, Feb 07, 2015 at 05:05:03PM +0100, Thomas Niederprüm wrote:
>> Am Sat, 7 Feb 2015 12:20:43 +0100
>> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
>>
>>> On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de
>>> wrote:
>>>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
>>>>
>>>> This patch adds a module parameter 'bitsperpixel' to adjust the
>>>> colordepth of the framebuffer. All values >1 will result in memory
>>>> map of the requested color depth. However only the MSB of each
>>>> pixel will be sent to the device. The framebuffer identifies itself
>>>> as a grayscale display with the specified depth.
>>>
>>> I'm not sure this is the right thing to do.
>>>
>>> The bits per pixel for this display is rightfully defined, used and
>>> reported to the userspace, why would you want to change that?
>>
>> You are right of course. The display is 1bpp and it reports to be 1
>> bpp. The problem is that there is almost no userspace library that can
>> handle 1 bit framebuffers correctly. So it is nice if the framebuffer
>> (optionally) can expose itself as 8 bits per pixel grayscale to the
>> userspace program. As an example this allows to run DirectFB on the
>> framebuffer, which is not possible out of the box for 1bpp.
>>
>> Also note that if do not set the module parameter at load time
>> the framebuffer will be 1bpp. So you have to actively set that module
>> parameter to make the framebuffer pretend to be more than 1bpp.
>>
>> In any case I don't cling to that patch, I just thought it was a nice
>> feature.
> 
> I'd say that the right fix would be to patch DirectFB, instead of
> faking that in the kernel.
> 
> But again, that's probably Tomi's call, not mine.

Right, I'm not thrilled =). I don't think it's a good idea to lie to the
userspace (except when fixing regressions).

 Tomi



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

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

* Re: [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-02-09  8:52       ` Maxime Ripard
@ 2015-03-10 10:49         ` Tomi Valkeinen
  2015-03-13 19:21           ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Tomi Valkeinen @ 2015-03-10 10:49 UTC (permalink / raw)
  To: Maxime Ripard, Thomas Niederprüm; +Cc: linux-fbdev, plagnioj, linux-kernel

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

On 09/02/15 10:52, Maxime Ripard wrote:
> On Sat, Feb 07, 2015 at 05:42:44PM +0100, Thomas Niederprüm wrote:
>>>> +static struct device_attribute device_attrs[] = {
>>>> +	__ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast,
>>>> store_contrast),
>>>> +	__ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim),
>>>> +
>>>> +};
>>>> +
>>>
>>> I would have thought this was something accessible through the
>>> framebuffer ioctl.
>>>
>>> Apparently it's not, at least for the contrast, so maybe it should be
>>> added there, instead of doing it for a single driver?
>>
>> I think the contrast setting for an OLED display is much like the
>> backlight setting for LCD panel. Since there is also no ioctl to set
>> the backlight of an LCD I wonder if the contrast of an OLED should have
>> one.
> 
> It's too much of framebuffer interface debate for me here. Tomi?

We have backlight and contrast already in backlight-class and lcd-class
(drivers/video/backlight/backlight.c and drivers/video/backlight/lcd.c).
Are those something that could be used here instead of custom sysfs files?

 Tomi



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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-02-14 14:22         ` Thomas Niederprüm
  2015-02-14 15:36           ` Maxime Ripard
@ 2015-03-10 11:28           ` Tomi Valkeinen
  2015-03-13 21:31             ` Thomas Niederprüm
  1 sibling, 1 reply; 138+ messages in thread
From: Tomi Valkeinen @ 2015-03-10 11:28 UTC (permalink / raw)
  To: Thomas Niederprüm, Maxime Ripard; +Cc: linux-fbdev, plagnioj, linux-kernel

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

On 14/02/15 16:22, Thomas Niederprüm wrote:
> Am Thu, 12 Feb 2015 16:11:21 +0100
> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> 
>> On Sat, Feb 07, 2015 at 04:35:41PM +0100, Thomas Niederprüm wrote:
>>> Am Sat, 7 Feb 2015 12:18:21 +0100
>>> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
>>>
>>>> Hi,
>>>>
>>>> On Fri, Feb 06, 2015 at 11:28:10PM +0100, niederp@physik.uni-kl.de
>>>> wrote:
>>>>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
>>>>>
>>>>> It makes sense to use vmalloc to allocate the video buffer
>>>>> since it has to be page aligned memory for using it with mmap.
>>>>
>>>> Please wrap your commit log at 80 chars.
>>>
>>> I'll try to do so in future, sorry for that.
>>>
>>>>
>>>> It looks like there's numerous fbdev drivers using this
>>>> (especially since you copy pasted that code, without mentionning
>>>> it).
>>>
>>> Yes, I should have mentioned that in the commit message. As
>>> implicitly indicated in the cover letter the rvmalloc() and
>>> rvfree() are copy pasted from the vfb driver. Honestly, I didn't
>>> give this one too much thought. It seemed a viable solution to the
>>> mmap problem. For a bit more history on that, see my comment below.
>>>
>>>>
>>>> That should be turned into an allocator so that drivers all get
>>>> this right.
>>>>
>>>>> Also deffered io seems buggy in combination with kmalloc'ed
>>>>> memory (crash on unloading the module).
>>>>
>>>> And maybe that's the real issue to fix.
>>>
>>> The problem is solved by using vmalloc ;)
>>
>> Yep, but why do you need to mark the reserved pages?
>>
>> ...
> 
> As far as I understood mmaped memory is marked as userspace memory in
> the page table and is therefore subject to swapping. The pages are
> marked reserved to make clear that this memory can not be swapped and
> thus lock the pages in memory. See discussions [0,1,2]. 

Why is it a problem if it is swapped? Only CPU uses the memory, as far
as I can see.

Also, isn't doing __pa() for the memory returned by vmalloc plain wrong?

What was the crash about when using kmalloc? It would be good to fix
defio, as I don't see why it should not work with kmalloced memory.

 Tomi



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

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

* Re: [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace.
  2015-03-10 10:49         ` Tomi Valkeinen
@ 2015-03-13 19:21           ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-13 19:21 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, linux-fbdev, plagnioj, linux-kernel

Am Tue, 10 Mar 2015 12:49:19 +0200
schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:

> On 09/02/15 10:52, Maxime Ripard wrote:
> > On Sat, Feb 07, 2015 at 05:42:44PM +0100, Thomas Niederprüm wrote:
> >>>> +static struct device_attribute device_attrs[] = {
> >>>> +	__ATTR(contrast, S_IRUGO|S_IWUSR, show_contrast,
> >>>> store_contrast),
> >>>> +	__ATTR(dim, S_IRUGO|S_IWUSR, show_dim, store_dim),
> >>>> +
> >>>> +};
> >>>> +
> >>>
> >>> I would have thought this was something accessible through the
> >>> framebuffer ioctl.
> >>>
> >>> Apparently it's not, at least for the contrast, so maybe it
> >>> should be added there, instead of doing it for a single driver?
> >>
> >> I think the contrast setting for an OLED display is much like the
> >> backlight setting for LCD panel. Since there is also no ioctl to
> >> set the backlight of an LCD I wonder if the contrast of an OLED
> >> should have one.
> > 
> > It's too much of framebuffer interface debate for me here. Tomi?
> 
> We have backlight and contrast already in backlight-class and
> lcd-class (drivers/video/backlight/backlight.c and
> drivers/video/backlight/lcd.c). Are those something that could be
> used here instead of custom sysfs files?

I just gave the backlight-class a try and it works like a charm. I
will include it in v4 and drop the sysfs handles instead. Thanks for the
hint!

Thomas


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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-03-10 10:45         ` Tomi Valkeinen
@ 2015-03-13 19:25           ` Thomas Niederprüm
  2015-03-25 10:56           ` Olliver Schinagl
  1 sibling, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-13 19:25 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, linux-fbdev, plagnioj, linux-kernel

Am Tue, 10 Mar 2015 12:45:49 +0200
schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:

> On 14/02/15 17:54, Maxime Ripard wrote:
> > On Sat, Feb 07, 2015 at 05:05:03PM +0100, Thomas Niederprüm wrote:
> >> Am Sat, 7 Feb 2015 12:20:43 +0100
> >> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> >>
> >>> On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de
> >>> wrote:
> >>>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> >>>>
> >>>> This patch adds a module parameter 'bitsperpixel' to adjust the
> >>>> colordepth of the framebuffer. All values >1 will result in
> >>>> memory map of the requested color depth. However only the MSB of
> >>>> each pixel will be sent to the device. The framebuffer
> >>>> identifies itself as a grayscale display with the specified
> >>>> depth.
> >>>
> >>> I'm not sure this is the right thing to do.
> >>>
> >>> The bits per pixel for this display is rightfully defined, used
> >>> and reported to the userspace, why would you want to change that?
> >>
> >> You are right of course. The display is 1bpp and it reports to be 1
> >> bpp. The problem is that there is almost no userspace library that
> >> can handle 1 bit framebuffers correctly. So it is nice if the
> >> framebuffer (optionally) can expose itself as 8 bits per pixel
> >> grayscale to the userspace program. As an example this allows to
> >> run DirectFB on the framebuffer, which is not possible out of the
> >> box for 1bpp.
> >>
> >> Also note that if do not set the module parameter at load time
> >> the framebuffer will be 1bpp. So you have to actively set that
> >> module parameter to make the framebuffer pretend to be more than
> >> 1bpp.
> >>
> >> In any case I don't cling to that patch, I just thought it was a
> >> nice feature.
> > 
> > I'd say that the right fix would be to patch DirectFB, instead of
> > faking that in the kernel.
> > 
> > But again, that's probably Tomi's call, not mine.
> 
> Right, I'm not thrilled =). I don't think it's a good idea to lie to
> the userspace (except when fixing regressions).

Ok, since Maxime and you agree that this is not desirable I will drop
that patch in v4.

Thomas

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-10 11:28           ` Tomi Valkeinen
@ 2015-03-13 21:31             ` Thomas Niederprüm
  2015-03-14 22:02               ` Geert Uytterhoeven
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-13 21:31 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Maxime Ripard, linux-fbdev, plagnioj, linux-kernel

Am Tue, 10 Mar 2015 13:28:25 +0200
schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:

> On 14/02/15 16:22, Thomas Niederprüm wrote:
> > Am Thu, 12 Feb 2015 16:11:21 +0100
> > schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> > 
> >> On Sat, Feb 07, 2015 at 04:35:41PM +0100, Thomas Niederprüm wrote:
> >>> Am Sat, 7 Feb 2015 12:18:21 +0100
> >>> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> >>>
> >>>> Hi,
> >>>>
> >>>> On Fri, Feb 06, 2015 at 11:28:10PM +0100,
> >>>> niederp@physik.uni-kl.de wrote:
> >>>>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> >>>>>
> >>>>> It makes sense to use vmalloc to allocate the video buffer
> >>>>> since it has to be page aligned memory for using it with mmap.
> >>>>
> >>>> Please wrap your commit log at 80 chars.
> >>>
> >>> I'll try to do so in future, sorry for that.
> >>>
> >>>>
> >>>> It looks like there's numerous fbdev drivers using this
> >>>> (especially since you copy pasted that code, without mentionning
> >>>> it).
> >>>
> >>> Yes, I should have mentioned that in the commit message. As
> >>> implicitly indicated in the cover letter the rvmalloc() and
> >>> rvfree() are copy pasted from the vfb driver. Honestly, I didn't
> >>> give this one too much thought. It seemed a viable solution to the
> >>> mmap problem. For a bit more history on that, see my comment
> >>> below.
> >>>
> >>>>
> >>>> That should be turned into an allocator so that drivers all get
> >>>> this right.
> >>>>
> >>>>> Also deffered io seems buggy in combination with kmalloc'ed
> >>>>> memory (crash on unloading the module).
> >>>>
> >>>> And maybe that's the real issue to fix.
> >>>
> >>> The problem is solved by using vmalloc ;)
> >>
> >> Yep, but why do you need to mark the reserved pages?
> >>
> >> ...
> > 
> > As far as I understood mmaped memory is marked as userspace memory
> > in the page table and is therefore subject to swapping. The pages
> > are marked reserved to make clear that this memory can not be
> > swapped and thus lock the pages in memory. See discussions [0,1,2]. 
> 
> Why is it a problem if it is swapped? Only CPU uses the memory, as far
> as I can see.

It seems to be no problem at all. I was copying the allocation code
from the vfb driver. The memory is no longer marked as reserved from
v2 on.

> Also, isn't doing __pa() for the memory returned by vmalloc plain
> wrong?

> What was the crash about when using kmalloc? It would be good to fix
> defio, as I don't see why it should not work with kmalloced memory.

The main challenge here is that the memory handed to userspace upon
mmap call needs to be page aligned. The memory returned by kmalloc has
no such alignment, but the pointer presented to the userspace program
gets aligned to next page boundary. It's not clear to me whether there
is an easy way to obtain page aligned kmalloc memory. Memory
allocated by vmalloc on the other hand is always aligned to page
boundaries. This is why I chose to go for vmalloc.

Thomas

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-13 21:31             ` Thomas Niederprüm
@ 2015-03-14 22:02               ` Geert Uytterhoeven
  2015-03-20 11:37                 ` Tomi Valkeinen
  0 siblings, 1 reply; 138+ messages in thread
From: Geert Uytterhoeven @ 2015-03-14 22:02 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: Tomi Valkeinen, Maxime Ripard, Linux Fbdev development list,
	Jean-Christophe PLAGNIOL-VILLARD, linux-kernel

On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
<niederp@physik.uni-kl.de> wrote:
> Am Tue, 10 Mar 2015 13:28:25 +0200
> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
>> Also, isn't doing __pa() for the memory returned by vmalloc plain
>> wrong?
>
>> What was the crash about when using kmalloc? It would be good to fix
>> defio, as I don't see why it should not work with kmalloced memory.
>
> The main challenge here is that the memory handed to userspace upon
> mmap call needs to be page aligned. The memory returned by kmalloc has
> no such alignment, but the pointer presented to the userspace program
> gets aligned to next page boundary. It's not clear to me whether there
> is an easy way to obtain page aligned kmalloc memory. Memory
> allocated by vmalloc on the other hand is always aligned to page
> boundaries. This is why I chose to go for vmalloc.

__get_free_pages()?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* [PATCHv4 00/10] Cleanup and add support for SSD1305
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (9 preceding siblings ...)
  2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-16 17:11 ` Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
                     ` (9 more replies)
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
  12 siblings, 10 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch series is the result of making the ssd1307fb driver work with
a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
this the intialization code for the SSD1306 and the SSD1307 is merged
and based on DT configuration to reflect the various possible wirings
of the SSD130X controller (04/10). Based on these changes it is straight
forward to add support for the SSD1305 controller (06/10).

While working on the driver I realized that it was not possible to
correctly mmap the video memory from userspace since the address handed
to the userspace app is a logical one where it should be a physical one.
Patch 01/10 fixes this. Furthermore the memory reserved by kzalloc is
not page aligned while the address handed to userspace is aligned to the
next page frame. This problem is fixed by using __get_free_pages() in 02/10.

Furthermore a module parameter is added to set the delay for the
deferred io update (07/10). Also the backlight class is implemented to make
the contrast setting available in userspace (09/10).

changes since v1 (thanks to Maxime for the feedback):
- dedicated patch for fixing smem_start address
- remove page reserve upon vmalloc
- remove return value check upon display turn-off at module unload
- use a module parameter refreshrate rather than delaydivider
- allocate fbdefio dynamically
- use sysfs_create_groups to create sysfs entries
- remove contrast, vhcom and dclk properties from DT since they are
  not part of hw description. The contrast module parameter was added
  to set contrast at load time. vhcom and dclk stays at it's default
  values for now.
- add new DT properties to in tree users of ssd130X
- rebased to apply on top of linux-next

changes since v2 (thanks to Maxime again):
- free memory allocated by vmalloc on driver unload
- set default values in the init code to the ones of the existing ssd1307
  init code
- added two ACKs (Maxime Ripard)

changes since v3:
- use backlight class rather than dedicated sysfs files to set the 
  contrast (Thanks to Tomi Valkeinen)
- remove [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel
- add new patch to blank the display (unreviewed)
- allocate video memory through __get_free_pages() rather than vmalloc
  (Thanks to Geert Uytterhoeven)
- minor rewordings of the commit messages

Thomas Niederprüm (10):
  fbdev: ssd1307fb: fix memory address smem_start.
  fbdev: ssd1307fb: Allocate page aligned video memory.
  of: Add Solomon Systech vendor prefix.
  fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  ARM: mxs: fix in tree users of ssd1306
  fbdev: ssd1307fb: Add support for SSD1305
  fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  fbdev: ssd1307fb: Turn off display on driver unload.
  fbdev: ssd1307fb: add backlight controls for setting the contrast
  fbdev: ssd1307fb: Add blank mode

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../devicetree/bindings/video/ssd1307fb.txt        |  23 +-
 arch/arm/boot/dts/imx28-cfa10036.dts               |   3 +
 drivers/video/fbdev/Kconfig                        |   1 +
 drivers/video/fbdev/ssd1307fb.c                    | 310 +++++++++++++++------
 5 files changed, 250 insertions(+), 88 deletions(-)

-- 
2.3.0


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

* [PATCHv4 01/10] fbdev: ssd1307fb: fix memory address smem_start.
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

the smem_start pointer of the framebuffer info struct needs to hold the
physical address rather than the logical address. Right now the logical
address returned by kmalloc is stored. This patch converts this address
to a physical address and thus fixes a driver crash on mmaping the
framebuffer memory due to an access to the wrong memory address.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f7ed6d9..61e0ce8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -515,7 +515,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
 	fb_deferred_io_init(info);
-- 
2.3.0


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

* [PATCHv4 02/10] fbdev: ssd1307fb: Allocate page aligned video memory.
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-18 17:38     ` Maxime Ripard
  2015-03-16 17:11   ` [PATCHv4 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

Currently the videomemory is allocated by kmalloc, making it a memory
region that is not necessarily page aligend. This leads to problems
upon mmap call, where the video memory's address gets aligned to the
next page boundary. The result is that the userspace program that issued
the mmap call is not able to access the video memory from the start to
the next page boundary.

This patch changes the allocation of the video memory to use
__get_free_pages() in order to obtain memory that is aligned
to page boundaries.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 61e0ce8..8d34c56 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -489,7 +489,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	vmem_size = par->width * par->height / 8;
 
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+					get_order(vmem_size));
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -573,6 +574,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	if (par->ops->remove)
 		par->ops->remove(par);
 	fb_deferred_io_cleanup(info);
+	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
 	framebuffer_release(info);
 
 	return 0;
-- 
2.3.0


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

* [PATCHv4 03/10] of: Add Solomon Systech vendor prefix.
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the solomon prefix for Solomon Systech Limited.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d3f4809..933c8f5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -169,6 +169,7 @@ sitronix	Sitronix Technology Corporation
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
+solomon        Solomon Systech Limited
 sony	Sony Corporation
 spansion	Spansion Inc.
 sprd	Spreadtrum Communications Inc.
-- 
2.3.0


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

* [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (2 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-18 19:27     ` Maxime Ripard
  2015-03-16 17:11   ` [PATCHv4 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
                     ` (5 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The 130X controllers are very similar from the configuration point of view.
The configuration registers for the SSD1305/6/7 are bit identical (except the
the VHCOM register and the the default values for clock setup register). This
patch unifies the init code of the controller and adds hardware specific
properties to DT that are needed to correctly initialize the device.

The SSD130X can be wired to the OLED panel in various ways. Even for the
same controller this wiring can differ from one display module to another
and can not be probed by software. The added DT properties reflect these
hardware decisions of the display module manufacturer.
The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
possibilities for the COM signals pin configuration and readout direction
of the video memory. The 'segment-no-remap' allows the inversion of the
memory-to-pin mapping ultimately inverting the order of the controllers
output pins. The 'prechargepX' values need to be adapted according the
capacitance of the OLEDs pixel cells.

So far these hardware specific bits are hard coded in the init code, making
the driver usable only for one certain wiring of the controller. This patch
makes the driver usable with all possible hardware setups, given a valid hw
description in DT. If these values are not set in DT the default values,
as they are set in the ssd1307 init code right now, are used. This implies
that without the corresponding DT property "segment-no-remap" the segment
remap of the ssd130X controller gets activated. Even though this is not the
default behaviour according to the datasheet it maintains backward
compatibility with older DTBs.

Note that the SSD1306 does not seem to be using the configuration written to
the registers at all. Therefore this patch does not try to maintain these
values without changes in DT. For reference an example is added to the DT
bindings documentation that reproduces the configuration that is set in the
current init code.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
 drivers/video/fbdev/ssd1307fb.c                    | 195 ++++++++++++---------
 2 files changed, 137 insertions(+), 79 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 7a12542..be27562 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -15,6 +15,16 @@ Required properties:
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
+  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
+                              to segment mapping
+  - solomon,com-sequential: Display uses sequential COM pin configuration
+  - solomon,com-lrremap: Display uses left-right COM pin remap
+  - solomon,com-invdir: Display uses inverted COM pin scan direction
+  - solomon,com-offset: Offset of the first COM pin wired to the panel
+  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
+  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
+                         This needs to be the higher, the higher the capacitance
+                         of the OLED's pixels is
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -26,3 +36,14 @@ ssd1307: oled@3c {
         reset-gpios = <&gpio2 7>;
         reset-active-low;
 };
+
+ssd1306: oled@3c {
+        compatible = "solomon,ssd1306fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+        solomon,com-lrremap;
+        solomon,com-invdir;
+        solomon,com-offset = <32>;
+};
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 8d34c56..9a66118 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -16,6 +16,9 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1306 6
+#define DEVID_SSD1307 7
+
 #define SSD1307FB_DATA			0x40
 #define SSD1307FB_COMMAND		0x80
 
@@ -38,22 +41,38 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+static u_int contrast = 128;
+module_param(contrast, uint, S_IRUGO);
+
 struct ssd1307fb_par;
 
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
+struct ssd1307fb_deviceinfo {
+	int device_id;
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
 };
 
 struct ssd1307fb_par {
+	u32 com_invdir;
+	u32 com_lrremap;
+	u32 com_offset;
+	u32 com_seq;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	struct ssd1307fb_deviceinfo *device_info;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
 	u32 page_offset;
+	u32 prechargep1;
+	u32 prechargep2;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 seg_remap;
+	u32 vcomh;
 	u32 width;
 };
 
@@ -254,69 +273,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
+	u32 precharge, dclk, com_invdir, compins;
 
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		par->pwm = pwm_get(&par->client->dev, NULL);
+		if (IS_ERR(par->pwm)) {
+			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+			return PTR_ERR(par->pwm);
+		}
 
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
+		par->pwm_period = pwm_get_period(par->pwm);
+		/* Enable the PWM */
+		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+		pwm_enable(par->pwm);
 
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
+		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+			par->pwm->pwm, par->pwm_period);
+	};
 
 	/* Set initial contrast */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x7f);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
 	if (ret < 0)
 		return ret;
 
 	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (par->seg_remap) {
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	};
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
+	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
 	if (ret < 0)
 		return ret;
 
@@ -334,34 +330,38 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
 	if (ret < 0)
 		return ret;
 
 	/* Set clock frequency */
+	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0xf0);
+	ret = ssd1307fb_write_cmd(par->client, dclk);
 	if (ret < 0)
 		return ret;
 
 	/* Set precharge period in number of ticks from the internal clock */
+	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	ret = ssd1307fb_write_cmd(par->client, precharge);
 	if (ret < 0)
 		return ret;
 
 	/* Set COM pins configuration */
+	compins = 0x02 | (!par->com_seq & 0x1) << 4
+				   | (par->com_lrremap & 0x1) << 5;
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	ret = ssd1307fb_write_cmd(par->client, compins);
 	if (ret < 0)
 		return ret;
 
@@ -370,18 +370,20 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x49);
+	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
 	if (ret < 0)
 		return ret;
 
-	/* Turn on the DC-DC Charge Pump */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
-	if (ret < 0)
-		return ret;
+	if (par->device_info->device_id == DEVID_SSD1306) {
+		/* Turn on the DC-DC Charge Pump */
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+		if (ret < 0)
+			return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x14);
-	if (ret < 0)
-		return ret;
+		ret = ssd1307fb_write_cmd(par->client, 0x14);
+		if (ret < 0)
+			return ret;
+	};
 
 	/* Switch to horizontal addressing mode */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
@@ -393,6 +395,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+    /* Set column range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
 	if (ret < 0)
 		return ret;
@@ -405,6 +408,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+    /* Set page range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
 	if (ret < 0)
 		return ret;
@@ -426,18 +430,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
+	.device_id  = DEVID_SSD1306,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 8,
+};
+
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
+	.device_id  = DEVID_SSD1307,
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 12,
 };
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
 		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
+		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
 	{
 		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
+		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
 	},
 	{},
 };
@@ -468,8 +482,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->info = info;
 	par->client = client;
 
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
+	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
+			ssd1307fb_of_match, &client->dev)->data;
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
@@ -487,6 +501,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
 		par->page_offset = 1;
 
+	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
+		par->com_offset = 0;
+
+	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
+		par->prechargep1 = 2;
+
+	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
+		par->prechargep2 = 0;
+
+	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
+	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
+	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
+	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
+
+	par->contrast = contrast;
+	par->vcomh = par->device_info->default_vcomh;
+
+	/* Setup display timing */
+	par->dclk_div = par->device_info->default_dclk_div;
+	par->dclk_frq = par->device_info->default_dclk_frq;
+
 	vmem_size = par->width * par->height / 8;
 
 	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -539,11 +574,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	gpio_set_value(par->reset, 1);
 	udelay(4);
 
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
+	ret = ssd1307fb_init(par);
+	if (ret)
+		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
 	if (ret) {
@@ -556,8 +589,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	return 0;
 
 panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 fb_alloc_error:
@@ -571,8 +606,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->device_id == DEVID_SSD1307) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 	fb_deferred_io_cleanup(info);
 	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
 	framebuffer_release(info);
-- 
2.3.0


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

* [PATCHv4 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (3 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch updates the in tree-users of the SSD1306 controller for using
the newly introduced DT properties.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index b04b6b8..570aa33 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -99,6 +99,9 @@
 					solomon,height = <32>;
 					solomon,width = <128>;
 					solomon,page-offset = <0>;
+					solomon,com-lrremap;
+					solomon,com-invdir;
+					solomon,com-offset = <32>;
 				};
 			};
 
-- 
2.3.0


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

* [PATCHv4 06/10] fbdev: ssd1307fb: Add support for SSD1305
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (4 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds support for the SSD1305 OLED controller.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/video/ssd1307fb.txt |  2 +-
 drivers/video/fbdev/ssd1307fb.c                       | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index be27562..a878fd2 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -2,7 +2,7 @@
 
 Required properties:
   - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
-    now is i2c, and the supported chips are ssd1306 and ssd1307.
+    now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307.
   - reg: Should contain address of the controller on the I2C bus. Most likely
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 9a66118..6fecec8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -16,6 +16,7 @@
 #include <linux/pwm.h>
 #include <linux/delay.h>
 
+#define DEVID_SSD1305 5
 #define DEVID_SSD1306 6
 #define DEVID_SSD1307 7
 
@@ -430,6 +431,13 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
+	.device_id  = DEVID_SSD1305,
+	.default_vcomh = 0x34,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 7,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
 	.device_id  = DEVID_SSD1306,
 	.default_vcomh = 0x20,
@@ -446,6 +454,10 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1305_deviceinfo,
+	},
+	{
 		.compatible = "solomon,ssd1306fb-i2c",
 		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
@@ -618,6 +630,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1305fb", 0 },
 	{ "ssd1306fb", 0 },
 	{ "ssd1307fb", 0 },
 	{ }
-- 
2.3.0


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

* [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (5 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-19 13:18     ` Maxime Ripard
  2015-03-16 17:11   ` [PATCHv4 08/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the module parameter "refreshrate" to set delay for the
deferred io. The refresh rate is given in units of Hertz. The default
refresh rate is 1 Hz. The refresh rate set through the newly introduced
parameter applies to all instances of the driver and for now it is not
possible to change it individually.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 6fecec8..8a8d305 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -42,6 +42,11 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define REFRASHRATE 1
+
+static u_int refreshrate = REFRASHRATE;
+module_param(refreshrate, uint, 0);
+
 static u_int contrast = 128;
 module_param(contrast, uint, S_IRUGO);
 
@@ -269,11 +274,6 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 	ssd1307fb_update_display(info->par);
 }
 
-static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
-	.deferred_io	= ssd1307fb_deferred_io,
-};
-
 static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
@@ -474,6 +474,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 {
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
+	struct fb_deferred_io *ssd1307fb_defio;
 	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
@@ -544,10 +545,20 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto fb_alloc_error;
 	}
 
+	ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
+	if (!ssd1307fb_defio) {
+		dev_err(&client->dev, "Couldn't allocate deferred io.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	ssd1307fb_defio->delay = HZ / refreshrate;
+	ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io;
+
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
 	info->fix.line_length = par->width / 8;
-	info->fbdefio = &ssd1307fb_defio;
+	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
 	info->var.xres = par->width;
-- 
2.3.0


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

* [PATCHv4 08/10] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (6 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
  2015-03-16 17:11   ` [PATCHv4 10/10] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch turns off the display when the driver is unloaded.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 8a8d305..0d851f1 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -628,6 +628,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct fb_info *info = i2c_get_clientdata(client);
 	struct ssd1307fb_par *par = info->par;
 
+	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+
 	unregister_framebuffer(info);
 	if (par->device_info->device_id == DEVID_SSD1307) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* [PATCHv4 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (7 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 08/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  2015-03-19 13:22     ` Maxime Ripard
  2015-03-16 17:11   ` [PATCHv4 10/10] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
  9 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The backlight class is used to create userspace handles for
setting the OLED contrast.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/Kconfig     |  1 +
 drivers/video/fbdev/ssd1307fb.c | 58 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index b3dd417..da70bae 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2478,6 +2478,7 @@ config FB_SSD1307
 	select FB_SYS_IMAGEBLIT
 	select FB_DEFERRED_IO
 	select PWM
+	select FB_BACKLIGHT
 	help
 	  This driver implements support for the Solomon SSD1307
 	  OLED controller over I2C.
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 0d851f1..4ebfcaf 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/backlight.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/fb.h>
@@ -42,6 +43,8 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define MAX_CONTRAST 255
+
 #define REFRASHRATE 1
 
 static u_int refreshrate = REFRASHRATE;
@@ -431,6 +434,43 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static int ssd1307fb_update_bl(struct backlight_device *bdev)
+{
+	struct ssd1307fb_par *par = bl_get_data(bdev);
+	int ret;
+	int brightness = bdev->props.brightness;
+
+	par->contrast = brightness;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	if (ret < 0)
+		return ret;
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int ssd1307fb_get_brightness(struct backlight_device *bdev)
+{
+	struct ssd1307fb_par *par = bl_get_data(bdev);
+
+	return par->contrast;
+}
+
+static int ssd1307fb_check_fb(struct backlight_device *bdev,
+				   struct fb_info *info)
+{
+	return (info->bl_dev == bdev);
+}
+
+static const struct backlight_ops ssd1307fb_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= ssd1307fb_update_bl,
+	.get_brightness	= ssd1307fb_get_brightness,
+	.check_fb	= ssd1307fb_check_fb,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
 	.device_id  = DEVID_SSD1305,
 	.default_vcomh = 0x34,
@@ -472,6 +512,8 @@ MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 static int ssd1307fb_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
+	struct backlight_device *bl;
+	char bl_name[12];
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
 	struct fb_deferred_io *ssd1307fb_defio;
@@ -607,10 +649,24 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto panel_init_error;
 	}
 
+	snprintf(bl_name, sizeof(bl_name), "ssd1307fb%d", info->node);
+	bl = backlight_device_register(bl_name, &client->dev, par,
+				       &ssd1307fb_bl_ops, NULL);
+	bl->props.brightness = contrast;
+	bl->props.max_brightness = MAX_CONTRAST;
+	info->bl_dev = bl;
+
+	if (IS_ERR(bl)) {
+		dev_err(&client->dev, "unable to register backlight device: %ld\n",
+			PTR_ERR(bl));
+		goto bl_init_error;
+	}
 	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
 
 	return 0;
 
+bl_init_error:
+	unregister_framebuffer(info);
 panel_init_error:
 	if (par->device_info->device_id == DEVID_SSD1307) {
 		pwm_disable(par->pwm);
@@ -630,6 +686,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 
 	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
 
+	backlight_device_unregister(info->bl_dev);
+
 	unregister_framebuffer(info);
 	if (par->device_info->device_id == DEVID_SSD1307) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* [PATCHv4 10/10] fbdev: ssd1307fb: Add blank mode
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (8 preceding siblings ...)
  2015-03-16 17:11   ` [PATCHv4 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
@ 2015-03-16 17:11   ` Thomas Niederprüm
  9 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-16 17:11 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds ssd1307fb_blank() to make the framebuffer capable
of blanking.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 4ebfcaf..9271bba 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -241,6 +241,18 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
 	return count;
 }
 
+static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct ssd1307fb_par *par = info->par;
+	int ret;
+
+	if (blank_mode != FB_BLANK_UNBLANK)
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+	else
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	return ret;
+}
+
 static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct ssd1307fb_par *par = info->par;
@@ -266,6 +278,7 @@ static struct fb_ops ssd1307fb_ops = {
 	.owner		= THIS_MODULE,
 	.fb_read	= fb_sys_read,
 	.fb_write	= ssd1307fb_write,
+	.fb_blank	= ssd1307fb_blank,
 	.fb_fillrect	= ssd1307fb_fillrect,
 	.fb_copyarea	= ssd1307fb_copyarea,
 	.fb_imageblit	= ssd1307fb_imageblit,
-- 
2.3.0


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

* Re: [PATCHv4 02/10] fbdev: ssd1307fb: Allocate page aligned video memory.
  2015-03-16 17:11   ` [PATCHv4 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
@ 2015-03-18 17:38     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-18 17:38 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Mon, Mar 16, 2015 at 06:11:50PM +0100, Thomas Niederprüm wrote:
> Currently the videomemory is allocated by kmalloc, making it a memory
> region that is not necessarily page aligend. This leads to problems
> upon mmap call, where the video memory's address gets aligned to the
> next page boundary. The result is that the userspace program that issued
> the mmap call is not able to access the video memory from the start to
> the next page boundary.
> 
> This patch changes the allocation of the video memory to use
> __get_free_pages() in order to obtain memory that is aligned
> to page boundaries.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-16 17:11   ` [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-18 19:27     ` Maxime Ripard
  2015-03-20 21:12       ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-03-18 19:27 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

Hi Thomas,

On Mon, Mar 16, 2015 at 06:11:52PM +0100, Thomas Niederprüm wrote:
> The 130X controllers are very similar from the configuration point of view.
> The configuration registers for the SSD1305/6/7 are bit identical (except the
> the VHCOM register and the the default values for clock setup register). This
> patch unifies the init code of the controller and adds hardware specific
> properties to DT that are needed to correctly initialize the device.
> 
> The SSD130X can be wired to the OLED panel in various ways. Even for the
> same controller this wiring can differ from one display module to another
> and can not be probed by software. The added DT properties reflect these
> hardware decisions of the display module manufacturer.
> The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
> possibilities for the COM signals pin configuration and readout direction
> of the video memory. The 'segment-no-remap' allows the inversion of the
> memory-to-pin mapping ultimately inverting the order of the controllers
> output pins. The 'prechargepX' values need to be adapted according the
> capacitance of the OLEDs pixel cells.
> 
> So far these hardware specific bits are hard coded in the init code, making
> the driver usable only for one certain wiring of the controller. This patch
> makes the driver usable with all possible hardware setups, given a valid hw
> description in DT. If these values are not set in DT the default values,
> as they are set in the ssd1307 init code right now, are used. This implies
> that without the corresponding DT property "segment-no-remap" the segment
> remap of the ssd130X controller gets activated. Even though this is not the
> default behaviour according to the datasheet it maintains backward
> compatibility with older DTBs.
> 
> Note that the SSD1306 does not seem to be using the configuration written to
> the registers at all. Therefore this patch does not try to maintain these
> values without changes in DT. For reference an example is added to the DT
> bindings documentation that reproduces the configuration that is set in the
> current init code.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

This looks mostly fine, thanks for your effort on this.

> ---
>  .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
>  drivers/video/fbdev/ssd1307fb.c                    | 195 ++++++++++++---------
>  2 files changed, 137 insertions(+), 79 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> index 7a12542..be27562 100644
> --- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> @@ -15,6 +15,16 @@ Required properties:
>  
>  Optional properties:
>    - reset-active-low: Is the reset gpio is active on physical low?
> +  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
> +                              to segment mapping
> +  - solomon,com-sequential: Display uses sequential COM pin configuration
> +  - solomon,com-lrremap: Display uses left-right COM pin remap
> +  - solomon,com-invdir: Display uses inverted COM pin scan direction
> +  - solomon,com-offset: Offset of the first COM pin wired to the panel

Documenting the offset unit would be fine.

> +  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
> +  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
> +                         This needs to be the higher, the higher the capacitance
> +                         of the OLED's pixels is
>  
>  [0]: Documentation/devicetree/bindings/pwm/pwm.txt
>  
> @@ -26,3 +36,14 @@ ssd1307: oled@3c {
>          reset-gpios = <&gpio2 7>;
>          reset-active-low;
>  };
> +
> +ssd1306: oled@3c {
> +        compatible = "solomon,ssd1306fb-i2c";
> +        reg = <0x3c>;
> +        pwms = <&pwm 4 3000>;
> +        reset-gpios = <&gpio2 7>;
> +        reset-active-low;
> +        solomon,com-lrremap;
> +        solomon,com-invdir;
> +        solomon,com-offset = <32>;
> +};
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 8d34c56..9a66118 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -16,6 +16,9 @@
>  #include <linux/pwm.h>
>  #include <linux/delay.h>
>  
> +#define DEVID_SSD1306 6
> +#define DEVID_SSD1307 7
> +
>  #define SSD1307FB_DATA			0x40
>  #define SSD1307FB_COMMAND		0x80
>  
> @@ -38,22 +41,38 @@
>  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
>  #define	SSD1307FB_SET_VCOMH		0xdb
>  
> +static u_int contrast = 128;
> +module_param(contrast, uint, S_IRUGO);
> +

Why is this patch adding a contrast parameter? You don't even mention
it in your commit log. This should be a separate patch.

>  struct ssd1307fb_par;
>  
> -struct ssd1307fb_ops {
> -	int (*init)(struct ssd1307fb_par *);
> -	int (*remove)(struct ssd1307fb_par *);
> +struct ssd1307fb_deviceinfo {
> +	int device_id;
> +	u32 default_vcomh;
> +	u32 default_dclk_div;
> +	u32 default_dclk_frq;
>  };
>  
>  struct ssd1307fb_par {
> +	u32 com_invdir;
> +	u32 com_lrremap;
> +	u32 com_offset;
> +	u32 com_seq;
> +	u32 contrast;
> +	u32 dclk_div;
> +	u32 dclk_frq;
> +	struct ssd1307fb_deviceinfo *device_info;
>  	struct i2c_client *client;
>  	u32 height;
>  	struct fb_info *info;
> -	struct ssd1307fb_ops *ops;
>  	u32 page_offset;
> +	u32 prechargep1;
> +	u32 prechargep2;
>  	struct pwm_device *pwm;
>  	u32 pwm_period;
>  	int reset;
> +	u32 seg_remap;
> +	u32 vcomh;
>  	u32 width;
>  };
>  
> @@ -254,69 +273,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
>  	.deferred_io	= ssd1307fb_deferred_io,
>  };
>  
> -static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
> +static int ssd1307fb_init(struct ssd1307fb_par *par)
>  {
>  	int ret;
> +	u32 precharge, dclk, com_invdir, compins;
>  
> -	par->pwm = pwm_get(&par->client->dev, NULL);
> -	if (IS_ERR(par->pwm)) {
> -		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
> -		return PTR_ERR(par->pwm);
> -	}
> -
> -	par->pwm_period = pwm_get_period(par->pwm);
> -	/* Enable the PWM */
> -	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> -	pwm_enable(par->pwm);
> -
> -	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
> -		par->pwm->pwm, par->pwm_period);
> -
> -	/* Map column 127 of the OLED to segment 0 */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Turn on the display */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
> -	if (ret < 0)
> -		return ret;
> -
> -	return 0;
> -}
> -
> -static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
> -{
> -	pwm_disable(par->pwm);
> -	pwm_put(par->pwm);
> -	return 0;
> -}
> +	if (par->device_info->device_id == DEVID_SSD1307) {
> +		par->pwm = pwm_get(&par->client->dev, NULL);
> +		if (IS_ERR(par->pwm)) {
> +			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
> +			return PTR_ERR(par->pwm);
> +		}
>  
> -static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
> -	.init	= ssd1307fb_ssd1307_init,
> -	.remove	= ssd1307fb_ssd1307_remove,
> -};
> +		par->pwm_period = pwm_get_period(par->pwm);
> +		/* Enable the PWM */
> +		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> +		pwm_enable(par->pwm);
>  
> -static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
> -{
> -	int ret;
> +		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
> +			par->pwm->pwm, par->pwm_period);
> +	};
>  
>  	/* Set initial contrast */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x7f);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Set COM direction */
> -	ret = ssd1307fb_write_cmd(par->client, 0xc8);
> +	ret = ssd1307fb_write_cmd(par->client, par->contrast);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set segment re-map */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> +	if (par->seg_remap) {
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> +		if (ret < 0)
> +			return ret;
> +	};
> +
> +	/* Set COM direction */
> +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -334,34 +330,38 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x20);
> +	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set clock frequency */
> +	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0xf0);
> +	ret = ssd1307fb_write_cmd(par->client, dclk);

It would make more sense to assign the variable where you use it.

>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set precharge period in number of ticks from the internal clock */
> +	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> +	ret = ssd1307fb_write_cmd(par->client, precharge);

Here too.

>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set COM pins configuration */
> +	compins = 0x02 | (!par->com_seq & 0x1) << 4
> +				   | (par->com_lrremap & 0x1) << 5;
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> +	ret = ssd1307fb_write_cmd(par->client, compins);

And here.

>  	if (ret < 0)
>  		return ret;
>  
> @@ -370,18 +370,20 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x49);
> +	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Turn on the DC-DC Charge Pump */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
> -	if (ret < 0)
> -		return ret;
> +	if (par->device_info->device_id == DEVID_SSD1306) {
> +		/* Turn on the DC-DC Charge Pump */
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
> +		if (ret < 0)
> +			return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x14);
> -	if (ret < 0)
> -		return ret;
> +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> +		if (ret < 0)
> +			return ret;
> +	};
>  
>  	/* Switch to horizontal addressing mode */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
> @@ -393,6 +395,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> +    /* Set column range */

The indentation is wrong.

>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
>  	if (ret < 0)
>  		return ret;
> @@ -405,6 +408,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> +    /* Set page range */

Here too.

>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
>  	if (ret < 0)
>  		return ret;
> @@ -426,18 +430,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	return 0;
>  }
>  
> -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> -	.init	= ssd1307fb_ssd1306_init,
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> +	.device_id  = DEVID_SSD1306,
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 0,
> +	.default_dclk_frq = 8,
> +};
> +
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> +	.device_id  = DEVID_SSD1307,
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 1,
> +	.default_dclk_frq = 12,
>  };
>  
>  static const struct of_device_id ssd1307fb_of_match[] = {
>  	{
>  		.compatible = "solomon,ssd1306fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1306_ops,
> +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
>  	},
>  	{
>  		.compatible = "solomon,ssd1307fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1307_ops,
> +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,

Do we need this ID? Wouldn't it make more sense to pass the pointer to
the struct we need to use?

>  	},
>  	{},
>  };
> @@ -468,8 +482,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	par->info = info;
>  	par->client = client;
>  
> -	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
> -							   &client->dev)->data;
> +	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
> +			ssd1307fb_of_match, &client->dev)->data;
>  
>  	par->reset = of_get_named_gpio(client->dev.of_node,
>  					 "reset-gpios", 0);
> @@ -487,6 +501,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
>  		par->page_offset = 1;
>  
> +	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
> +		par->com_offset = 0;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
> +		par->prechargep1 = 2;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
> +		par->prechargep2 = 0;
> +
> +	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
> +	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
> +	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
> +	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
> +
> +	par->contrast = contrast;
> +	par->vcomh = par->device_info->default_vcomh;
> +
> +	/* Setup display timing */
> +	par->dclk_div = par->device_info->default_dclk_div;
> +	par->dclk_frq = par->device_info->default_dclk_frq;
> +
>  	vmem_size = par->width * par->height / 8;
>  
>  	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
> @@ -539,11 +574,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	gpio_set_value(par->reset, 1);
>  	udelay(4);
>  
> -	if (par->ops->init) {
> -		ret = par->ops->init(par);
> -		if (ret)
> -			goto reset_oled_error;
> -	}
> +	ret = ssd1307fb_init(par);
> +	if (ret)
> +		goto reset_oled_error;
>  
>  	ret = register_framebuffer(info);
>  	if (ret) {
> @@ -556,8 +589,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	return 0;
>  
>  panel_init_error:
> -	if (par->ops->remove)
> -		par->ops->remove(par);
> +	if (par->device_info->device_id == DEVID_SSD1307) {
> +		pwm_disable(par->pwm);
> +		pwm_put(par->pwm);
> +	};
>  reset_oled_error:
>  	fb_deferred_io_cleanup(info);
>  fb_alloc_error:
> @@ -571,8 +606,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
>  	struct ssd1307fb_par *par = info->par;
>  
>  	unregister_framebuffer(info);
> -	if (par->ops->remove)
> -		par->ops->remove(par);
> +	if (par->device_info->device_id == DEVID_SSD1307) {
> +		pwm_disable(par->pwm);
> +		pwm_put(par->pwm);
> +	};
>  	fb_deferred_io_cleanup(info);
>  	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
>  	framebuffer_release(info);
> -- 
> 2.3.0
> 

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  2015-03-16 17:11   ` [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
@ 2015-03-19 13:18     ` Maxime Ripard
  2015-03-20 21:16       ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-03-19 13:18 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Mon, Mar 16, 2015 at 06:11:55PM +0100, Thomas Niederprüm wrote:
> This patch adds the module parameter "refreshrate" to set delay for the
> deferred io. The refresh rate is given in units of Hertz. The default
> refresh rate is 1 Hz. The refresh rate set through the newly introduced
> parameter applies to all instances of the driver and for now it is not
> possible to change it individually.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
>  1 file changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 6fecec8..8a8d305 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -42,6 +42,11 @@
>  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
>  #define	SSD1307FB_SET_VCOMH		0xdb
>  
> +#define REFRASHRATE 1
> +
> +static u_int refreshrate = REFRASHRATE;

s/REFRASH/REFRESH/ :)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv4 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast
  2015-03-16 17:11   ` [PATCHv4 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
@ 2015-03-19 13:22     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-19 13:22 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Mon, Mar 16, 2015 at 06:11:57PM +0100, Thomas Niederprüm wrote:
> The backlight class is used to create userspace handles for
> setting the OLED contrast.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-14 22:02               ` Geert Uytterhoeven
@ 2015-03-20 11:37                 ` Tomi Valkeinen
  2015-03-20 12:12                   ` Geert Uytterhoeven
  2015-03-20 14:47                   ` Maxime Ripard
  0 siblings, 2 replies; 138+ messages in thread
From: Tomi Valkeinen @ 2015-03-20 11:37 UTC (permalink / raw)
  To: Geert Uytterhoeven, Thomas Niederprüm
  Cc: Maxime Ripard, Linux Fbdev development list,
	Jean-Christophe PLAGNIOL-VILLARD, linux-kernel

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

On 15/03/15 00:02, Geert Uytterhoeven wrote:
> On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
> <niederp@physik.uni-kl.de> wrote:
>> Am Tue, 10 Mar 2015 13:28:25 +0200
>> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
>>> Also, isn't doing __pa() for the memory returned by vmalloc plain
>>> wrong?
>>
>>> What was the crash about when using kmalloc? It would be good to fix
>>> defio, as I don't see why it should not work with kmalloced memory.
>>
>> The main challenge here is that the memory handed to userspace upon
>> mmap call needs to be page aligned. The memory returned by kmalloc has
>> no such alignment, but the pointer presented to the userspace program
>> gets aligned to next page boundary. It's not clear to me whether there
>> is an easy way to obtain page aligned kmalloc memory. Memory
>> allocated by vmalloc on the other hand is always aligned to page
>> boundaries. This is why I chose to go for vmalloc.
> 
> __get_free_pages()?

I'm not that experienced with mem management, so I have to ask...
__get_free_pages() probably works fine, but isn't vmalloc better here?

__get_free_pages() will give you possibly a lot more memory than you
need. And the memory is contiguous, so it could be difficult to allocate
a larger memory area. The driver doesn't need contiguous memory (except
in the virtual sense).

 Tomi



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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-20 11:37                 ` Tomi Valkeinen
@ 2015-03-20 12:12                   ` Geert Uytterhoeven
  2015-03-20 14:47                   ` Maxime Ripard
  1 sibling, 0 replies; 138+ messages in thread
From: Geert Uytterhoeven @ 2015-03-20 12:12 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Thomas Niederprüm, Maxime Ripard,
	Linux Fbdev development list, Jean-Christophe PLAGNIOL-VILLARD,
	linux-kernel

On Fri, Mar 20, 2015 at 12:37 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On 15/03/15 00:02, Geert Uytterhoeven wrote:
>> On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
>> <niederp@physik.uni-kl.de> wrote:
>>> Am Tue, 10 Mar 2015 13:28:25 +0200
>>> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
>>>> Also, isn't doing __pa() for the memory returned by vmalloc plain
>>>> wrong?
>>>
>>>> What was the crash about when using kmalloc? It would be good to fix
>>>> defio, as I don't see why it should not work with kmalloced memory.
>>>
>>> The main challenge here is that the memory handed to userspace upon
>>> mmap call needs to be page aligned. The memory returned by kmalloc has
>>> no such alignment, but the pointer presented to the userspace program
>>> gets aligned to next page boundary. It's not clear to me whether there
>>> is an easy way to obtain page aligned kmalloc memory. Memory
>>> allocated by vmalloc on the other hand is always aligned to page
>>> boundaries. This is why I chose to go for vmalloc.
>>
>> __get_free_pages()?
>
> I'm not that experienced with mem management, so I have to ask...
> __get_free_pages() probably works fine, but isn't vmalloc better here?
>
> __get_free_pages() will give you possibly a lot more memory than you
> need. And the memory is contiguous, so it could be difficult to allocate
> a larger memory area. The driver doesn't need contiguous memory (except
> in the virtual sense).

I was responding to the question about obtaining page aligned kmalloc
memory.
If it doesn't need to be physically contiguous, vmalloc() is fine.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-20 11:37                 ` Tomi Valkeinen
  2015-03-20 12:12                   ` Geert Uytterhoeven
@ 2015-03-20 14:47                   ` Maxime Ripard
  2015-03-20 15:24                     ` Geert Uytterhoeven
  2015-03-20 15:25                     ` Tomi Valkeinen
  1 sibling, 2 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-20 14:47 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Geert Uytterhoeven, Thomas Niederprüm,
	Linux Fbdev development list, Jean-Christophe PLAGNIOL-VILLARD,
	linux-kernel

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

On Fri, Mar 20, 2015 at 01:37:50PM +0200, Tomi Valkeinen wrote:
> On 15/03/15 00:02, Geert Uytterhoeven wrote:
> > On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
> > <niederp@physik.uni-kl.de> wrote:
> >> Am Tue, 10 Mar 2015 13:28:25 +0200
> >> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
> >>> Also, isn't doing __pa() for the memory returned by vmalloc plain
> >>> wrong?
> >>
> >>> What was the crash about when using kmalloc? It would be good to fix
> >>> defio, as I don't see why it should not work with kmalloced memory.
> >>
> >> The main challenge here is that the memory handed to userspace upon
> >> mmap call needs to be page aligned. The memory returned by kmalloc has
> >> no such alignment, but the pointer presented to the userspace program
> >> gets aligned to next page boundary. It's not clear to me whether there
> >> is an easy way to obtain page aligned kmalloc memory. Memory
> >> allocated by vmalloc on the other hand is always aligned to page
> >> boundaries. This is why I chose to go for vmalloc.
> > 
> > __get_free_pages()?
> 
> I'm not that experienced with mem management, so I have to ask...
> __get_free_pages() probably works fine, but isn't vmalloc better here?
> 
> __get_free_pages() will give you possibly a lot more memory than you
> need. And the memory is contiguous, so it could be difficult to allocate
> a larger memory area. The driver doesn't need contiguous memory (except
> in the virtual sense).

vmalloc also returns pages, so the size will be page-aligned. It
doesn't make much of a difference here, since we will only use a
single page in both case (the max resolution of these screens is
128x39, with one bit per pixel).

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-20 14:47                   ` Maxime Ripard
@ 2015-03-20 15:24                     ` Geert Uytterhoeven
  2015-03-20 20:27                       ` Thomas Niederprüm
  2015-03-20 15:25                     ` Tomi Valkeinen
  1 sibling, 1 reply; 138+ messages in thread
From: Geert Uytterhoeven @ 2015-03-20 15:24 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tomi Valkeinen, Thomas Niederprüm,
	Linux Fbdev development list, Jean-Christophe PLAGNIOL-VILLARD,
	linux-kernel

On Fri, Mar 20, 2015 at 3:47 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Fri, Mar 20, 2015 at 01:37:50PM +0200, Tomi Valkeinen wrote:
>> On 15/03/15 00:02, Geert Uytterhoeven wrote:
>> > On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
>> > <niederp@physik.uni-kl.de> wrote:
>> >> Am Tue, 10 Mar 2015 13:28:25 +0200
>> >> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
>> >>> Also, isn't doing __pa() for the memory returned by vmalloc plain
>> >>> wrong?
>> >>
>> >>> What was the crash about when using kmalloc? It would be good to fix
>> >>> defio, as I don't see why it should not work with kmalloced memory.
>> >>
>> >> The main challenge here is that the memory handed to userspace upon
>> >> mmap call needs to be page aligned. The memory returned by kmalloc has
>> >> no such alignment, but the pointer presented to the userspace program
>> >> gets aligned to next page boundary. It's not clear to me whether there
>> >> is an easy way to obtain page aligned kmalloc memory. Memory
>> >> allocated by vmalloc on the other hand is always aligned to page
>> >> boundaries. This is why I chose to go for vmalloc.
>> >
>> > __get_free_pages()?
>>
>> I'm not that experienced with mem management, so I have to ask...
>> __get_free_pages() probably works fine, but isn't vmalloc better here?
>>
>> __get_free_pages() will give you possibly a lot more memory than you
>> need. And the memory is contiguous, so it could be difficult to allocate
>> a larger memory area. The driver doesn't need contiguous memory (except
>> in the virtual sense).
>
> vmalloc also returns pages, so the size will be page-aligned. It
> doesn't make much of a difference here, since we will only use a
> single page in both case (the max resolution of these screens is
> 128x39, with one bit per pixel).

In that case I recommend get_zeroed_page(), to avoid the vmalloc()
overhead of setting up a mapping.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-20 14:47                   ` Maxime Ripard
  2015-03-20 15:24                     ` Geert Uytterhoeven
@ 2015-03-20 15:25                     ` Tomi Valkeinen
  2015-03-20 20:36                       ` Thomas Niederprüm
  1 sibling, 1 reply; 138+ messages in thread
From: Tomi Valkeinen @ 2015-03-20 15:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Geert Uytterhoeven, Thomas Niederprüm,
	Linux Fbdev development list, Jean-Christophe PLAGNIOL-VILLARD,
	linux-kernel

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

On 20/03/15 16:47, Maxime Ripard wrote:
> On Fri, Mar 20, 2015 at 01:37:50PM +0200, Tomi Valkeinen wrote:
>> On 15/03/15 00:02, Geert Uytterhoeven wrote:
>>> On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
>>> <niederp@physik.uni-kl.de> wrote:
>>>> Am Tue, 10 Mar 2015 13:28:25 +0200
>>>> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
>>>>> Also, isn't doing __pa() for the memory returned by vmalloc plain
>>>>> wrong?
>>>>
>>>>> What was the crash about when using kmalloc? It would be good to fix
>>>>> defio, as I don't see why it should not work with kmalloced memory.
>>>>
>>>> The main challenge here is that the memory handed to userspace upon
>>>> mmap call needs to be page aligned. The memory returned by kmalloc has
>>>> no such alignment, but the pointer presented to the userspace program
>>>> gets aligned to next page boundary. It's not clear to me whether there
>>>> is an easy way to obtain page aligned kmalloc memory. Memory
>>>> allocated by vmalloc on the other hand is always aligned to page
>>>> boundaries. This is why I chose to go for vmalloc.
>>>
>>> __get_free_pages()?
>>
>> I'm not that experienced with mem management, so I have to ask...
>> __get_free_pages() probably works fine, but isn't vmalloc better here?
>>
>> __get_free_pages() will give you possibly a lot more memory than you
>> need. And the memory is contiguous, so it could be difficult to allocate
>> a larger memory area. The driver doesn't need contiguous memory (except
>> in the virtual sense).
> 
> vmalloc also returns pages, so the size will be page-aligned. It
> doesn't make much of a difference here, since we will only use a
> single page in both case (the max resolution of these screens is
> 128x39, with one bit per pixel).

Ok, that's not much, then =).

In that case __get_free_pages sounds fine. Even if the resolution would
be slightly higher, we're only talking about a page or two extra.

Usually double-underscore in front of a func means "don't call this". I
don't know why this one has the underscores.

 Tomi



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

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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-20 15:24                     ` Geert Uytterhoeven
@ 2015-03-20 20:27                       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-20 20:27 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Maxime Ripard, Tomi Valkeinen, Linux Fbdev development list,
	Jean-Christophe PLAGNIOL-VILLARD, linux-kernel

Am Fri, 20 Mar 2015 16:24:29 +0100
schrieb Geert Uytterhoeven <geert@linux-m68k.org>:

> On Fri, Mar 20, 2015 at 3:47 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > On Fri, Mar 20, 2015 at 01:37:50PM +0200, Tomi Valkeinen wrote:
> >> On 15/03/15 00:02, Geert Uytterhoeven wrote:
> >> > On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
> >> > <niederp@physik.uni-kl.de> wrote:
> >> >> Am Tue, 10 Mar 2015 13:28:25 +0200
> >> >> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
> >> >>> Also, isn't doing __pa() for the memory returned by vmalloc
> >> >>> plain wrong?
> >> >>
> >> >>> What was the crash about when using kmalloc? It would be good
> >> >>> to fix defio, as I don't see why it should not work with
> >> >>> kmalloced memory.
> >> >>
> >> >> The main challenge here is that the memory handed to userspace
> >> >> upon mmap call needs to be page aligned. The memory returned by
> >> >> kmalloc has no such alignment, but the pointer presented to the
> >> >> userspace program gets aligned to next page boundary. It's not
> >> >> clear to me whether there is an easy way to obtain page aligned
> >> >> kmalloc memory. Memory allocated by vmalloc on the other hand
> >> >> is always aligned to page boundaries. This is why I chose to go
> >> >> for vmalloc.
> >> >
> >> > __get_free_pages()?
> >>
> >> I'm not that experienced with mem management, so I have to ask...
> >> __get_free_pages() probably works fine, but isn't vmalloc better
> >> here?
> >>
> >> __get_free_pages() will give you possibly a lot more memory than
> >> you need. And the memory is contiguous, so it could be difficult
> >> to allocate a larger memory area. The driver doesn't need
> >> contiguous memory (except in the virtual sense).
> >
> > vmalloc also returns pages, so the size will be page-aligned. It
> > doesn't make much of a difference here, since we will only use a
> > single page in both case (the max resolution of these screens is
> > 128x39, with one bit per pixel).
> 
> In that case I recommend get_zeroed_page(), to avoid the vmalloc()
> overhead of setting up a mapping.

I looked into get_zeroed_page() too but I thought __get_free_pages()
might be more future proof since get_zeroed_page() will not reserve
enough memory if more than one page is needed. This might occur if a new
controller pops up that has more pixels than bits in a page or the
driver is used on a system with a small page size. Also
get_zeroed_page() is also just calling __get_free_pages() with the
order parameter set to 0. Therefore I think a call like

__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(size)) 

does the same as get_zeroed_page() if only one page is needed but has
the ability to reserve more pages if needed.

Thomas


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

* Re: [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory.
  2015-03-20 15:25                     ` Tomi Valkeinen
@ 2015-03-20 20:36                       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-20 20:36 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Maxime Ripard, Geert Uytterhoeven, Linux Fbdev development list,
	Jean-Christophe PLAGNIOL-VILLARD, linux-kernel

Am Fri, 20 Mar 2015 17:25:29 +0200
schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:

> On 20/03/15 16:47, Maxime Ripard wrote:
> > On Fri, Mar 20, 2015 at 01:37:50PM +0200, Tomi Valkeinen wrote:
> >> On 15/03/15 00:02, Geert Uytterhoeven wrote:
> >>> On Fri, Mar 13, 2015 at 10:31 PM, Thomas Niederprüm
> >>> <niederp@physik.uni-kl.de> wrote:
> >>>> Am Tue, 10 Mar 2015 13:28:25 +0200
> >>>> schrieb Tomi Valkeinen <tomi.valkeinen@ti.com>:
> >>>>> Also, isn't doing __pa() for the memory returned by vmalloc
> >>>>> plain wrong?
> >>>>
> >>>>> What was the crash about when using kmalloc? It would be good
> >>>>> to fix defio, as I don't see why it should not work with
> >>>>> kmalloced memory.
> >>>>
> >>>> The main challenge here is that the memory handed to userspace
> >>>> upon mmap call needs to be page aligned. The memory returned by
> >>>> kmalloc has no such alignment, but the pointer presented to the
> >>>> userspace program gets aligned to next page boundary. It's not
> >>>> clear to me whether there is an easy way to obtain page aligned
> >>>> kmalloc memory. Memory allocated by vmalloc on the other hand is
> >>>> always aligned to page boundaries. This is why I chose to go for
> >>>> vmalloc.
> >>>
> >>> __get_free_pages()?
> >>
> >> I'm not that experienced with mem management, so I have to ask...
> >> __get_free_pages() probably works fine, but isn't vmalloc better
> >> here?
> >>
> >> __get_free_pages() will give you possibly a lot more memory than
> >> you need. And the memory is contiguous, so it could be difficult
> >> to allocate a larger memory area. The driver doesn't need
> >> contiguous memory (except in the virtual sense).
> > 
> > vmalloc also returns pages, so the size will be page-aligned. It
> > doesn't make much of a difference here, since we will only use a
> > single page in both case (the max resolution of these screens is
> > 128x39, with one bit per pixel).
> 
> Ok, that's not much, then =).
> 
> In that case __get_free_pages sounds fine. Even if the resolution
> would be slightly higher, we're only talking about a page or two
> extra.
> 
> Usually double-underscore in front of a func means "don't call this".
> I don't know why this one has the underscores.

This irritated me as well. But since it turned out that there is even a
section on "get_free_page and Friends" in LDD3 that talks about
__get_free_pages() without any word of caution, I assumed it's ok to
call this functions.

Thomas

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

* Re: [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-18 19:27     ` Maxime Ripard
@ 2015-03-20 21:12       ` Thomas Niederprüm
  2015-03-24 15:24         ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-20 21:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

Am Wed, 18 Mar 2015 20:27:19 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> Hi Thomas,
> 
> On Mon, Mar 16, 2015 at 06:11:52PM +0100, Thomas Niederprüm wrote:
> > The 130X controllers are very similar from the configuration point
> > of view. The configuration registers for the SSD1305/6/7 are bit
> > identical (except the the VHCOM register and the the default values
> > for clock setup register). This patch unifies the init code of the
> > controller and adds hardware specific properties to DT that are
> > needed to correctly initialize the device.
> > 
> > The SSD130X can be wired to the OLED panel in various ways. Even
> > for the same controller this wiring can differ from one display
> > module to another and can not be probed by software. The added DT
> > properties reflect these hardware decisions of the display module
> > manufacturer. The 'com-sequential', 'com-lrremap' and 'com-invdir'
> > values define different possibilities for the COM signals pin
> > configuration and readout direction of the video memory. The
> > 'segment-no-remap' allows the inversion of the memory-to-pin
> > mapping ultimately inverting the order of the controllers output
> > pins. The 'prechargepX' values need to be adapted according the
> > capacitance of the OLEDs pixel cells.
> > 
> > So far these hardware specific bits are hard coded in the init
> > code, making the driver usable only for one certain wiring of the
> > controller. This patch makes the driver usable with all possible
> > hardware setups, given a valid hw description in DT. If these
> > values are not set in DT the default values, as they are set in the
> > ssd1307 init code right now, are used. This implies that without
> > the corresponding DT property "segment-no-remap" the segment remap
> > of the ssd130X controller gets activated. Even though this is not
> > the default behaviour according to the datasheet it maintains
> > backward compatibility with older DTBs.
> > 
> > Note that the SSD1306 does not seem to be using the configuration
> > written to the registers at all. Therefore this patch does not try
> > to maintain these values without changes in DT. For reference an
> > example is added to the DT bindings documentation that reproduces
> > the configuration that is set in the current init code.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> This looks mostly fine, thanks for your effort on this.
> 
> > ---
> >  .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
> >  drivers/video/fbdev/ssd1307fb.c                    | 195
> > ++++++++++++--------- 2 files changed, 137 insertions(+), 79
> > deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > 7a12542..be27562 100644 ---
> > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
> > +15,16 @@ Required properties: 
> >  Optional properties:
> >    - reset-active-low: Is the reset gpio is active on physical low?
> > +  - solomon,segment-no-remap: Display needs normal (non-inverted)
> > data column
> > +                              to segment mapping
> > +  - solomon,com-sequential: Display uses sequential COM pin
> > configuration
> > +  - solomon,com-lrremap: Display uses left-right COM pin remap
> > +  - solomon,com-invdir: Display uses inverted COM pin scan
> > direction
> > +  - solomon,com-offset: Offset of the first COM pin wired to the
> > panel
> 
> Documenting the offset unit would be fine.

The com-offset determines which line of the display panel should
receive the first line of video memory. When designing your display
module you could decide to do something crazy and connect the first
lines of your panel to  (for example) pin COM32 onward. By setting the
com-offset to 32 you could still recover the correct image on your
panel. So in some sense the unit of the com-offset is display lines or
number of pins, depending on whether you see it from the controller
side or from the panel side. I will update the documentation to reflect
this.

> 
> > +  - solomon,prechargep1: Length of deselect period (phase 1) in
> > clock cycles.
> > +  - solomon,prechargep2: Length of precharge period (phase 2) in
> > clock cycles.
> > +                         This needs to be the higher, the higher
> > the capacitance
> > +                         of the OLED's pixels is
> >  
> >  [0]: Documentation/devicetree/bindings/pwm/pwm.txt
> >  
> > @@ -26,3 +36,14 @@ ssd1307: oled@3c {
> >          reset-gpios = <&gpio2 7>;
> >          reset-active-low;
> >  };
> > +
> > +ssd1306: oled@3c {
> > +        compatible = "solomon,ssd1306fb-i2c";
> > +        reg = <0x3c>;
> > +        pwms = <&pwm 4 3000>;
> > +        reset-gpios = <&gpio2 7>;
> > +        reset-active-low;
> > +        solomon,com-lrremap;
> > +        solomon,com-invdir;
> > +        solomon,com-offset = <32>;
> > +};
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 8d34c56..9a66118 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -16,6 +16,9 @@
> >  #include <linux/pwm.h>
> >  #include <linux/delay.h>
> >  
> > +#define DEVID_SSD1306 6
> > +#define DEVID_SSD1307 7
> > +
> >  #define SSD1307FB_DATA			0x40
> >  #define SSD1307FB_COMMAND		0x80
> >  
> > @@ -38,22 +41,38 @@
> >  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
> >  #define	SSD1307FB_SET_VCOMH		0xdb
> >  
> > +static u_int contrast = 128;
> > +module_param(contrast, uint, S_IRUGO);
> > +
> 
> Why is this patch adding a contrast parameter? You don't even mention
> it in your commit log. This should be a separate patch.

I agree, this should disappear or go into another patch. Since the
contrast can also be set through the backlight class, I wonder whether
it is useful to keep this module parameter. I'm using it right now to
set the initial contrast as in my use case I almost always want the
smallest possible contrast setting. In any case I will split this into
a separate patch.
 
> >  struct ssd1307fb_par;
> >  
> > -struct ssd1307fb_ops {
> > -	int (*init)(struct ssd1307fb_par *);
> > -	int (*remove)(struct ssd1307fb_par *);
> > +struct ssd1307fb_deviceinfo {
> > +	int device_id;
> > +	u32 default_vcomh;
> > +	u32 default_dclk_div;
> > +	u32 default_dclk_frq;
> >  };
> >  
> >  struct ssd1307fb_par {
> > +	u32 com_invdir;
> > +	u32 com_lrremap;
> > +	u32 com_offset;
> > +	u32 com_seq;
> > +	u32 contrast;
> > +	u32 dclk_div;
> > +	u32 dclk_frq;
> > +	struct ssd1307fb_deviceinfo *device_info;
> >  	struct i2c_client *client;
> >  	u32 height;
> >  	struct fb_info *info;
> > -	struct ssd1307fb_ops *ops;
> >  	u32 page_offset;
> > +	u32 prechargep1;
> > +	u32 prechargep2;
> >  	struct pwm_device *pwm;
> >  	u32 pwm_period;
> >  	int reset;
> > +	u32 seg_remap;
> > +	u32 vcomh;
> >  	u32 width;
> >  };
> >  
> > @@ -254,69 +273,46 @@ static struct fb_deferred_io ssd1307fb_defio
> > = { .deferred_io	= ssd1307fb_deferred_io,
> >  };
> >  
> > -static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
> > +static int ssd1307fb_init(struct ssd1307fb_par *par)
> >  {
> >  	int ret;
> > +	u32 precharge, dclk, com_invdir, compins;
> >  
> > -	par->pwm = pwm_get(&par->client->dev, NULL);
> > -	if (IS_ERR(par->pwm)) {
> > -		dev_err(&par->client->dev, "Could not get PWM from
> > device tree!\n");
> > -		return PTR_ERR(par->pwm);
> > -	}
> > -
> > -	par->pwm_period = pwm_get_period(par->pwm);
> > -	/* Enable the PWM */
> > -	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> > -	pwm_enable(par->pwm);
> > -
> > -	dev_dbg(&par->client->dev, "Using PWM%d with a %dns
> > period.\n",
> > -		par->pwm->pwm, par->pwm_period);
> > -
> > -	/* Map column 127 of the OLED to segment 0 */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	/* Turn on the display */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_ON);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	return 0;
> > -}
> > -
> > -static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
> > -{
> > -	pwm_disable(par->pwm);
> > -	pwm_put(par->pwm);
> > -	return 0;
> > -}
> > +	if (par->device_info->device_id == DEVID_SSD1307) {
> > +		par->pwm = pwm_get(&par->client->dev, NULL);
> > +		if (IS_ERR(par->pwm)) {
> > +			dev_err(&par->client->dev, "Could not get
> > PWM from device tree!\n");
> > +			return PTR_ERR(par->pwm);
> > +		}
> >  
> > -static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
> > -	.init	= ssd1307fb_ssd1307_init,
> > -	.remove	= ssd1307fb_ssd1307_remove,
> > -};
> > +		par->pwm_period = pwm_get_period(par->pwm);
> > +		/* Enable the PWM */
> > +		pwm_config(par->pwm, par->pwm_period / 2,
> > par->pwm_period);
> > +		pwm_enable(par->pwm);
> >  
> > -static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
> > -{
> > -	int ret;
> > +		dev_dbg(&par->client->dev, "Using PWM%d with a
> > %dns period.\n",
> > +			par->pwm->pwm, par->pwm_period);
> > +	};
> >  
> >  	/* Set initial contrast */
> >  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x7f);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	/* Set COM direction */
> > -	ret = ssd1307fb_write_cmd(par->client, 0xc8);
> > +	ret = ssd1307fb_write_cmd(par->client, par->contrast);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set segment re-map */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > +	if (par->seg_remap) {
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> > +
> > +	/* Set COM direction */
> > +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> > +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -334,34 +330,38 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x20);
> > +	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set clock frequency */
> > +	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_CLOCK_FREQ); if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0xf0);
> > +	ret = ssd1307fb_write_cmd(par->client, dclk);
> 
> It would make more sense to assign the variable where you use it.
I will move the assignment right in front of the write command.
 
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set precharge period in number of ticks from the
> > internal clock */
> > +	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 &
> > 0xf) << 4; ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_PRECHARGE_PERIOD); if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> > +	ret = ssd1307fb_write_cmd(par->client, precharge);
> 
> Here too.
> 
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set COM pins configuration */
> > +	compins = 0x02 | (!par->com_seq & 0x1) << 4
> > +				   | (par->com_lrremap & 0x1) << 5;
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_COM_PINS_CONFIG); if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> > +	ret = ssd1307fb_write_cmd(par->client, compins);
> 
> And here.
> 
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -370,18 +370,20 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x49);
> > +	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	/* Turn on the DC-DC Charge Pump */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_CHARGE_PUMP);
> > -	if (ret < 0)
> > -		return ret;
> > +	if (par->device_info->device_id == DEVID_SSD1306) {
> > +		/* Turn on the DC-DC Charge Pump */
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_CHARGE_PUMP);
> > +		if (ret < 0)
> > +			return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x14);
> > -	if (ret < 0)
> > -		return ret;
> > +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> >  
> >  	/* Switch to horizontal addressing mode */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_ADDRESS_MODE); @@ -393,6 +395,7 @@ static int
> > ssd1307fb_ssd1306_init(struct ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > +    /* Set column range */
> 
> The indentation is wrong.
Im surprised that I didn't see that myself, because the way it
highlighted is hard to miss. However, thank you for catching this.

> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_COL_RANGE); if (ret < 0)
> >  		return ret;
> > @@ -405,6 +408,7 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > +    /* Set page range */
> 
> Here too.
> 
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_PAGE_RANGE); if (ret < 0)
> >  		return ret;
> > @@ -426,18 +430,28 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) return 0;
> >  }
> >  
> > -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> > -	.init	= ssd1307fb_ssd1306_init,
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> > +	.device_id  = DEVID_SSD1306,
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 0,
> > +	.default_dclk_frq = 8,
> > +};
> > +
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> > +	.device_id  = DEVID_SSD1307,
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 1,
> > +	.default_dclk_frq = 12,
> >  };
> >  
> >  static const struct of_device_id ssd1307fb_of_match[] = {
> >  	{
> >  		.compatible = "solomon,ssd1306fb-i2c",
> > -		.data = (void *)&ssd1307fb_ssd1306_ops,
> > +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
> >  	},
> >  	{
> >  		.compatible = "solomon,ssd1307fb-i2c",
> > -		.data = (void *)&ssd1307fb_ssd1307_ops,
> > +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
> 
> Do we need this ID? Wouldn't it make more sense to pass the pointer to
> the struct we need to use?

Are you talking about the device_id inside the struct
ssd1307_deviceinfo? I need the device_id to serve special needs of the
individual controllers during initialization. For example the ssd1307
needs to set up the pwm in the init code. 


> >  	},
> >  	{},
> >  };
> > @@ -468,8 +482,8 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, par->info = info;
> >  	par->client = client;
> >  
> > -	par->ops = (struct ssd1307fb_ops
> > *)of_match_device(ssd1307fb_of_match,
> > -
> > &client->dev)->data;
> > +	par->device_info = (struct ssd1307fb_deviceinfo
> > *)of_match_device(
> > +			ssd1307fb_of_match, &client->dev)->data;
> >  
> >  	par->reset = of_get_named_gpio(client->dev.of_node,
> >  					 "reset-gpios", 0);
> > @@ -487,6 +501,27 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, if (of_property_read_u32(node, "solomon,page-offset",
> > &par->page_offset)) par->page_offset = 1;
> >  
> > +	if (of_property_read_u32(node, "solomon,com-offset",
> > &par->com_offset))
> > +		par->com_offset = 0;
> > +
> > +	if (of_property_read_u32(node, "solomon,prechargep1",
> > &par->prechargep1))
> > +		par->prechargep1 = 2;
> > +
> > +	if (of_property_read_u32(node, "solomon,prechargep2",
> > &par->prechargep2))
> > +		par->prechargep2 = 0;
> > +
> > +	par->seg_remap = !of_property_read_bool(node,
> > "solomon,segment-no-remap");
> > +	par->com_seq = of_property_read_bool(node,
> > "solomon,com-sequential");
> > +	par->com_lrremap = of_property_read_bool(node,
> > "solomon,com-lrremap");
> > +	par->com_invdir = of_property_read_bool(node,
> > "solomon,com-invdir"); +
> > +	par->contrast = contrast;
> > +	par->vcomh = par->device_info->default_vcomh;
> > +
> > +	/* Setup display timing */
> > +	par->dclk_div = par->device_info->default_dclk_div;
> > +	par->dclk_frq = par->device_info->default_dclk_frq;
> > +
> >  	vmem_size = par->width * par->height / 8;
> >  
> >  	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
> > @@ -539,11 +574,9 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, gpio_set_value(par->reset, 1);
> >  	udelay(4);
> >  
> > -	if (par->ops->init) {
> > -		ret = par->ops->init(par);
> > -		if (ret)
> > -			goto reset_oled_error;
> > -	}
> > +	ret = ssd1307fb_init(par);
> > +	if (ret)
> > +		goto reset_oled_error;
> >  
> >  	ret = register_framebuffer(info);
> >  	if (ret) {
> > @@ -556,8 +589,10 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, return 0;
> >  
> >  panel_init_error:
> > -	if (par->ops->remove)
> > -		par->ops->remove(par);
> > +	if (par->device_info->device_id == DEVID_SSD1307) {
> > +		pwm_disable(par->pwm);
> > +		pwm_put(par->pwm);
> > +	};
> >  reset_oled_error:
> >  	fb_deferred_io_cleanup(info);
> >  fb_alloc_error:
> > @@ -571,8 +606,10 @@ static int ssd1307fb_remove(struct i2c_client
> > *client) struct ssd1307fb_par *par = info->par;
> >  
> >  	unregister_framebuffer(info);
> > -	if (par->ops->remove)
> > -		par->ops->remove(par);
> > +	if (par->device_info->device_id == DEVID_SSD1307) {
> > +		pwm_disable(par->pwm);
> > +		pwm_put(par->pwm);
> > +	};
> >  	fb_deferred_io_cleanup(info);
> >  	__free_pages(__va(info->fix.smem_start),
> > get_order(info->fix.smem_len)); framebuffer_release(info);
> > -- 
> > 2.3.0
> > 

Thomas


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

* Re: [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  2015-03-19 13:18     ` Maxime Ripard
@ 2015-03-20 21:16       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-20 21:16 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

Am Thu, 19 Mar 2015 14:18:24 +0100
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Mon, Mar 16, 2015 at 06:11:55PM +0100, Thomas Niederprüm wrote:
> > This patch adds the module parameter "refreshrate" to set delay for
> > the deferred io. The refresh rate is given in units of Hertz. The
> > default refresh rate is 1 Hz. The refresh rate set through the
> > newly introduced parameter applies to all instances of the driver
> > and for now it is not possible to change it individually.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
> >  1 file changed, 17 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 6fecec8..8a8d305 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -42,6 +42,11 @@
> >  #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
> >  #define	SSD1307FB_SET_VCOMH		0xdb
> >  
> > +#define REFRASHRATE 1
> > +
> > +static u_int refreshrate = REFRASHRATE;
> 
> s/REFRASH/REFRESH/ :)

It's written the wrong way and the right way in the same line :) Of
course I will fix that.

Thanks,
Thomas

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

* Re: [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-20 21:12       ` Thomas Niederprüm
@ 2015-03-24 15:24         ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-24 15:24 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Fri, Mar 20, 2015 at 10:12:54PM +0100, Thomas Niederprüm wrote:
> > >  static const struct of_device_id ssd1307fb_of_match[] = {
> > >  	{
> > >  		.compatible = "solomon,ssd1306fb-i2c",
> > > -		.data = (void *)&ssd1307fb_ssd1306_ops,
> > > +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
> > >  	},
> > >  	{
> > >  		.compatible = "solomon,ssd1307fb-i2c",
> > > -		.data = (void *)&ssd1307fb_ssd1307_ops,
> > > +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
> > 
> > Do we need this ID? Wouldn't it make more sense to pass the pointer to
> > the struct we need to use?
> 
> Are you talking about the device_id inside the struct
> ssd1307_deviceinfo?

Yes.

> I need the device_id to serve special needs of the individual
> controllers during initialization. For example the ssd1307 needs to
> set up the pwm in the init code.

Then you can add a bool in the structure to say whether it needs a PWM
or not.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* [PATCHv5 00/11] Cleanup and add support for SSD1305
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (10 preceding siblings ...)
  2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-24 21:23 ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 01/11] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
                     ` (10 more replies)
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
  12 siblings, 11 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

Hi,

this patch series is the result of making the ssd1307fb driver work with
a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
this the intialization code for the SSD1306 and the SSD1307 is merged
and based on DT configuration to reflect the various possible wirings
of the SSD130X controller (04/11). Based on these changes it is straight
forward to add support for the SSD1305 controller (06/11).

While working on the driver I realized that it was not possible to
correctly mmap the video memory from userspace since the address handed
to the userspace app is a logical one where it should be a physical one.
Patch 01/10 fixes this. Furthermore the memory reserved by kzalloc is
not page aligned while the address handed to userspace is aligned to the
next page frame. This problem is fixed by using __get_free_pages() in 02/11.

Furthermore a module parameter is added to set the delay for the
deferred io update (07/11). Also the backlight class is implemented to make
the contrast setting available in userspace (10/11).

changes since v1 (thanks to Maxime for the feedback):
- dedicated patch for fixing smem_start address
- remove page reserve upon vmalloc
- remove return value check upon display turn-off at module unload
- use a module parameter refreshrate rather than delaydivider
- allocate fbdefio dynamically
- use sysfs_create_groups to create sysfs entries
- remove contrast, vhcom and dclk properties from DT since they are
  not part of hw description. The contrast module parameter was added
  to set contrast at load time. vhcom and dclk stays at it's default
  values for now.
- add new DT properties to in tree users of ssd130X
- rebased to apply on top of linux-next

changes since v2 (thanks to Maxime again):
- free memory allocated by vmalloc on driver unload
- set default values in the init code to the ones of the existing ssd1307
  init code
- added two ACKs (Maxime Ripard)

changes since v3:
- use backlight class rather than dedicated sysfs files to set the 
  contrast (Thanks to Tomi Valkeinen)
- remove [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel
- add new patch to blank the display (unreviewed)
- allocate video memory through __get_free_pages() rather than vmalloc
  (Thanks to Geert Uytterhoeven)
- minor rewordings of the commit messages

changes since v4 (thanks to Maxime):
- added two ACKs (Maxime Ripard)
- fixed typo: s/REFRASHRATE/REFRESHRATE
- updated the documentation to make clear the unit of com-offset
- move addition of the module parameter contrast to a separate patch (09/11)
- fix indentation errors
- get rid of device_id in the device_info struct


Thomas Niederprüm (11):
  fbdev: ssd1307fb: fix memory address smem_start.
  fbdev: ssd1307fb: Allocate page aligned video memory.
  of: Add Solomon Systech vendor prefix.
  fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  ARM: mxs: fix in tree users of ssd1306
  fbdev: ssd1307fb: Add support for SSD1305
  fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  fbdev: ssd1307fb: Turn off display on driver unload.
  fbdev: ssd1307fb: Add module parameter to set the initial contrast
  fbdev: ssd1307fb: add backlight controls for setting the contrast
  fbdev: ssd1307fb: Add blank mode

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../devicetree/bindings/video/ssd1307fb.txt        |  23 +-
 arch/arm/boot/dts/imx28-cfa10036.dts               |   3 +
 drivers/video/fbdev/Kconfig                        |   1 +
 drivers/video/fbdev/ssd1307fb.c                    | 310 +++++++++++++++------
 5 files changed, 250 insertions(+), 88 deletions(-)

-- 
2.3.0


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

* [PATCHv5 01/11] fbdev: ssd1307fb: fix memory address smem_start.
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 02/11] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

the smem_start pointer of the framebuffer info struct needs to hold the
physical address rather than the logical address. Right now the logical
address returned by kmalloc is stored. This patch converts this address
to a physical address and thus fixes a driver crash on mmaping the
framebuffer memory due to an access to the wrong memory address.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f7ed6d9..61e0ce8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -515,7 +515,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
 	fb_deferred_io_init(info);
-- 
2.3.0


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

* [PATCHv5 02/11] fbdev: ssd1307fb: Allocate page aligned video memory.
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 01/11] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 03/11] of: Add Solomon Systech vendor prefix Thomas Niederprüm
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

Currently the videomemory is allocated by kmalloc, making it a memory
region that is not necessarily page aligend. This leads to problems
upon mmap call, where the video memory's address gets aligned to the
next page boundary. The result is that the userspace program that issued
the mmap call is not able to access the video memory from the start to
the next page boundary.

This patch changes the allocation of the video memory to use
__get_free_pages() in order to obtain memory that is aligned
to page boundaries.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 61e0ce8..8d34c56 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -489,7 +489,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	vmem_size = par->width * par->height / 8;
 
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+					get_order(vmem_size));
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -573,6 +574,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	if (par->ops->remove)
 		par->ops->remove(par);
 	fb_deferred_io_cleanup(info);
+	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
 	framebuffer_release(info);
 
 	return 0;
-- 
2.3.0


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

* [PATCHv5 03/11] of: Add Solomon Systech vendor prefix.
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 01/11] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 02/11] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
                     ` (7 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the solomon prefix for Solomon Systech Limited.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d3f4809..933c8f5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -169,6 +169,7 @@ sitronix	Sitronix Technology Corporation
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
+solomon        Solomon Systech Limited
 sony	Sony Corporation
 spansion	Spansion Inc.
 sprd	Spreadtrum Communications Inc.
-- 
2.3.0


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

* [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (2 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 03/11] of: Add Solomon Systech vendor prefix Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 22:14     ` Maxime Ripard
  2015-03-25 15:49     ` Olliver Schinagl
  2015-03-24 21:23   ` [PATCHv5 05/11] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
                     ` (6 subsequent siblings)
  10 siblings, 2 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The 130X controllers are very similar from the configuration point of view.
The configuration registers for the SSD1305/6/7 are bit identical (except the
the VHCOM register and the the default values for clock setup register). This
patch unifies the init code of the controller and adds hardware specific
properties to DT that are needed to correctly initialize the device.

The SSD130X can be wired to the OLED panel in various ways. Even for the
same controller this wiring can differ from one display module to another
and can not be probed by software. The added DT properties reflect these
hardware decisions of the display module manufacturer.
The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
possibilities for the COM signals pin configuration and readout direction
of the video memory. The 'segment-no-remap' allows the inversion of the
memory-to-pin mapping ultimately inverting the order of the controllers
output pins. The 'prechargepX' values need to be adapted according to the
capacitance of the OLEDs pixel cells.

So far these hardware specific bits are hard coded in the init code, making
the driver usable only for one certain wiring of the controller. This patch
makes the driver usable with all possible hardware setups, given a valid hw
description in DT. If these values are not set in DT the default values,
as they are set in the ssd1307 init code right now, are used. This implies
that without the corresponding DT property "segment-no-remap" the segment
remap of the ssd130X controller gets activated. Even though this is not the
default behaviour according to the datasheet it maintains backward
compatibility with older DTBs.

Note that the SSD1306 does not seem to be using the configuration written to
the registers at all. Therefore this patch does not try to maintain these
values without changes in DT. For reference an example is added to the DT
bindings documentation that reproduces the configuration that is set in the
current init code.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
 drivers/video/fbdev/ssd1307fb.c                    | 192 ++++++++++++---------
 2 files changed, 134 insertions(+), 79 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 7a12542..637690f 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -15,6 +15,16 @@ Required properties:
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
+  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
+                              to segment mapping
+  - solomon,com-sequential: Display uses sequential COM pin configuration
+  - solomon,com-lrremap: Display uses left-right COM pin remap
+  - solomon,com-invdir: Display uses inverted COM pin scan direction
+  - solomon,com-offset: Number of the COM pin wired to the first display line
+  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
+  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
+                         This needs to be the higher, the higher the capacitance
+                         of the OLED's pixels is
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -26,3 +36,14 @@ ssd1307: oled@3c {
         reset-gpios = <&gpio2 7>;
         reset-active-low;
 };
+
+ssd1306: oled@3c {
+        compatible = "solomon,ssd1306fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+        solomon,com-lrremap;
+        solomon,com-invdir;
+        solomon,com-offset = <32>;
+};
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 8d34c56..d16aad4 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -40,20 +40,34 @@
 
 struct ssd1307fb_par;
 
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
+struct ssd1307fb_deviceinfo {
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
+	int need_pwm;
+	int need_chargepump;
 };
 
 struct ssd1307fb_par {
+	u32 com_invdir;
+	u32 com_lrremap;
+	u32 com_offset;
+	u32 com_seq;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	struct ssd1307fb_deviceinfo *device_info;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
 	u32 page_offset;
+	u32 prechargep1;
+	u32 prechargep2;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 seg_remap;
+	u32 vcomh;
 	u32 width;
 };
 
@@ -254,69 +268,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
+	u32 precharge, dclk, com_invdir, compins;
 
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
+	if (par->device_info->need_pwm) {
+		par->pwm = pwm_get(&par->client->dev, NULL);
+		if (IS_ERR(par->pwm)) {
+			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+			return PTR_ERR(par->pwm);
+		}
 
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
+		par->pwm_period = pwm_get_period(par->pwm);
+		/* Enable the PWM */
+		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+		pwm_enable(par->pwm);
 
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
+		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+			par->pwm->pwm, par->pwm_period);
+	};
 
 	/* Set initial contrast */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x7f);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
 	if (ret < 0)
 		return ret;
 
 	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (par->seg_remap) {
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	};
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
+	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
 	if (ret < 0)
 		return ret;
 
@@ -334,7 +325,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
 	if (ret < 0)
 		return ret;
 
@@ -343,7 +334,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0xf0);
+	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
+	ret = ssd1307fb_write_cmd(par->client, dclk);
 	if (ret < 0)
 		return ret;
 
@@ -352,7 +344,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
+	ret = ssd1307fb_write_cmd(par->client, precharge);
 	if (ret < 0)
 		return ret;
 
@@ -361,7 +354,9 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	compins = 0x02 | (!par->com_seq & 0x1) << 4
+				   | (par->com_lrremap & 0x1) << 5;
+	ret = ssd1307fb_write_cmd(par->client, compins);
 	if (ret < 0)
 		return ret;
 
@@ -370,18 +365,20 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x49);
+	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
 	if (ret < 0)
 		return ret;
 
-	/* Turn on the DC-DC Charge Pump */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
-	if (ret < 0)
-		return ret;
+	if (par->device_info->need_chargepump) {
+		/* Turn on the DC-DC Charge Pump */
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+		if (ret < 0)
+			return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x14);
-	if (ret < 0)
-		return ret;
+		ret = ssd1307fb_write_cmd(par->client, 0x14);
+		if (ret < 0)
+			return ret;
+	};
 
 	/* Switch to horizontal addressing mode */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
@@ -393,6 +390,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+	/* Set column range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
 	if (ret < 0)
 		return ret;
@@ -405,6 +403,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+	/* Set page range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
 	if (ret < 0)
 		return ret;
@@ -426,18 +425,30 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 8,
+	.need_pwm = 0,
+	.need_chargepump = 1,
+};
+
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 12,
+	.need_pwm = 1,
+	.need_chargepump = 0,
 };
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
 		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
+		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
 	{
 		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
+		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
 	},
 	{},
 };
@@ -468,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->info = info;
 	par->client = client;
 
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
+	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
+			ssd1307fb_of_match, &client->dev)->data;
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
@@ -487,6 +498,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
 		par->page_offset = 1;
 
+	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
+		par->com_offset = 0;
+
+	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
+		par->prechargep1 = 2;
+
+	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
+		par->prechargep2 = 0;
+
+	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
+	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
+	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
+	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
+
+	par->contrast = 127;
+	par->vcomh = par->device_info->default_vcomh;
+
+	/* Setup display timing */
+	par->dclk_div = par->device_info->default_dclk_div;
+	par->dclk_frq = par->device_info->default_dclk_frq;
+
 	vmem_size = par->width * par->height / 8;
 
 	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -539,11 +571,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	gpio_set_value(par->reset, 1);
 	udelay(4);
 
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
+	ret = ssd1307fb_init(par);
+	if (ret)
+		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
 	if (ret) {
@@ -556,8 +586,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	return 0;
 
 panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->need_pwm) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 fb_alloc_error:
@@ -571,8 +603,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->need_pwm) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 	fb_deferred_io_cleanup(info);
 	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
 	framebuffer_release(info);
-- 
2.3.0


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

* [PATCHv5 05/11] ARM: mxs: fix in tree users of ssd1306
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (3 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 06/11] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch updates the in tree-users of the SSD1306 controller for using
the newly introduced DT properties.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index b04b6b8..570aa33 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -99,6 +99,9 @@
 					solomon,height = <32>;
 					solomon,width = <128>;
 					solomon,page-offset = <0>;
+					solomon,com-lrremap;
+					solomon,com-invdir;
+					solomon,com-offset = <32>;
 				};
 			};
 
-- 
2.3.0


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

* [PATCHv5 06/11] fbdev: ssd1307fb: Add support for SSD1305
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (4 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 05/11] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 07/11] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
                     ` (4 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds support for the SSD1305 OLED controller.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/video/ssd1307fb.txt |  2 +-
 drivers/video/fbdev/ssd1307fb.c                       | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 637690f..acdf1ae 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -2,7 +2,7 @@
 
 Required properties:
   - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
-    now is i2c, and the supported chips are ssd1306 and ssd1307.
+    now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307.
   - reg: Should contain address of the controller on the I2C bus. Most likely
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index d16aad4..284c527 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -425,6 +425,14 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 0,
+	.default_dclk_frq = 7,
+	.need_pwm = 0,
+	.need_chargepump = 0,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
 	.default_vcomh = 0x20,
 	.default_dclk_div = 0,
@@ -443,6 +451,10 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1305_deviceinfo,
+	},
+	{
 		.compatible = "solomon,ssd1306fb-i2c",
 		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
@@ -615,6 +627,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1305fb", 0 },
 	{ "ssd1306fb", 0 },
 	{ "ssd1307fb", 0 },
 	{ }
-- 
2.3.0


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

* [PATCHv5 07/11] fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (5 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 06/11] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:54     ` Maxime Ripard
  2015-03-24 21:23   ` [PATCHv5 08/11] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
                     ` (3 subsequent siblings)
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the module parameter "refreshrate" to set delay for the
deferred io. The refresh rate is given in units of Hertz. The default
refresh rate is 1 Hz. The refresh rate set through the newly introduced
parameter applies to all instances of the driver and for now it is not
possible to change it individually.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 284c527..b38973e 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -38,6 +38,11 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define REFRESHRATE 1
+
+static u_int refreshrate = REFRESHRATE;
+module_param(refreshrate, uint, 0);
+
 struct ssd1307fb_par;
 
 struct ssd1307fb_deviceinfo {
@@ -263,11 +268,6 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 	ssd1307fb_update_display(info->par);
 }
 
-static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
-	.deferred_io	= ssd1307fb_deferred_io,
-};
-
 static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
@@ -471,6 +471,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 {
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
+	struct fb_deferred_io *ssd1307fb_defio;
 	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
@@ -541,10 +542,20 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto fb_alloc_error;
 	}
 
+	ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
+	if (!ssd1307fb_defio) {
+		dev_err(&client->dev, "Couldn't allocate deferred io.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	ssd1307fb_defio->delay = HZ / refreshrate;
+	ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io;
+
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
 	info->fix.line_length = par->width / 8;
-	info->fbdefio = &ssd1307fb_defio;
+	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
 	info->var.xres = par->width;
-- 
2.3.0


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

* [PATCHv5 08/11] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (6 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 07/11] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast Thomas Niederprüm
                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch turns off the display when the driver is unloaded.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index b38973e..6149827 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -625,6 +625,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct fb_info *info = i2c_get_clientdata(client);
 	struct ssd1307fb_par *par = info->par;
 
+	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+
 	unregister_framebuffer(info);
 	if (par->device_info->need_pwm) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (7 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 08/11] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 22:16     ` Maxime Ripard
  2015-03-24 21:23   ` [PATCHv5 10/11] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the module parameter "contrast" to determine the
contrast value that is used to initialize the display. This
setting applies to all instances of the driver.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 6149827..d5aec5c 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -43,6 +43,9 @@
 static u_int refreshrate = REFRESHRATE;
 module_param(refreshrate, uint, 0);
 
+static u_int contrast = 127;
+module_param(contrast, uint, S_IRUGO);
+
 struct ssd1307fb_par;
 
 struct ssd1307fb_deviceinfo {
@@ -525,7 +528,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
 	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
 
-	par->contrast = 127;
+	par->contrast = contrast;
 	par->vcomh = par->device_info->default_vcomh;
 
 	/* Setup display timing */
-- 
2.3.0


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

* [PATCHv5 10/11] fbdev: ssd1307fb: add backlight controls for setting the contrast
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (8 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-24 21:23   ` [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The backlight class is used to create userspace handles for
setting the OLED contrast.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/Kconfig     |  1 +
 drivers/video/fbdev/ssd1307fb.c | 58 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index b3dd417..da70bae 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2478,6 +2478,7 @@ config FB_SSD1307
 	select FB_SYS_IMAGEBLIT
 	select FB_DEFERRED_IO
 	select PWM
+	select FB_BACKLIGHT
 	help
 	  This driver implements support for the Solomon SSD1307
 	  OLED controller over I2C.
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index d5aec5c..061cc95 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/backlight.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/fb.h>
@@ -38,6 +39,8 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define MAX_CONTRAST 255
+
 #define REFRESHRATE 1
 
 static u_int refreshrate = REFRESHRATE;
@@ -428,6 +431,43 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static int ssd1307fb_update_bl(struct backlight_device *bdev)
+{
+	struct ssd1307fb_par *par = bl_get_data(bdev);
+	int ret;
+	int brightness = bdev->props.brightness;
+
+	par->contrast = brightness;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	if (ret < 0)
+		return ret;
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int ssd1307fb_get_brightness(struct backlight_device *bdev)
+{
+	struct ssd1307fb_par *par = bl_get_data(bdev);
+
+	return par->contrast;
+}
+
+static int ssd1307fb_check_fb(struct backlight_device *bdev,
+				   struct fb_info *info)
+{
+	return (info->bl_dev == bdev);
+}
+
+static const struct backlight_ops ssd1307fb_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= ssd1307fb_update_bl,
+	.get_brightness	= ssd1307fb_get_brightness,
+	.check_fb	= ssd1307fb_check_fb,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
 	.default_vcomh = 0x34,
 	.default_dclk_div = 0,
@@ -472,6 +512,8 @@ MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 static int ssd1307fb_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
+	struct backlight_device *bl;
+	char bl_name[12];
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
 	struct fb_deferred_io *ssd1307fb_defio;
@@ -607,10 +649,24 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto panel_init_error;
 	}
 
+	snprintf(bl_name, sizeof(bl_name), "ssd1307fb%d", info->node);
+	bl = backlight_device_register(bl_name, &client->dev, par,
+				       &ssd1307fb_bl_ops, NULL);
+	bl->props.brightness = contrast;
+	bl->props.max_brightness = MAX_CONTRAST;
+	info->bl_dev = bl;
+
+	if (IS_ERR(bl)) {
+		dev_err(&client->dev, "unable to register backlight device: %ld\n",
+			PTR_ERR(bl));
+		goto bl_init_error;
+	}
 	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
 
 	return 0;
 
+bl_init_error:
+	unregister_framebuffer(info);
 panel_init_error:
 	if (par->device_info->need_pwm) {
 		pwm_disable(par->pwm);
@@ -630,6 +686,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 
 	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
 
+	backlight_device_unregister(info->bl_dev);
+
 	unregister_framebuffer(info);
 	if (par->device_info->need_pwm) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (9 preceding siblings ...)
  2015-03-24 21:23   ` [PATCHv5 10/11] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
@ 2015-03-24 21:23   ` Thomas Niederprüm
  2015-03-25 15:50     ` Olliver Schinagl
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-24 21:23 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds ssd1307fb_blank() to make the framebuffer capable
of blanking.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 061cc95..9101b27 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -238,6 +238,18 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
 	return count;
 }
 
+static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct ssd1307fb_par *par = info->par;
+	int ret;
+
+	if (blank_mode != FB_BLANK_UNBLANK)
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+	else
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	return ret;
+}
+
 static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct ssd1307fb_par *par = info->par;
@@ -263,6 +275,7 @@ static struct fb_ops ssd1307fb_ops = {
 	.owner		= THIS_MODULE,
 	.fb_read	= fb_sys_read,
 	.fb_write	= ssd1307fb_write,
+	.fb_blank	= ssd1307fb_blank,
 	.fb_fillrect	= ssd1307fb_fillrect,
 	.fb_copyarea	= ssd1307fb_copyarea,
 	.fb_imageblit	= ssd1307fb_imageblit,
-- 
2.3.0


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

* Re: [PATCHv5 07/11] fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  2015-03-24 21:23   ` [PATCHv5 07/11] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
@ 2015-03-24 21:54     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-24 21:54 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Tue, Mar 24, 2015 at 10:23:54PM +0100, Thomas Niederprüm wrote:
> This patch adds the module parameter "refreshrate" to set delay for the
> deferred io. The refresh rate is given in units of Hertz. The default
> refresh rate is 1 Hz. The refresh rate set through the newly introduced
> parameter applies to all instances of the driver and for now it is not
> possible to change it individually.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-24 21:23   ` [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-24 22:14     ` Maxime Ripard
  2015-03-25 20:03       ` Thomas Niederprüm
  2015-03-25 15:49     ` Olliver Schinagl
  1 sibling, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-03-24 22:14 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Tue, Mar 24, 2015 at 10:23:51PM +0100, Thomas Niederprüm wrote:
> The 130X controllers are very similar from the configuration point of view.
> The configuration registers for the SSD1305/6/7 are bit identical (except the
> the VHCOM register and the the default values for clock setup register). This
> patch unifies the init code of the controller and adds hardware specific
> properties to DT that are needed to correctly initialize the device.
> 
> The SSD130X can be wired to the OLED panel in various ways. Even for the
> same controller this wiring can differ from one display module to another
> and can not be probed by software. The added DT properties reflect these
> hardware decisions of the display module manufacturer.
> The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
> possibilities for the COM signals pin configuration and readout direction
> of the video memory. The 'segment-no-remap' allows the inversion of the
> memory-to-pin mapping ultimately inverting the order of the controllers
> output pins. The 'prechargepX' values need to be adapted according to the
> capacitance of the OLEDs pixel cells.
> 
> So far these hardware specific bits are hard coded in the init code, making
> the driver usable only for one certain wiring of the controller. This patch
> makes the driver usable with all possible hardware setups, given a valid hw
> description in DT. If these values are not set in DT the default values,
> as they are set in the ssd1307 init code right now, are used. This implies
> that without the corresponding DT property "segment-no-remap" the segment
> remap of the ssd130X controller gets activated. Even though this is not the
> default behaviour according to the datasheet it maintains backward
> compatibility with older DTBs.
> 
> Note that the SSD1306 does not seem to be using the configuration written to
> the registers at all. Therefore this patch does not try to maintain these
> values without changes in DT. For reference an example is added to the DT
> bindings documentation that reproduces the configuration that is set in the
> current init code.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
>  drivers/video/fbdev/ssd1307fb.c                    | 192 ++++++++++++---------
>  2 files changed, 134 insertions(+), 79 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> index 7a12542..637690f 100644
> --- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> @@ -15,6 +15,16 @@ Required properties:
>  
>  Optional properties:
>    - reset-active-low: Is the reset gpio is active on physical low?
> +  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
> +                              to segment mapping
> +  - solomon,com-sequential: Display uses sequential COM pin configuration
> +  - solomon,com-lrremap: Display uses left-right COM pin remap
> +  - solomon,com-invdir: Display uses inverted COM pin scan direction
> +  - solomon,com-offset: Number of the COM pin wired to the first display line
> +  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
> +  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
> +                         This needs to be the higher, the higher the capacitance
> +                         of the OLED's pixels is
>  
>  [0]: Documentation/devicetree/bindings/pwm/pwm.txt
>  
> @@ -26,3 +36,14 @@ ssd1307: oled@3c {
>          reset-gpios = <&gpio2 7>;
>          reset-active-low;
>  };
> +
> +ssd1306: oled@3c {
> +        compatible = "solomon,ssd1306fb-i2c";
> +        reg = <0x3c>;
> +        pwms = <&pwm 4 3000>;
> +        reset-gpios = <&gpio2 7>;
> +        reset-active-low;
> +        solomon,com-lrremap;
> +        solomon,com-invdir;
> +        solomon,com-offset = <32>;
> +};
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 8d34c56..d16aad4 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -40,20 +40,34 @@
>  
>  struct ssd1307fb_par;
>  
> -struct ssd1307fb_ops {
> -	int (*init)(struct ssd1307fb_par *);
> -	int (*remove)(struct ssd1307fb_par *);
> +struct ssd1307fb_deviceinfo {
> +	u32 default_vcomh;
> +	u32 default_dclk_div;
> +	u32 default_dclk_frq;
> +	int need_pwm;
> +	int need_chargepump;
>  };
>  
>  struct ssd1307fb_par {
> +	u32 com_invdir;
> +	u32 com_lrremap;
> +	u32 com_offset;
> +	u32 com_seq;
> +	u32 contrast;
> +	u32 dclk_div;
> +	u32 dclk_frq;
> +	struct ssd1307fb_deviceinfo *device_info;
>  	struct i2c_client *client;
>  	u32 height;
>  	struct fb_info *info;
> -	struct ssd1307fb_ops *ops;
>  	u32 page_offset;
> +	u32 prechargep1;
> +	u32 prechargep2;
>  	struct pwm_device *pwm;
>  	u32 pwm_period;
>  	int reset;
> +	u32 seg_remap;
> +	u32 vcomh;
>  	u32 width;
>  };
>  
> @@ -254,69 +268,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
>  	.deferred_io	= ssd1307fb_deferred_io,
>  };
>  
> -static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
> +static int ssd1307fb_init(struct ssd1307fb_par *par)
>  {
>  	int ret;
> +	u32 precharge, dclk, com_invdir, compins;
>  
> -	par->pwm = pwm_get(&par->client->dev, NULL);
> -	if (IS_ERR(par->pwm)) {
> -		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
> -		return PTR_ERR(par->pwm);
> -	}
> -
> -	par->pwm_period = pwm_get_period(par->pwm);
> -	/* Enable the PWM */
> -	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> -	pwm_enable(par->pwm);
> -
> -	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
> -		par->pwm->pwm, par->pwm_period);
> -
> -	/* Map column 127 of the OLED to segment 0 */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Turn on the display */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
> -	if (ret < 0)
> -		return ret;
> -
> -	return 0;
> -}
> -
> -static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
> -{
> -	pwm_disable(par->pwm);
> -	pwm_put(par->pwm);
> -	return 0;
> -}
> +	if (par->device_info->need_pwm) {
> +		par->pwm = pwm_get(&par->client->dev, NULL);
> +		if (IS_ERR(par->pwm)) {
> +			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
> +			return PTR_ERR(par->pwm);
> +		}
>  
> -static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
> -	.init	= ssd1307fb_ssd1307_init,
> -	.remove	= ssd1307fb_ssd1307_remove,
> -};
> +		par->pwm_period = pwm_get_period(par->pwm);
> +		/* Enable the PWM */
> +		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> +		pwm_enable(par->pwm);
>  
> -static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
> -{
> -	int ret;
> +		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
> +			par->pwm->pwm, par->pwm_period);
> +	};
>  
>  	/* Set initial contrast */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x7f);
> -	if (ret < 0)
> -		return ret;
> -
> -	/* Set COM direction */
> -	ret = ssd1307fb_write_cmd(par->client, 0xc8);
> +	ret = ssd1307fb_write_cmd(par->client, par->contrast);
>  	if (ret < 0)
>  		return ret;
>  
>  	/* Set segment re-map */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> +	if (par->seg_remap) {
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
> +		if (ret < 0)
> +			return ret;
> +	};
> +
> +	/* Set COM direction */
> +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -334,7 +325,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x20);
> +	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -343,7 +334,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0xf0);
> +	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
> +	ret = ssd1307fb_write_cmd(par->client, dclk);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -352,7 +344,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> +	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
> +	ret = ssd1307fb_write_cmd(par->client, precharge);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -361,7 +354,9 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> +	compins = 0x02 | (!par->com_seq & 0x1) << 4
> +				   | (par->com_lrremap & 0x1) << 5;
> +	ret = ssd1307fb_write_cmd(par->client, compins);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -370,18 +365,20 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x49);
> +	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Turn on the DC-DC Charge Pump */
> -	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
> -	if (ret < 0)
> -		return ret;
> +	if (par->device_info->need_chargepump) {
> +		/* Turn on the DC-DC Charge Pump */
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
> +		if (ret < 0)
> +			return ret;
>  
> -	ret = ssd1307fb_write_cmd(par->client, 0x14);
> -	if (ret < 0)
> -		return ret;
> +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> +		if (ret < 0)
> +			return ret;
> +	};
>  
>  	/* Switch to horizontal addressing mode */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
> @@ -393,6 +390,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> +	/* Set column range */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
>  	if (ret < 0)
>  		return ret;
> @@ -405,6 +403,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	if (ret < 0)
>  		return ret;
>  
> +	/* Set page range */
>  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
>  	if (ret < 0)
>  		return ret;
> @@ -426,18 +425,30 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>  	return 0;
>  }
>  
> -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> -	.init	= ssd1307fb_ssd1306_init,
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 0,

A division by 0 ?

> +	.default_dclk_frq = 8,
> +	.need_pwm = 0,

You don't need to declare this field, its value will already be
initialized to 0.

> +	.need_chargepump = 1,
> +};
> +
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 1,
> +	.default_dclk_frq = 12,
> +	.need_pwm = 1,
> +	.need_chargepump = 0,
>  };

Same thing here.

>  
>  static const struct of_device_id ssd1307fb_of_match[] = {
>  	{
>  		.compatible = "solomon,ssd1306fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1306_ops,
> +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
>  	},
>  	{
>  		.compatible = "solomon,ssd1307fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1307_ops,
> +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
>  	},
>  	{},
>  };
> @@ -468,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	par->info = info;
>  	par->client = client;
>  
> -	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
> -							   &client->dev)->data;
> +	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
> +			ssd1307fb_of_match, &client->dev)->data;
>  
>  	par->reset = of_get_named_gpio(client->dev.of_node,
>  					 "reset-gpios", 0);
> @@ -487,6 +498,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
>  		par->page_offset = 1;
>  
> +	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
> +		par->com_offset = 0;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
> +		par->prechargep1 = 2;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
> +		par->prechargep2 = 0;
> +
> +	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
> +	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
> +	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
> +	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
> +
> +	par->contrast = 127;
> +	par->vcomh = par->device_info->default_vcomh;
> +
> +	/* Setup display timing */
> +	par->dclk_div = par->device_info->default_dclk_div;
> +	par->dclk_frq = par->device_info->default_dclk_frq;
> +
>  	vmem_size = par->width * par->height / 8;
>  
>  	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
> @@ -539,11 +571,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	gpio_set_value(par->reset, 1);
>  	udelay(4);
>  
> -	if (par->ops->init) {
> -		ret = par->ops->init(par);
> -		if (ret)
> -			goto reset_oled_error;
> -	}
> +	ret = ssd1307fb_init(par);
> +	if (ret)
> +		goto reset_oled_error;
>  
>  	ret = register_framebuffer(info);
>  	if (ret) {
> @@ -556,8 +586,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
>  	return 0;
>  
>  panel_init_error:
> -	if (par->ops->remove)
> -		par->ops->remove(par);
> +	if (par->device_info->need_pwm) {
> +		pwm_disable(par->pwm);
> +		pwm_put(par->pwm);
> +	};
>  reset_oled_error:
>  	fb_deferred_io_cleanup(info);
>  fb_alloc_error:
> @@ -571,8 +603,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
>  	struct ssd1307fb_par *par = info->par;
>  
>  	unregister_framebuffer(info);
> -	if (par->ops->remove)
> -		par->ops->remove(par);
> +	if (par->device_info->need_pwm) {
> +		pwm_disable(par->pwm);
> +		pwm_put(par->pwm);
> +	};
>  	fb_deferred_io_cleanup(info);
>  	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
>  	framebuffer_release(info);
> -- 
> 2.3.0
> 

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast
  2015-03-24 21:23   ` [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast Thomas Niederprüm
@ 2015-03-24 22:16     ` Maxime Ripard
  2015-03-25 20:10       ` Thomas Niederprüm
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-03-24 22:16 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Tue, Mar 24, 2015 at 10:23:56PM +0100, Thomas Niederprüm wrote:
> This patch adds the module parameter "contrast" to determine the
> contrast value that is used to initialize the display. This
> setting applies to all instances of the driver.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Do we still need this patch given that the next one is doing the exact
same thing?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-03-10 10:45         ` Tomi Valkeinen
  2015-03-13 19:25           ` Thomas Niederprüm
@ 2015-03-25 10:56           ` Olliver Schinagl
  2015-03-25 16:02             ` Maxime Ripard
  1 sibling, 1 reply; 138+ messages in thread
From: Olliver Schinagl @ 2015-03-25 10:56 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-fbdev, plagnioj, linux-kernel

Hey all,

On 10-03-15 11:45, Tomi Valkeinen wrote:
> On 14/02/15 17:54, Maxime Ripard wrote:
>> On Sat, Feb 07, 2015 at 05:05:03PM +0100, Thomas Niederprüm wrote:
>>> Am Sat, 7 Feb 2015 12:20:43 +0100
>>> schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
>>>
>>>> On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de
>>>> wrote:
>>>>> From: Thomas Niederprüm <niederp@physik.uni-kl.de>
>>>>>
>>>>> This patch adds a module parameter 'bitsperpixel' to adjust the
>>>>> colordepth of the framebuffer. All values >1 will result in memory
>>>>> map of the requested color depth. However only the MSB of each
>>>>> pixel will be sent to the device. The framebuffer identifies itself
>>>>> as a grayscale display with the specified depth.
>>>>
>>>> I'm not sure this is the right thing to do.
>>>>
>>>> The bits per pixel for this display is rightfully defined, used and
>>>> reported to the userspace, why would you want to change that?
>>>
>>> You are right of course. The display is 1bpp and it reports to be 1
>>> bpp. The problem is that there is almost no userspace library that can
>>> handle 1 bit framebuffers correctly. So it is nice if the framebuffer
>>> (optionally) can expose itself as 8 bits per pixel grayscale to the
>>> userspace program. As an example this allows to run DirectFB on the
>>> framebuffer, which is not possible out of the box for 1bpp.
>>>
>>> Also note that if do not set the module parameter at load time
>>> the framebuffer will be 1bpp. So you have to actively set that module
>>> parameter to make the framebuffer pretend to be more than 1bpp.
>>>
>>> In any case I don't cling to that patch, I just thought it was a nice
>>> feature.
>>
>> I'd say that the right fix would be to patch DirectFB, instead of
>> faking that in the kernel.
>>
>> But again, that's probably Tomi's call, not mine.
>
> Right, I'm not thrilled =). I don't think it's a good idea to lie to the
> userspace (except when fixing regressions).

I've done the same thing actually in a local patchset and while you are 
right, we shouldn't lie to userspace, my choice was a performance one.

Right now, in the driver we already have to convert from a regular 
packed pixel framebuffer, to the format that supports the page layout of 
the actual chip. Especially on slow hardware, doing the math within this 
conversion just adds a few multiplications.

Also, there is indeed a lot of userspace out there which doesn't expect 
single bit displays.

Having said that, what about actually faking grayscale? If we toggle a 
pixel fast enough (we can achieve 40ish fps right now with a 400 kHz I2C 
bus) it appears to a user as gray. This can't easily be done in user 
space, would that be acceptable?

Olliver

>
>   Tomi
>
>



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

* Re: [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-24 21:23   ` [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
  2015-03-24 22:14     ` Maxime Ripard
@ 2015-03-25 15:49     ` Olliver Schinagl
  2015-03-25 22:14       ` Thomas Niederprüm
  1 sibling, 1 reply; 138+ messages in thread
From: Olliver Schinagl @ 2015-03-25 15:49 UTC (permalink / raw)
  To: Thomas Niederprüm, plagnioj, tomi.valkeinen, maxime.ripard,
	kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel

Hey Thomas,

awesome the time you put into this driver. It does what I was working on 
the last few weeks, but with a much bigger bang ;)

I personally have a ssd1309 and will be submitting the patches for that 
after testing your patch-set.

On 24-03-15 22:23, Thomas Niederprüm wrote:
> The 130X controllers are very similar from the configuration point of view.
> The configuration registers for the SSD1305/6/7 are bit identical (except the
> the VHCOM register and the the default values for clock setup register). This
> patch unifies the init code of the controller and adds hardware specific
> properties to DT that are needed to correctly initialize the device.
>
> The SSD130X can be wired to the OLED panel in various ways. Even for the
> same controller this wiring can differ from one display module to another
> and can not be probed by software. The added DT properties reflect these
> hardware decisions of the display module manufacturer.
> The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
> possibilities for the COM signals pin configuration and readout direction
> of the video memory. The 'segment-no-remap' allows the inversion of the
> memory-to-pin mapping ultimately inverting the order of the controllers
> output pins. The 'prechargepX' values need to be adapted according to the
> capacitance of the OLEDs pixel cells.
>
> So far these hardware specific bits are hard coded in the init code, making
> the driver usable only for one certain wiring of the controller. This patch
> makes the driver usable with all possible hardware setups, given a valid hw
> description in DT. If these values are not set in DT the default values,
> as they are set in the ssd1307 init code right now, are used. This implies
> that without the corresponding DT property "segment-no-remap" the segment
> remap of the ssd130X controller gets activated. Even though this is not the
> default behaviour according to the datasheet it maintains backward
> compatibility with older DTBs.
>
> Note that the SSD1306 does not seem to be using the configuration written to
> the registers at all. Therefore this patch does not try to maintain these
> values without changes in DT. For reference an example is added to the DT
> bindings documentation that reproduces the configuration that is set in the
> current init code.
>
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>   .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
>   drivers/video/fbdev/ssd1307fb.c                    | 192 ++++++++++++---------
>   2 files changed, 134 insertions(+), 79 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> index 7a12542..637690f 100644
> --- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> @@ -15,6 +15,16 @@ Required properties:
>
>   Optional properties:
>     - reset-active-low: Is the reset gpio is active on physical low?
> +  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
> +                              to segment mapping
> +  - solomon,com-sequential: Display uses sequential COM pin configuration
> +  - solomon,com-lrremap: Display uses left-right COM pin remap
> +  - solomon,com-invdir: Display uses inverted COM pin scan direction
> +  - solomon,com-offset: Number of the COM pin wired to the first display line
> +  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
> +  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
> +                         This needs to be the higher, the higher the capacitance
> +                         of the OLED's pixels is
Aren't the height, width and page-offset also optional? They should be 
set to sane defaults when not supplied. Though the default (which is the 
max really) width/height depends on the actual attached display to the 
chip (I mention this in the vcomh section too below, the controller's 
width/height would be the absolute maximum values, the display can 
always be smaller).

Same goes to say for the precharge, and probably other parameters. I 
don't think we have a proper framework to handle the attached displays 
to a controller chip at the moment anyhow?

>
>   [0]: Documentation/devicetree/bindings/pwm/pwm.txt
>
<snip>
> +
> +	/* Set COM direction */
> +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
Shouldn't this be par->com_invdir & 0x1 ?
The datasheet only mentions 1 bit change for the ssd1306, ssd1307 and 
ssd1309. I dont' know what the ssd1305 does here though.

> +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
>   	if (ret < 0)
>   		return ret;
<snip>
>
> -	ret = ssd1307fb_write_cmd(par->client, 0x14);
> -	if (ret < 0)
> -		return ret;
> +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> +		if (ret < 0)
> +			return ret;
> +	};
I had to look hard for this setting, as my old datasheet had omitted the 
charge pump def.

but wouldn't you want something like (0x10 | 
par->device_info->need_chargepump & 0x1 << 2) & 0x14 to follow your 
previous styles?

Only bit 2 determines the state of the charge-pump. And I guess it 
should be safe to use on the other chips as well. My 1309 doesn't seem 
to have a problem with it, I'm working a lot on this display so it will 
be tested thoroughly in the next few weeks.

>
>   	/* Switch to horizontal addressing mode */
>   	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
> @@ -393,6 +390,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
>   	if (ret < 0)
>   		return ret;
>
<snip>
>
> -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> -	.init	= ssd1307fb_ssd1306_init,
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 0,
> +	.default_dclk_frq = 8,
> +	.need_pwm = 0,
> +	.need_chargepump = 1,
> +};
This device info struct, is this really always fixed data? We use a 
ssd1309 with a MI12864MO i think and the combination of these two parts 
defines atleast the vcomh I would imagine? There are only a very limited 
number of consumers of this driver so for now it won't make much of a 
difference, just mentioning it as it is a configurable so it may matter 
depending on the physical display.
> +
> +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> +	.default_vcomh = 0x20,
> +	.default_dclk_div = 1,
> +	.default_dclk_frq = 12,
> +	.need_pwm = 1,
> +	.need_chargepump = 0,
>   };
>
>   static const struct of_device_id ssd1307fb_of_match[] = {
>   	{
>   		.compatible = "solomon,ssd1306fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1306_ops,
> +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
>   	},
>   	{
>   		.compatible = "solomon,ssd1307fb-i2c",
> -		.data = (void *)&ssd1307fb_ssd1307_ops,
> +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
>   	},
>   	{},
>   };
> @@ -468,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
>   	par->info = info;
>   	par->client = client;
>
> -	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
> -							   &client->dev)->data;
> +	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
> +			ssd1307fb_of_match, &client->dev)->data;
>
>   	par->reset = of_get_named_gpio(client->dev.of_node,
>   					 "reset-gpios", 0);
> @@ -487,6 +498,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
>   	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
>   		par->page_offset = 1;
While your re-doing the whole driver, why use a default page_offset of 
1? 0 makes far more sense (its the default on my board also) and 
logically, we'd start counting at 0 as programmers ;) Also, the 
datasheet uses 0 as a default preset.

>
> +	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
> +		par->com_offset = 0;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
> +		par->prechargep1 = 2;
> +
> +	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
> +		par->prechargep2 = 0;
Why set the default to 0 here? The datasheet sets it to 0x2 by default 
for example.
> +
> +	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
> +	par->com_seq = of_property_read_bool(node, "solomon,com-sequential");
all the other parameters are somewhat abbreviated, or the property name 
matches the variable name. I'd just abbreviate it to com-seq clear and 
short.


Overal, the driver works and can have a Tested-by: Olliver Schinagl 
<o.schinagl@ultimaker.com> from me (for the 1309 which I'll submit very 
soon.

Olliver

P.S. Do you have a link for your display? I'm curious as to how it looks.

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

* Re: [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode
  2015-03-24 21:23   ` [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
@ 2015-03-25 15:50     ` Olliver Schinagl
  2015-03-25 20:33       ` Thomas Niederprüm
  2015-03-25 22:00       ` Maxime Ripard
  0 siblings, 2 replies; 138+ messages in thread
From: Olliver Schinagl @ 2015-03-25 15:50 UTC (permalink / raw)
  To: Thomas Niederprüm, plagnioj, tomi.valkeinen, maxime.ripard,
	kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel

Hey Thomas,

On 24-03-15 22:23, Thomas Niederprüm wrote:
> This patch adds ssd1307fb_blank() to make the framebuffer capable
> of blanking.
>
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>   drivers/video/fbdev/ssd1307fb.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
>
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 061cc95..9101b27 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -238,6 +238,18 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
>   	return count;
>   }
>
> +static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
> +{
> +	struct ssd1307fb_par *par = info->par;
> +	int ret;
> +
> +	if (blank_mode != FB_BLANK_UNBLANK)
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
> +	else
> +		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
I'd probably add an extra return, or drop the ret var at all and just 
return the function.

or even shorter :)
return sd1307fb_write_cmd(par->client, (blank_mode != FB_BLANK_UNBLANK) 
? SSD1307FB_DISPLAY_OFF : SSD1307FB_DISPLAY_ON;

Olliver
> +	return ret;
> +}
> +
>   static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
>   {
>   	struct ssd1307fb_par *par = info->par;
> @@ -263,6 +275,7 @@ static struct fb_ops ssd1307fb_ops = {
>   	.owner		= THIS_MODULE,
>   	.fb_read	= fb_sys_read,
>   	.fb_write	= ssd1307fb_write,
> +	.fb_blank	= ssd1307fb_blank,
>   	.fb_fillrect	= ssd1307fb_fillrect,
>   	.fb_copyarea	= ssd1307fb_copyarea,
>   	.fb_imageblit	= ssd1307fb_imageblit,
>


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

* Re: [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel.
  2015-03-25 10:56           ` Olliver Schinagl
@ 2015-03-25 16:02             ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-25 16:02 UTC (permalink / raw)
  To: Olliver Schinagl
  Cc: Tomi Valkeinen, Thomas Niederprüm, linux-fbdev, plagnioj,
	linux-kernel

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

On Wed, Mar 25, 2015 at 11:56:38AM +0100, Olliver Schinagl wrote:
> Hey all,
> 
> On 10-03-15 11:45, Tomi Valkeinen wrote:
> >On 14/02/15 17:54, Maxime Ripard wrote:
> >>On Sat, Feb 07, 2015 at 05:05:03PM +0100, Thomas Niederprüm wrote:
> >>>Am Sat, 7 Feb 2015 12:20:43 +0100
> >>>schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:
> >>>
> >>>>On Fri, Feb 06, 2015 at 11:28:11PM +0100, niederp@physik.uni-kl.de
> >>>>wrote:
> >>>>>From: Thomas Niederprüm <niederp@physik.uni-kl.de>
> >>>>>
> >>>>>This patch adds a module parameter 'bitsperpixel' to adjust the
> >>>>>colordepth of the framebuffer. All values >1 will result in memory
> >>>>>map of the requested color depth. However only the MSB of each
> >>>>>pixel will be sent to the device. The framebuffer identifies itself
> >>>>>as a grayscale display with the specified depth.
> >>>>
> >>>>I'm not sure this is the right thing to do.
> >>>>
> >>>>The bits per pixel for this display is rightfully defined, used and
> >>>>reported to the userspace, why would you want to change that?
> >>>
> >>>You are right of course. The display is 1bpp and it reports to be 1
> >>>bpp. The problem is that there is almost no userspace library that can
> >>>handle 1 bit framebuffers correctly. So it is nice if the framebuffer
> >>>(optionally) can expose itself as 8 bits per pixel grayscale to the
> >>>userspace program. As an example this allows to run DirectFB on the
> >>>framebuffer, which is not possible out of the box for 1bpp.
> >>>
> >>>Also note that if do not set the module parameter at load time
> >>>the framebuffer will be 1bpp. So you have to actively set that module
> >>>parameter to make the framebuffer pretend to be more than 1bpp.
> >>>
> >>>In any case I don't cling to that patch, I just thought it was a nice
> >>>feature.
> >>
> >>I'd say that the right fix would be to patch DirectFB, instead of
> >>faking that in the kernel.
> >>
> >>But again, that's probably Tomi's call, not mine.
> >
> >Right, I'm not thrilled =). I don't think it's a good idea to lie to the
> >userspace (except when fixing regressions).
> 
> I've done the same thing actually in a local patchset and while you are
> right, we shouldn't lie to userspace, my choice was a performance one.

Userspace drivers can be more performant than the kernel ones. That
doesn't mean that it's a good choice, let alone the right choice.

> Right now, in the driver we already have to convert from a regular packed
> pixel framebuffer, to the format that supports the page layout of the actual
> chip. Especially on slow hardware, doing the math within this conversion
> just adds a few multiplications.

And how does implementing monochrome operations in directfb would make
things worse from a performance point of view?

Are you really using performance as an argument for a device that is
driven through i2c?

> Also, there is indeed a lot of userspace out there which doesn't expect
> single bit displays.

And so just because *they* don't expect it and are not supporting
every case they should, *we* should do something about it?

A lot of userspace applications don't check syscall errors. Does that
mean that we should never return an error?

> Having said that, what about actually faking grayscale? If we toggle a pixel
> fast enough (we can achieve 40ish fps right now with a 400 kHz I2C bus) it
> appears to a user as gray. This can't easily be done in user space, would
> that be acceptable?

You can't make the assumption that the bus is fast enough. It's your
case, it might not be the case for everyone.

Seriously, the device is monochrome, deal with it. If you wanted a
grayscale screen, you should have chosen better.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-24 22:14     ` Maxime Ripard
@ 2015-03-25 20:03       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-25 20:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

Am Tue, 24 Mar 2015 15:14:28 -0700
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Tue, Mar 24, 2015 at 10:23:51PM +0100, Thomas Niederprüm wrote:
> > The 130X controllers are very similar from the configuration point
> > of view. The configuration registers for the SSD1305/6/7 are bit
> > identical (except the the VHCOM register and the the default values
> > for clock setup register). This patch unifies the init code of the
> > controller and adds hardware specific properties to DT that are
> > needed to correctly initialize the device.
> > 
> > The SSD130X can be wired to the OLED panel in various ways. Even
> > for the same controller this wiring can differ from one display
> > module to another and can not be probed by software. The added DT
> > properties reflect these hardware decisions of the display module
> > manufacturer. The 'com-sequential', 'com-lrremap' and 'com-invdir'
> > values define different possibilities for the COM signals pin
> > configuration and readout direction of the video memory. The
> > 'segment-no-remap' allows the inversion of the memory-to-pin
> > mapping ultimately inverting the order of the controllers output
> > pins. The 'prechargepX' values need to be adapted according to the
> > capacitance of the OLEDs pixel cells.
> > 
> > So far these hardware specific bits are hard coded in the init
> > code, making the driver usable only for one certain wiring of the
> > controller. This patch makes the driver usable with all possible
> > hardware setups, given a valid hw description in DT. If these
> > values are not set in DT the default values, as they are set in the
> > ssd1307 init code right now, are used. This implies that without
> > the corresponding DT property "segment-no-remap" the segment remap
> > of the ssd130X controller gets activated. Even though this is not
> > the default behaviour according to the datasheet it maintains
> > backward compatibility with older DTBs.
> > 
> > Note that the SSD1306 does not seem to be using the configuration
> > written to the registers at all. Therefore this patch does not try
> > to maintain these values without changes in DT. For reference an
> > example is added to the DT bindings documentation that reproduces
> > the configuration that is set in the current init code.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
> >  drivers/video/fbdev/ssd1307fb.c                    | 192
> > ++++++++++++--------- 2 files changed, 134 insertions(+), 79
> > deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > 7a12542..637690f 100644 ---
> > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
> > +15,16 @@ Required properties: 
> >  Optional properties:
> >    - reset-active-low: Is the reset gpio is active on physical low?
> > +  - solomon,segment-no-remap: Display needs normal (non-inverted)
> > data column
> > +                              to segment mapping
> > +  - solomon,com-sequential: Display uses sequential COM pin
> > configuration
> > +  - solomon,com-lrremap: Display uses left-right COM pin remap
> > +  - solomon,com-invdir: Display uses inverted COM pin scan
> > direction
> > +  - solomon,com-offset: Number of the COM pin wired to the first
> > display line
> > +  - solomon,prechargep1: Length of deselect period (phase 1) in
> > clock cycles.
> > +  - solomon,prechargep2: Length of precharge period (phase 2) in
> > clock cycles.
> > +                         This needs to be the higher, the higher
> > the capacitance
> > +                         of the OLED's pixels is
> >  
> >  [0]: Documentation/devicetree/bindings/pwm/pwm.txt
> >  
> > @@ -26,3 +36,14 @@ ssd1307: oled@3c {
> >          reset-gpios = <&gpio2 7>;
> >          reset-active-low;
> >  };
> > +
> > +ssd1306: oled@3c {
> > +        compatible = "solomon,ssd1306fb-i2c";
> > +        reg = <0x3c>;
> > +        pwms = <&pwm 4 3000>;
> > +        reset-gpios = <&gpio2 7>;
> > +        reset-active-low;
> > +        solomon,com-lrremap;
> > +        solomon,com-invdir;
> > +        solomon,com-offset = <32>;
> > +};
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 8d34c56..d16aad4 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -40,20 +40,34 @@
> >  
> >  struct ssd1307fb_par;
> >  
> > -struct ssd1307fb_ops {
> > -	int (*init)(struct ssd1307fb_par *);
> > -	int (*remove)(struct ssd1307fb_par *);
> > +struct ssd1307fb_deviceinfo {
> > +	u32 default_vcomh;
> > +	u32 default_dclk_div;
> > +	u32 default_dclk_frq;
> > +	int need_pwm;
> > +	int need_chargepump;
> >  };
> >  
> >  struct ssd1307fb_par {
> > +	u32 com_invdir;
> > +	u32 com_lrremap;
> > +	u32 com_offset;
> > +	u32 com_seq;
> > +	u32 contrast;
> > +	u32 dclk_div;
> > +	u32 dclk_frq;
> > +	struct ssd1307fb_deviceinfo *device_info;
> >  	struct i2c_client *client;
> >  	u32 height;
> >  	struct fb_info *info;
> > -	struct ssd1307fb_ops *ops;
> >  	u32 page_offset;
> > +	u32 prechargep1;
> > +	u32 prechargep2;
> >  	struct pwm_device *pwm;
> >  	u32 pwm_period;
> >  	int reset;
> > +	u32 seg_remap;
> > +	u32 vcomh;
> >  	u32 width;
> >  };
> >  
> > @@ -254,69 +268,46 @@ static struct fb_deferred_io ssd1307fb_defio
> > = { .deferred_io	= ssd1307fb_deferred_io,
> >  };
> >  
> > -static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
> > +static int ssd1307fb_init(struct ssd1307fb_par *par)
> >  {
> >  	int ret;
> > +	u32 precharge, dclk, com_invdir, compins;
> >  
> > -	par->pwm = pwm_get(&par->client->dev, NULL);
> > -	if (IS_ERR(par->pwm)) {
> > -		dev_err(&par->client->dev, "Could not get PWM from
> > device tree!\n");
> > -		return PTR_ERR(par->pwm);
> > -	}
> > -
> > -	par->pwm_period = pwm_get_period(par->pwm);
> > -	/* Enable the PWM */
> > -	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> > -	pwm_enable(par->pwm);
> > -
> > -	dev_dbg(&par->client->dev, "Using PWM%d with a %dns
> > period.\n",
> > -		par->pwm->pwm, par->pwm_period);
> > -
> > -	/* Map column 127 of the OLED to segment 0 */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	/* Turn on the display */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_ON);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	return 0;
> > -}
> > -
> > -static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
> > -{
> > -	pwm_disable(par->pwm);
> > -	pwm_put(par->pwm);
> > -	return 0;
> > -}
> > +	if (par->device_info->need_pwm) {
> > +		par->pwm = pwm_get(&par->client->dev, NULL);
> > +		if (IS_ERR(par->pwm)) {
> > +			dev_err(&par->client->dev, "Could not get
> > PWM from device tree!\n");
> > +			return PTR_ERR(par->pwm);
> > +		}
> >  
> > -static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
> > -	.init	= ssd1307fb_ssd1307_init,
> > -	.remove	= ssd1307fb_ssd1307_remove,
> > -};
> > +		par->pwm_period = pwm_get_period(par->pwm);
> > +		/* Enable the PWM */
> > +		pwm_config(par->pwm, par->pwm_period / 2,
> > par->pwm_period);
> > +		pwm_enable(par->pwm);
> >  
> > -static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
> > -{
> > -	int ret;
> > +		dev_dbg(&par->client->dev, "Using PWM%d with a
> > %dns period.\n",
> > +			par->pwm->pwm, par->pwm_period);
> > +	};
> >  
> >  	/* Set initial contrast */
> >  	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x7f);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	/* Set COM direction */
> > -	ret = ssd1307fb_write_cmd(par->client, 0xc8);
> > +	ret = ssd1307fb_write_cmd(par->client, par->contrast);
> >  	if (ret < 0)
> >  		return ret;
> >  
> >  	/* Set segment re-map */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > +	if (par->seg_remap) {
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SEG_REMAP_ON);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> > +
> > +	/* Set COM direction */
> > +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> > +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -334,7 +325,7 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x20);
> > +	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -343,7 +334,8 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0xf0);
> > +	dclk = (par->dclk_div & 0xf) | (par->dclk_frq & 0xf) << 4;
> > +	ret = ssd1307fb_write_cmd(par->client, dclk);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -352,7 +344,8 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> > +	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 &
> > 0xf) << 4;
> > +	ret = ssd1307fb_write_cmd(par->client, precharge);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -361,7 +354,9 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x22);
> > +	compins = 0x02 | (!par->com_seq & 0x1) << 4
> > +				   | (par->com_lrremap & 0x1) << 5;
> > +	ret = ssd1307fb_write_cmd(par->client, compins);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > @@ -370,18 +365,20 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x49);
> > +	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
> >  	if (ret < 0)
> >  		return ret;
> >  
> > -	/* Turn on the DC-DC Charge Pump */
> > -	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_CHARGE_PUMP);
> > -	if (ret < 0)
> > -		return ret;
> > +	if (par->device_info->need_chargepump) {
> > +		/* Turn on the DC-DC Charge Pump */
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_CHARGE_PUMP);
> > +		if (ret < 0)
> > +			return ret;
> >  
> > -	ret = ssd1307fb_write_cmd(par->client, 0x14);
> > -	if (ret < 0)
> > -		return ret;
> > +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> >  
> >  	/* Switch to horizontal addressing mode */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_ADDRESS_MODE); @@ -393,6 +390,7 @@ static int
> > ssd1307fb_ssd1306_init(struct ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > +	/* Set column range */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_COL_RANGE); if (ret < 0)
> >  		return ret;
> > @@ -405,6 +403,7 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) if (ret < 0)
> >  		return ret;
> >  
> > +	/* Set page range */
> >  	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_PAGE_RANGE); if (ret < 0)
> >  		return ret;
> > @@ -426,18 +425,30 @@ static int ssd1307fb_ssd1306_init(struct
> > ssd1307fb_par *par) return 0;
> >  }
> >  
> > -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> > -	.init	= ssd1307fb_ssd1306_init,
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 0,
> 
> A division by 0 ?

default_dclk_div stores the bit value for the divider register. The
bit encodes the divider as follows: bit = (divider - 1). But I guess
your are right that it makes more sense to store the actual divider
here and just calculate the bit value when writing to the device.

> 
> > +	.default_dclk_frq = 8,
> > +	.need_pwm = 0,
> 
> You don't need to declare this field, its value will already be
> initialized to 0.
I wasn't sure whether this is necessarily the case. But your hint and
a bit more reading on initialization of static structs convinced me. I
will remove the unnecessary fields.

Thomas

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

* Re: [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast
  2015-03-24 22:16     ` Maxime Ripard
@ 2015-03-25 20:10       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-25 20:10 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

Am Tue, 24 Mar 2015 15:16:36 -0700
schrieb Maxime Ripard <maxime.ripard@free-electrons.com>:

> On Tue, Mar 24, 2015 at 10:23:56PM +0100, Thomas Niederprüm wrote:
> > This patch adds the module parameter "contrast" to determine the
> > contrast value that is used to initialize the display. This
> > setting applies to all instances of the driver.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> 
> Do we still need this patch given that the next one is doing the exact
> same thing?
I was kind of expecting this objection. I added this module parameter
since it suits my use case where I always run the display at the lowest
possible contrast. With this module parameter I can specify this need
at module load time and I do not need udev or to touch the backlight
controls manually every time the driver is loaded. I see that this is
probably a (too) weak argument, so if nobody complains I will remove
this patch for the next round.

Thomas

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

* Re: [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode
  2015-03-25 15:50     ` Olliver Schinagl
@ 2015-03-25 20:33       ` Thomas Niederprüm
  2015-03-25 22:00       ` Maxime Ripard
  1 sibling, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-25 20:33 UTC (permalink / raw)
  To: Olliver Schinagl
  Cc: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo,
	robh+dt, linux-fbdev, linux-kernel

Am Wed, 25 Mar 2015 16:50:05 +0100
schrieb Olliver Schinagl <oliver@schinagl.nl>:

> Hey Thomas,
> 
> On 24-03-15 22:23, Thomas Niederprüm wrote:
> > This patch adds ssd1307fb_blank() to make the framebuffer capable
> > of blanking.
> >
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >   drivers/video/fbdev/ssd1307fb.c | 13 +++++++++++++
> >   1 file changed, 13 insertions(+)
> >
> > diff --git a/drivers/video/fbdev/ssd1307fb.c
> > b/drivers/video/fbdev/ssd1307fb.c index 061cc95..9101b27 100644
> > --- a/drivers/video/fbdev/ssd1307fb.c
> > +++ b/drivers/video/fbdev/ssd1307fb.c
> > @@ -238,6 +238,18 @@ static ssize_t ssd1307fb_write(struct fb_info
> > *info, const char __user *buf, return count;
> >   }
> >
> > +static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
> > +{
> > +	struct ssd1307fb_par *par = info->par;
> > +	int ret;
> > +
> > +	if (blank_mode != FB_BLANK_UNBLANK)
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_OFF);
> > +	else
> > +		ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_DISPLAY_ON);
> I'd probably add an extra return, or drop the ret var at all and just 
> return the function.
> 
> or even shorter :)
> return sd1307fb_write_cmd(par->client, (blank_mode !=
> FB_BLANK_UNBLANK) ? SSD1307FB_DISPLAY_OFF : SSD1307FB_DISPLAY_ON;

Wow, short and elegant. Thanks for the hint, I will include it in v6.

Thomas



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

* Re: [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode
  2015-03-25 15:50     ` Olliver Schinagl
  2015-03-25 20:33       ` Thomas Niederprüm
@ 2015-03-25 22:00       ` Maxime Ripard
  1 sibling, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-03-25 22:00 UTC (permalink / raw)
  To: Olliver Schinagl
  Cc: Thomas Niederprüm, plagnioj, tomi.valkeinen, kernel,
	shawn.guo, robh+dt, linux-fbdev, linux-kernel

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

On Wed, Mar 25, 2015 at 04:50:05PM +0100, Olliver Schinagl wrote:
> Hey Thomas,
> 
> On 24-03-15 22:23, Thomas Niederprüm wrote:
> >This patch adds ssd1307fb_blank() to make the framebuffer capable
> >of blanking.
> >
> >Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> >---
> >  drivers/video/fbdev/ssd1307fb.c | 13 +++++++++++++
> >  1 file changed, 13 insertions(+)
> >
> >diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> >index 061cc95..9101b27 100644
> >--- a/drivers/video/fbdev/ssd1307fb.c
> >+++ b/drivers/video/fbdev/ssd1307fb.c
> >@@ -238,6 +238,18 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
> >  	return count;
> >  }
> >
> >+static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
> >+{
> >+	struct ssd1307fb_par *par = info->par;
> >+	int ret;
> >+
> >+	if (blank_mode != FB_BLANK_UNBLANK)
> >+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
> >+	else
> >+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
> I'd probably add an extra return, or drop the ret var at all and just return
> the function.
> 
> or even shorter :)
> return sd1307fb_write_cmd(par->client, (blank_mode != FB_BLANK_UNBLANK) ?
> SSD1307FB_DISPLAY_OFF : SSD1307FB_DISPLAY_ON;

In some domains, shorter is not better ;)

This is one of these cases. It's much clearer as it is.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-25 15:49     ` Olliver Schinagl
@ 2015-03-25 22:14       ` Thomas Niederprüm
  0 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-25 22:14 UTC (permalink / raw)
  To: Olliver Schinagl
  Cc: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo,
	robh+dt, linux-fbdev, linux-kernel

Am Wed, 25 Mar 2015 16:49:47 +0100
schrieb Olliver Schinagl <oliver@schinagl.nl>:

> Hey Thomas,
> 
> awesome the time you put into this driver. It does what I was working
> on the last few weeks, but with a much bigger bang ;)
> 
> I personally have a ssd1309 and will be submitting the patches for
> that after testing your patch-set.

Yeah, it turned out to be quite some work. But I'm glad to see that it
might turn out useful for you and I'm looking forward to see support
added for even more controllers.

> On 24-03-15 22:23, Thomas Niederprüm wrote:
> > The 130X controllers are very similar from the configuration point
> > of view. The configuration registers for the SSD1305/6/7 are bit
> > identical (except the the VHCOM register and the the default values
> > for clock setup register). This patch unifies the init code of the
> > controller and adds hardware specific properties to DT that are
> > needed to correctly initialize the device.
> >
> > The SSD130X can be wired to the OLED panel in various ways. Even
> > for the same controller this wiring can differ from one display
> > module to another and can not be probed by software. The added DT
> > properties reflect these hardware decisions of the display module
> > manufacturer. The 'com-sequential', 'com-lrremap' and 'com-invdir'
> > values define different possibilities for the COM signals pin
> > configuration and readout direction of the video memory. The
> > 'segment-no-remap' allows the inversion of the memory-to-pin
> > mapping ultimately inverting the order of the controllers output
> > pins. The 'prechargepX' values need to be adapted according to the
> > capacitance of the OLEDs pixel cells.
> >
> > So far these hardware specific bits are hard coded in the init
> > code, making the driver usable only for one certain wiring of the
> > controller. This patch makes the driver usable with all possible
> > hardware setups, given a valid hw description in DT. If these
> > values are not set in DT the default values, as they are set in the
> > ssd1307 init code right now, are used. This implies that without
> > the corresponding DT property "segment-no-remap" the segment remap
> > of the ssd130X controller gets activated. Even though this is not
> > the default behaviour according to the datasheet it maintains
> > backward compatibility with older DTBs.
> >
> > Note that the SSD1306 does not seem to be using the configuration
> > written to the registers at all. Therefore this patch does not try
> > to maintain these values without changes in DT. For reference an
> > example is added to the DT bindings documentation that reproduces
> > the configuration that is set in the current init code.
> >
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >   .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
> >   drivers/video/fbdev/ssd1307fb.c                    | 192
> > ++++++++++++--------- 2 files changed, 134 insertions(+), 79
> > deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt index
> > 7a12542..637690f 100644 ---
> > a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++
> > b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -15,6
> > +15,16 @@ Required properties:
> >
> >   Optional properties:
> >     - reset-active-low: Is the reset gpio is active on physical low?
> > +  - solomon,segment-no-remap: Display needs normal (non-inverted)
> > data column
> > +                              to segment mapping
> > +  - solomon,com-sequential: Display uses sequential COM pin
> > configuration
> > +  - solomon,com-lrremap: Display uses left-right COM pin remap
> > +  - solomon,com-invdir: Display uses inverted COM pin scan
> > direction
> > +  - solomon,com-offset: Number of the COM pin wired to the first
> > display line
> > +  - solomon,prechargep1: Length of deselect period (phase 1) in
> > clock cycles.
> > +  - solomon,prechargep2: Length of precharge period (phase 2) in
> > clock cycles.
> > +                         This needs to be the higher, the higher
> > the capacitance
> > +                         of the OLED's pixels is
> Aren't the height, width and page-offset also optional? They should
> be set to sane defaults when not supplied. Though the default (which
> is the max really) width/height depends on the actual attached
> display to the chip (I mention this in the vcomh section too below,
> the controller's width/height would be the absolute maximum values,
> the display can always be smaller).
> 
> Same goes to say for the precharge, and probably other parameters. I 
> don't think we have a proper framework to handle the attached
> displays to a controller chip at the moment anyhow?
> 
> >
> >   [0]: Documentation/devicetree/bindings/pwm/pwm.txt
> >
> <snip>
> > +
> > +	/* Set COM direction */
> > +	com_invdir = 0xc0 | (par->com_invdir & 0xf) << 3;
> Shouldn't this be par->com_invdir & 0x1 ?
> The datasheet only mentions 1 bit change for the ssd1306, ssd1307 and 
> ssd1309. I dont' know what the ssd1305 does here though.

Yes, you are right, it should be  par->com_invdir &0x1. The
register of the 1305 is identical to the 1306/7.

> 
> > +	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
> >   	if (ret < 0)
> >   		return ret;
> <snip>
> >
> > -	ret = ssd1307fb_write_cmd(par->client, 0x14);
> > -	if (ret < 0)
> > -		return ret;
> > +		ret = ssd1307fb_write_cmd(par->client, 0x14);
> > +		if (ret < 0)
> > +			return ret;
> > +	};
> I had to look hard for this setting, as my old datasheet had omitted
> the charge pump def.
> 
> but wouldn't you want something like (0x10 | 
> par->device_info->need_chargepump & 0x1 << 2) & 0x14 to follow your 
> previous styles?
> 
> Only bit 2 determines the state of the charge-pump. And I guess it 
> should be safe to use on the other chips as well. My 1309 doesn't
> seem to have a problem with it, I'm working a lot on this display so
> it will be tested thoroughly in the next few weeks.

I didn't look into this so far, I just took that command from the
ssd1306 init code. I just checked the datasheet of the 1306 and I agree
that par->device_info->need_chargepump & 0x1 << 2) & 0x14 should be
what we want here, assuming that the other controllers make no use of
the register 0xBD. I can confirm that my 1305 based display module
seems not to use it. I'll include your suggestion for the next round.

> >
> >   	/* Switch to horizontal addressing mode */
> >   	ret = ssd1307fb_write_cmd(par->client,
> > SSD1307FB_SET_ADDRESS_MODE); @@ -393,6 +390,7 @@ static int
> > ssd1307fb_ssd1306_init(struct ssd1307fb_par *par) if (ret < 0)
> >   		return ret;
> >
> <snip>
> >
> > -static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
> > -	.init	= ssd1307fb_ssd1306_init,
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 0,
> > +	.default_dclk_frq = 8,
> > +	.need_pwm = 0,
> > +	.need_chargepump = 1,
> > +};
> This device info struct, is this really always fixed data? We use a 
> ssd1309 with a MI12864MO i think and the combination of these two
> parts defines atleast the vcomh I would imagine? There are only a
> very limited number of consumers of this driver so for now it won't
> make much of a difference, just mentioning it as it is a configurable
> so it may matter depending on the physical display.

Note that the default_vcomh just holds the default value for vcomh as
stated in the controller's datasheet. It becomes necessary to define
those on a per controller basis since this one of the very few
registers that actually differ between the different ssd130X. As this
is only the default value this is fixed data.
Once it becomes relevant to set this according to the hardware of the
display module (controller + panel) I guess one has to introduce a DT
property for this. For my particular device (see below) the default
value was working nicely, which is why I did not dive into this.

> > +
> > +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
> > +	.default_vcomh = 0x20,
> > +	.default_dclk_div = 1,
> > +	.default_dclk_frq = 12,
> > +	.need_pwm = 1,
> > +	.need_chargepump = 0,
> >   };
> >
> >   static const struct of_device_id ssd1307fb_of_match[] = {
> >   	{
> >   		.compatible = "solomon,ssd1306fb-i2c",
> > -		.data = (void *)&ssd1307fb_ssd1306_ops,
> > +		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
> >   	},
> >   	{
> >   		.compatible = "solomon,ssd1307fb-i2c",
> > -		.data = (void *)&ssd1307fb_ssd1307_ops,
> > +		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
> >   	},
> >   	{},
> >   };
> > @@ -468,8 +479,8 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, par->info = info;
> >   	par->client = client;
> >
> > -	par->ops = (struct ssd1307fb_ops
> > *)of_match_device(ssd1307fb_of_match,
> > -
> > &client->dev)->data;
> > +	par->device_info = (struct ssd1307fb_deviceinfo
> > *)of_match_device(
> > +			ssd1307fb_of_match, &client->dev)->data;
> >
> >   	par->reset = of_get_named_gpio(client->dev.of_node,
> >   					 "reset-gpios", 0);
> > @@ -487,6 +498,27 @@ static int ssd1307fb_probe(struct i2c_client
> > *client, if (of_property_read_u32(node, "solomon,page-offset",
> > &par->page_offset)) par->page_offset = 1;
> While your re-doing the whole driver, why use a default page_offset
> of 1? 0 makes far more sense (its the default on my board also) and 
> logically, we'd start counting at 0 as programmers ;) Also, the 
> datasheet uses 0 as a default preset.

the page_offset is not a quantity that appears in the datasheet. Don't
mix it up with the com-offset (that is referred to as offset in the
datsheet). the page_offset is used in the init code to set the upper
limit of the page address range. 

> >
> > +	if (of_property_read_u32(node, "solomon,com-offset",
> > &par->com_offset))
> > +		par->com_offset = 0;
> > +
> > +	if (of_property_read_u32(node, "solomon,prechargep1",
> > &par->prechargep1))
> > +		par->prechargep1 = 2;
> > +
> > +	if (of_property_read_u32(node, "solomon,prechargep2",
> > &par->prechargep2))
> > +		par->prechargep2 = 0;
> Why set the default to 0 here? The datasheet sets it to 0x2 by
> default for example.

You are right, I will correct this.

> > +
> > +	par->seg_remap = !of_property_read_bool(node,
> > "solomon,segment-no-remap");
> > +	par->com_seq = of_property_read_bool(node,
> > "solomon,com-sequential");
> all the other parameters are somewhat abbreviated, or the property
> name matches the variable name. I'd just abbreviate it to com-seq
> clear and short.

Ok, why not. I will abbreviate the name for v6

> 
> 
> Overal, the driver works and can have a Tested-by: Olliver Schinagl 
> <o.schinagl@ultimaker.com> from me (for the 1309 which I'll submit
> very soon.

Great!

> 
> Olliver
> 
> P.S. Do you have a link for your display? I'm curious as to how it
> looks.

I'm using those two (very similar) displays:
http://www.newhavendisplay.com/nhd22312832ucy3-p-3787.html
http://www.newhavendisplay.com/nhd22312832umb3-p-6086.html

Thomas

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

* [PATCHv6 00/10] Cleanup and add support for SSD1305
  2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
                   ` (11 preceding siblings ...)
  2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-31 18:27 ` Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
                     ` (10 more replies)
  12 siblings, 11 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

Hi,

this patch series is the result of making the ssd1307fb driver work with
a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
this the intialization code for the SSD1306 and the SSD1307 is merged
and based on DT configuration to reflect the various possible wirings
of the SSD130X controller (04/10). Based on these changes it is straight
forward to add support for the SSD1305 controller (06/10).

While working on the driver I realized that it was not possible to
correctly mmap the video memory from userspace since the address handed
to the userspace app is a logical one where it should be a physical one.
Patch 01/10 fixes this. Furthermore the memory reserved by kzalloc is
not page aligned while the address handed to userspace is aligned to the
next page frame. This problem is fixed by using __get_free_pages() in 02/10.

Furthermore a module parameter is added to set the delay for the
deferred io update (07/10). Also the backlight class is implemented to make
the contrast setting available in userspace (09/10).

changes since v1 (thanks to Maxime for the feedback):
- dedicated patch for fixing smem_start address
- remove page reserve upon vmalloc
- remove return value check upon display turn-off at module unload
- use a module parameter refreshrate rather than delaydivider
- allocate fbdefio dynamically
- use sysfs_create_groups to create sysfs entries
- remove contrast, vhcom and dclk properties from DT since they are
  not part of hw description. The contrast module parameter was added
  to set contrast at load time. vhcom and dclk stays at it's default
  values for now.
- add new DT properties to in tree users of ssd130X
- rebased to apply on top of linux-next

changes since v2 (thanks to Maxime again):
- free memory allocated by vmalloc on driver unload
- set default values in the init code to the ones of the existing ssd1307
  init code
- added two ACKs (Maxime Ripard)

changes since v3:
- use backlight class rather than dedicated sysfs files to set the 
  contrast (Thanks to Tomi Valkeinen)
- remove [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel
- add new patch to blank the display (unreviewed)
- allocate video memory through __get_free_pages() rather than vmalloc
  (Thanks to Geert Uytterhoeven)
- minor rewordings of the commit messages

changes since v4 (thanks to Maxime):
- added two ACKs (Maxime Ripard)
- fixed typo: s/REFRASHRATE/REFRESHRATE
- updated the documentation to make clear the unit of com-offset
- move addition of the module parameter contrast to a separate patch (09/11)
- fix indentation errors
- get rid of device_id in the device_info struct

changes since v5:
- remove [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set
  the initial contrast
- remove unnecessary variable initialization in the deviceinfo struct as
  pointed out by Maxime
- make the variable dclk_div hold the actual divider rather than the
  corresponding bit value
- remove ret variable in ssd1307fb_blank() (thanks to Olliver Schinagl)
- fixed bit mask for com_invdir as indicated by Olliver
- change initialization of the charge pump as suggested by Olliver
- change the default value for prechargep2 to 0x2 (thanks to Olliver)
- change DT property name "com-sequential" to "com-seq"
- added one ACK (Maxime Ripard)
- added Tested-by Olliver Schinagl

Thomas Niederprüm (10):
  fbdev: ssd1307fb: fix memory address smem_start.
  fbdev: ssd1307fb: Allocate page aligned video memory.
  of: Add Solomon Systech vendor prefix.
  fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  ARM: mxs: fix in tree users of ssd1306
  fbdev: ssd1307fb: Add support for SSD1305
  fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  fbdev: ssd1307fb: Turn off display on driver unload.
  fbdev: ssd1307fb: add backlight controls for setting the contrast
  fbdev: ssd1307fb: Add blank mode

 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 .../devicetree/bindings/video/ssd1307fb.txt        |  23 +-
 arch/arm/boot/dts/imx28-cfa10036.dts               |   3 +
 drivers/video/fbdev/Kconfig                        |   1 +
 drivers/video/fbdev/ssd1307fb.c                    | 288 +++++++++++++++------
 5 files changed, 234 insertions(+), 82 deletions(-)

-- 
2.3.0


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

* [PATCHv6 01/10] fbdev: ssd1307fb: fix memory address smem_start.
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

the smem_start pointer of the framebuffer info struct needs to hold the
physical address rather than the logical address. Right now the logical
address returned by kmalloc is stored. This patch converts this address
to a physical address and thus fixes a driver crash on mmaping the
framebuffer memory due to an access to the wrong memory address.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f7ed6d9..61e0ce8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -515,7 +515,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	info->var.blue.offset = 0;
 
 	info->screen_base = (u8 __force __iomem *)vmem;
-	info->fix.smem_start = (unsigned long)vmem;
+	info->fix.smem_start = __pa(vmem);
 	info->fix.smem_len = vmem_size;
 
 	fb_deferred_io_init(info);
-- 
2.3.0


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

* [PATCHv6 02/10] fbdev: ssd1307fb: Allocate page aligned video memory.
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

Currently the videomemory is allocated by kmalloc, making it a memory
region that is not necessarily page aligend. This leads to problems
upon mmap call, where the video memory's address gets aligned to the
next page boundary. The result is that the userspace program that issued
the mmap call is not able to access the video memory from the start to
the next page boundary.

This patch changes the allocation of the video memory to use
__get_free_pages() in order to obtain memory that is aligned
to page boundaries.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 61e0ce8..8d34c56 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -489,7 +489,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	vmem_size = par->width * par->height / 8;
 
-	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+					get_order(vmem_size));
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
 		ret = -ENOMEM;
@@ -573,6 +574,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	if (par->ops->remove)
 		par->ops->remove(par);
 	fb_deferred_io_cleanup(info);
+	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
 	framebuffer_release(info);
 
 	return 0;
-- 
2.3.0


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

* [PATCHv6 03/10] of: Add Solomon Systech vendor prefix.
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-04-01 20:33     ` Rob Herring
  2015-03-31 18:27   ` [PATCHv6 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
                     ` (7 subsequent siblings)
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the solomon prefix for Solomon Systech Limited.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index d3f4809..933c8f5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -169,6 +169,7 @@ sitronix	Sitronix Technology Corporation
 smsc	Standard Microsystems Corporation
 snps	Synopsys, Inc.
 solidrun	SolidRun
+solomon        Solomon Systech Limited
 sony	Sony Corporation
 spansion	Spansion Inc.
 sprd	Spreadtrum Communications Inc.
-- 
2.3.0


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

* [PATCHv6 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (2 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-04-01 16:00     ` Maxime Ripard
  2015-03-31 18:27   ` [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The 130X controllers are very similar from the configuration point of view.
The configuration registers for the SSD1305/6/7 are bit identical (except the
the VHCOM register and the the default values for clock setup register). This
patch unifies the init code of the controller and adds hardware specific
properties to DT that are needed to correctly initialize the device.

The SSD130X can be wired to the OLED panel in various ways. Even for the
same controller this wiring can differ from one display module to another
and can not be probed by software. The added DT properties reflect these
hardware decisions of the display module manufacturer.
The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
possibilities for the COM signals pin configuration and readout direction
of the video memory. The 'segment-no-remap' allows the inversion of the
memory-to-pin mapping ultimately inverting the order of the controllers
output pins. The 'prechargepX' values need to be adapted according to the
capacitance of the OLEDs pixel cells.

So far these hardware specific bits are hard coded in the init code, making
the driver usable only for one certain wiring of the controller. This patch
makes the driver usable with all possible hardware setups, given a valid hw
description in DT. If these values are not set in DT the default values,
as they are set in the ssd1307 init code right now, are used. This implies
that without the corresponding DT property "segment-no-remap" the segment
remap of the ssd130X controller gets activated. Even though this is not the
default behaviour according to the datasheet it maintains backward
compatibility with older DTBs.

Note that the SSD1306 does not seem to be using the configuration written to
the registers at all. Therefore this patch does not try to maintain these
values without changes in DT. For reference an example is added to the DT
bindings documentation that reproduces the configuration that is set in the
current init code.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Tested-by: Olliver Schinagl <o.schinagl@ultimaker.com>
---
 .../devicetree/bindings/video/ssd1307fb.txt        |  21 +++
 drivers/video/fbdev/ssd1307fb.c                    | 177 ++++++++++++---------
 2 files changed, 125 insertions(+), 73 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 7a12542..635efa3 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -15,6 +15,16 @@ Required properties:
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
+  - solomon,segment-no-remap: Display needs normal (non-inverted) data column
+                              to segment mapping
+  - solomon,com-seq: Display uses sequential COM pin configuration
+  - solomon,com-lrremap: Display uses left-right COM pin remap
+  - solomon,com-invdir: Display uses inverted COM pin scan direction
+  - solomon,com-offset: Number of the COM pin wired to the first display line
+  - solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
+  - solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
+                         This needs to be the higher, the higher the capacitance
+                         of the OLED's pixels is
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -26,3 +36,14 @@ ssd1307: oled@3c {
         reset-gpios = <&gpio2 7>;
         reset-active-low;
 };
+
+ssd1306: oled@3c {
+        compatible = "solomon,ssd1306fb-i2c";
+        reg = <0x3c>;
+        pwms = <&pwm 4 3000>;
+        reset-gpios = <&gpio2 7>;
+        reset-active-low;
+        solomon,com-lrremap;
+        solomon,com-invdir;
+        solomon,com-offset = <32>;
+};
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 8d34c56..8667c77 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -40,20 +40,34 @@
 
 struct ssd1307fb_par;
 
-struct ssd1307fb_ops {
-	int (*init)(struct ssd1307fb_par *);
-	int (*remove)(struct ssd1307fb_par *);
+struct ssd1307fb_deviceinfo {
+	u32 default_vcomh;
+	u32 default_dclk_div;
+	u32 default_dclk_frq;
+	int need_pwm;
+	int need_chargepump;
 };
 
 struct ssd1307fb_par {
+	u32 com_invdir;
+	u32 com_lrremap;
+	u32 com_offset;
+	u32 com_seq;
+	u32 contrast;
+	u32 dclk_div;
+	u32 dclk_frq;
+	struct ssd1307fb_deviceinfo *device_info;
 	struct i2c_client *client;
 	u32 height;
 	struct fb_info *info;
-	struct ssd1307fb_ops *ops;
 	u32 page_offset;
+	u32 prechargep1;
+	u32 prechargep2;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 seg_remap;
+	u32 vcomh;
 	u32 width;
 };
 
@@ -254,69 +268,46 @@ static struct fb_deferred_io ssd1307fb_defio = {
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
-static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par)
+static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
+	u32 precharge, dclk, com_invdir, compins;
 
-	par->pwm = pwm_get(&par->client->dev, NULL);
-	if (IS_ERR(par->pwm)) {
-		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
-		return PTR_ERR(par->pwm);
-	}
-
-	par->pwm_period = pwm_get_period(par->pwm);
-	/* Enable the PWM */
-	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
-	pwm_enable(par->pwm);
-
-	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
-		par->pwm->pwm, par->pwm_period);
-
-	/* Map column 127 of the OLED to segment 0 */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
-	if (ret < 0)
-		return ret;
-
-	/* Turn on the display */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
+	if (par->device_info->need_pwm) {
+		par->pwm = pwm_get(&par->client->dev, NULL);
+		if (IS_ERR(par->pwm)) {
+			dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+			return PTR_ERR(par->pwm);
+		}
 
-static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par)
-{
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
-	return 0;
-}
+		par->pwm_period = pwm_get_period(par->pwm);
+		/* Enable the PWM */
+		pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+		pwm_enable(par->pwm);
 
-static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
-	.init	= ssd1307fb_ssd1307_init,
-	.remove	= ssd1307fb_ssd1307_remove,
-};
-
-static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
-{
-	int ret;
+		dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
+			par->pwm->pwm, par->pwm_period);
+	};
 
 	/* Set initial contrast */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x7f);
-	if (ret < 0)
-		return ret;
-
-	/* Set COM direction */
-	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
 	if (ret < 0)
 		return ret;
 
 	/* Set segment re-map */
-	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (par->seg_remap) {
+		ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+		if (ret < 0)
+			return ret;
+	};
+
+	/* Set COM direction */
+	com_invdir = 0xc0 | (par->com_invdir & 0x1) << 3;
+	ret = ssd1307fb_write_cmd(par->client,  com_invdir);
 	if (ret < 0)
 		return ret;
 
@@ -334,7 +325,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	ret = ssd1307fb_write_cmd(par->client, par->com_offset);
 	if (ret < 0)
 		return ret;
 
@@ -343,7 +334,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0xf0);
+	dclk = ((par->dclk_div - 1) & 0xf) | (par->dclk_frq & 0xf) << 4;
+	ret = ssd1307fb_write_cmd(par->client, dclk);
 	if (ret < 0)
 		return ret;
 
@@ -352,7 +344,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4;
+	ret = ssd1307fb_write_cmd(par->client, precharge);
 	if (ret < 0)
 		return ret;
 
@@ -361,7 +354,9 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x22);
+	compins = 0x02 | (!par->com_seq & 0x1) << 4
+				   | (par->com_lrremap & 0x1) << 5;
+	ret = ssd1307fb_write_cmd(par->client, compins);
 	if (ret < 0)
 		return ret;
 
@@ -370,7 +365,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x49);
+	ret = ssd1307fb_write_cmd(par->client, par->vcomh);
 	if (ret < 0)
 		return ret;
 
@@ -379,7 +374,8 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
-	ret = ssd1307fb_write_cmd(par->client, 0x14);
+	ret = ssd1307fb_write_cmd(par->client,
+		(par->device_info->need_chargepump & 0x1 << 2) & 0x14);
 	if (ret < 0)
 		return ret;
 
@@ -393,6 +389,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+	/* Set column range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
 	if (ret < 0)
 		return ret;
@@ -405,6 +402,7 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	if (ret < 0)
 		return ret;
 
+	/* Set page range */
 	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
 	if (ret < 0)
 		return ret;
@@ -426,18 +424,28 @@ static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
-static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
-	.init	= ssd1307fb_ssd1306_init,
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 8,
+	.need_chargepump = 1,
+};
+
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
+	.default_vcomh = 0x20,
+	.default_dclk_div = 2,
+	.default_dclk_frq = 12,
+	.need_pwm = 1,
 };
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
 		.compatible = "solomon,ssd1306fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1306_ops,
+		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
 	{
 		.compatible = "solomon,ssd1307fb-i2c",
-		.data = (void *)&ssd1307fb_ssd1307_ops,
+		.data = (void *)&ssd1307fb_ssd1307_deviceinfo,
 	},
 	{},
 };
@@ -468,8 +476,8 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	par->info = info;
 	par->client = client;
 
-	par->ops = (struct ssd1307fb_ops *)of_match_device(ssd1307fb_of_match,
-							   &client->dev)->data;
+	par->device_info = (struct ssd1307fb_deviceinfo *)of_match_device(
+			ssd1307fb_of_match, &client->dev)->data;
 
 	par->reset = of_get_named_gpio(client->dev.of_node,
 					 "reset-gpios", 0);
@@ -487,6 +495,27 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
 		par->page_offset = 1;
 
+	if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset))
+		par->com_offset = 0;
+
+	if (of_property_read_u32(node, "solomon,prechargep1", &par->prechargep1))
+		par->prechargep1 = 2;
+
+	if (of_property_read_u32(node, "solomon,prechargep2", &par->prechargep2))
+		par->prechargep2 = 2;
+
+	par->seg_remap = !of_property_read_bool(node, "solomon,segment-no-remap");
+	par->com_seq = of_property_read_bool(node, "solomon,com-seq");
+	par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap");
+	par->com_invdir = of_property_read_bool(node, "solomon,com-invdir");
+
+	par->contrast = 127;
+	par->vcomh = par->device_info->default_vcomh;
+
+	/* Setup display timing */
+	par->dclk_div = par->device_info->default_dclk_div;
+	par->dclk_frq = par->device_info->default_dclk_frq;
+
 	vmem_size = par->width * par->height / 8;
 
 	vmem = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -539,11 +568,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	gpio_set_value(par->reset, 1);
 	udelay(4);
 
-	if (par->ops->init) {
-		ret = par->ops->init(par);
-		if (ret)
-			goto reset_oled_error;
-	}
+	ret = ssd1307fb_init(par);
+	if (ret)
+		goto reset_oled_error;
 
 	ret = register_framebuffer(info);
 	if (ret) {
@@ -556,8 +583,10 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	return 0;
 
 panel_init_error:
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->need_pwm) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 fb_alloc_error:
@@ -571,8 +600,10 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	if (par->ops->remove)
-		par->ops->remove(par);
+	if (par->device_info->need_pwm) {
+		pwm_disable(par->pwm);
+		pwm_put(par->pwm);
+	};
 	fb_deferred_io_cleanup(info);
 	__free_pages(__va(info->fix.smem_start), get_order(info->fix.smem_len));
 	framebuffer_release(info);
-- 
2.3.0


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

* [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (3 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-05-07 10:55     ` Tomi Valkeinen
  2015-03-31 18:27   ` [PATCHv6 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
                     ` (5 subsequent siblings)
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch updates the in tree-users of the SSD1306 controller for using
the newly introduced DT properties.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index b04b6b8..570aa33 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -99,6 +99,9 @@
 					solomon,height = <32>;
 					solomon,width = <128>;
 					solomon,page-offset = <0>;
+					solomon,com-lrremap;
+					solomon,com-invdir;
+					solomon,com-offset = <32>;
 				};
 			};
 
-- 
2.3.0


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

* [PATCHv6 06/10] fbdev: ssd1307fb: Add support for SSD1305
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (4 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-04-01 16:01     ` Maxime Ripard
  2015-03-31 18:27   ` [PATCHv6 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
                     ` (4 subsequent siblings)
  10 siblings, 1 reply; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds support for the SSD1305 OLED controller.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 Documentation/devicetree/bindings/video/ssd1307fb.txt |  2 +-
 drivers/video/fbdev/ssd1307fb.c                       | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 635efa3..d1be78d 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -2,7 +2,7 @@
 
 Required properties:
   - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
-    now is i2c, and the supported chips are ssd1306 and ssd1307.
+    now is i2c, and the supported chips are ssd1305, ssd1306 and ssd1307.
   - reg: Should contain address of the controller on the I2C bus. Most likely
          0x3c or 0x3d
   - pwm: Should contain the pwm to use according to the OF device tree PWM
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 8667c77..f685d24 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -424,6 +424,12 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
+	.default_vcomh = 0x34,
+	.default_dclk_div = 1,
+	.default_dclk_frq = 7,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = {
 	.default_vcomh = 0x20,
 	.default_dclk_div = 1,
@@ -440,6 +446,10 @@ static struct ssd1307fb_deviceinfo ssd1307fb_ssd1307_deviceinfo = {
 
 static const struct of_device_id ssd1307fb_of_match[] = {
 	{
+		.compatible = "solomon,ssd1305fb-i2c",
+		.data = (void *)&ssd1307fb_ssd1305_deviceinfo,
+	},
+	{
 		.compatible = "solomon,ssd1306fb-i2c",
 		.data = (void *)&ssd1307fb_ssd1306_deviceinfo,
 	},
@@ -612,6 +622,7 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1305fb", 0 },
 	{ "ssd1306fb", 0 },
 	{ "ssd1307fb", 0 },
 	{ }
-- 
2.3.0


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

* [PATCHv6 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (5 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 08/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
                     ` (3 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds the module parameter "refreshrate" to set delay for the
deferred io. The refresh rate is given in units of Hertz. The default
refresh rate is 1 Hz. The refresh rate set through the newly introduced
parameter applies to all instances of the driver and for now it is not
possible to change it individually.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index f685d24..85eeda0 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -38,6 +38,11 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define REFRESHRATE 1
+
+static u_int refreshrate = REFRESHRATE;
+module_param(refreshrate, uint, 0);
+
 struct ssd1307fb_par;
 
 struct ssd1307fb_deviceinfo {
@@ -263,11 +268,6 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 	ssd1307fb_update_display(info->par);
 }
 
-static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
-	.deferred_io	= ssd1307fb_deferred_io,
-};
-
 static int ssd1307fb_init(struct ssd1307fb_par *par)
 {
 	int ret;
@@ -466,6 +466,7 @@ static int ssd1307fb_probe(struct i2c_client *client,
 {
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
+	struct fb_deferred_io *ssd1307fb_defio;
 	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
@@ -536,10 +537,20 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto fb_alloc_error;
 	}
 
+	ssd1307fb_defio = devm_kzalloc(&client->dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
+	if (!ssd1307fb_defio) {
+		dev_err(&client->dev, "Couldn't allocate deferred io.\n");
+		ret = -ENOMEM;
+		goto fb_alloc_error;
+	}
+
+	ssd1307fb_defio->delay = HZ / refreshrate;
+	ssd1307fb_defio->deferred_io = ssd1307fb_deferred_io;
+
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
 	info->fix.line_length = par->width / 8;
-	info->fbdefio = &ssd1307fb_defio;
+	info->fbdefio = ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
 	info->var.xres = par->width;
-- 
2.3.0


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

* [PATCHv6 08/10] fbdev: ssd1307fb: Turn off display on driver unload.
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (6 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch turns off the display when the driver is unloaded.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/ssd1307fb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 85eeda0..5f3d5a8 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -620,6 +620,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct fb_info *info = i2c_get_clientdata(client);
 	struct ssd1307fb_par *par = info->par;
 
+	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+
 	unregister_framebuffer(info);
 	if (par->device_info->need_pwm) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* [PATCHv6 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (7 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 08/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-03-31 18:27   ` [PATCHv6 10/10] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
  2015-05-27 10:15   ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Tomi Valkeinen
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

The backlight class is used to create userspace handles for
setting the OLED contrast.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/video/fbdev/Kconfig     |  1 +
 drivers/video/fbdev/ssd1307fb.c | 58 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index b3dd417..da70bae 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2478,6 +2478,7 @@ config FB_SSD1307
 	select FB_SYS_IMAGEBLIT
 	select FB_DEFERRED_IO
 	select PWM
+	select FB_BACKLIGHT
 	help
 	  This driver implements support for the Solomon SSD1307
 	  OLED controller over I2C.
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 5f3d5a8..77efed7 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/backlight.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/fb.h>
@@ -38,6 +39,8 @@
 #define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
 #define	SSD1307FB_SET_VCOMH		0xdb
 
+#define MAX_CONTRAST 255
+
 #define REFRESHRATE 1
 
 static u_int refreshrate = REFRESHRATE;
@@ -424,6 +427,43 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
 	return 0;
 }
 
+static int ssd1307fb_update_bl(struct backlight_device *bdev)
+{
+	struct ssd1307fb_par *par = bl_get_data(bdev);
+	int ret;
+	int brightness = bdev->props.brightness;
+
+	par->contrast = brightness;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	if (ret < 0)
+		return ret;
+	ret = ssd1307fb_write_cmd(par->client, par->contrast);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int ssd1307fb_get_brightness(struct backlight_device *bdev)
+{
+	struct ssd1307fb_par *par = bl_get_data(bdev);
+
+	return par->contrast;
+}
+
+static int ssd1307fb_check_fb(struct backlight_device *bdev,
+				   struct fb_info *info)
+{
+	return (info->bl_dev == bdev);
+}
+
+static const struct backlight_ops ssd1307fb_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= ssd1307fb_update_bl,
+	.get_brightness	= ssd1307fb_get_brightness,
+	.check_fb	= ssd1307fb_check_fb,
+};
+
 static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = {
 	.default_vcomh = 0x34,
 	.default_dclk_div = 1,
@@ -464,6 +504,8 @@ MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
 static int ssd1307fb_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
+	struct backlight_device *bl;
+	char bl_name[12];
 	struct fb_info *info;
 	struct device_node *node = client->dev.of_node;
 	struct fb_deferred_io *ssd1307fb_defio;
@@ -599,10 +641,24 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		goto panel_init_error;
 	}
 
+	snprintf(bl_name, sizeof(bl_name), "ssd1307fb%d", info->node);
+	bl = backlight_device_register(bl_name, &client->dev, par,
+				       &ssd1307fb_bl_ops, NULL);
+	bl->props.brightness = par->contrast;
+	bl->props.max_brightness = MAX_CONTRAST;
+	info->bl_dev = bl;
+
+	if (IS_ERR(bl)) {
+		dev_err(&client->dev, "unable to register backlight device: %ld\n",
+			PTR_ERR(bl));
+		goto bl_init_error;
+	}
 	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size);
 
 	return 0;
 
+bl_init_error:
+	unregister_framebuffer(info);
 panel_init_error:
 	if (par->device_info->need_pwm) {
 		pwm_disable(par->pwm);
@@ -622,6 +678,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 
 	ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
 
+	backlight_device_unregister(info->bl_dev);
+
 	unregister_framebuffer(info);
 	if (par->device_info->need_pwm) {
 		pwm_disable(par->pwm);
-- 
2.3.0


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

* [PATCHv6 10/10] fbdev: ssd1307fb: Add blank mode
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (8 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
@ 2015-03-31 18:27   ` Thomas Niederprüm
  2015-05-27 10:15   ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Tomi Valkeinen
  10 siblings, 0 replies; 138+ messages in thread
From: Thomas Niederprüm @ 2015-03-31 18:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen, maxime.ripard, kernel, shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel, Thomas Niederprüm

This patch adds ssd1307fb_blank() to make the framebuffer capable
of blanking.

Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
---
 drivers/video/fbdev/ssd1307fb.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index 77efed7..8fc224c 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -235,6 +235,16 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
 	return count;
 }
 
+static int ssd1307fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct ssd1307fb_par *par = info->par;
+
+	if (blank_mode != FB_BLANK_UNBLANK)
+		return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF);
+	else
+		return ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+}
+
 static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct ssd1307fb_par *par = info->par;
@@ -260,6 +270,7 @@ static struct fb_ops ssd1307fb_ops = {
 	.owner		= THIS_MODULE,
 	.fb_read	= fb_sys_read,
 	.fb_write	= ssd1307fb_write,
+	.fb_blank	= ssd1307fb_blank,
 	.fb_fillrect	= ssd1307fb_fillrect,
 	.fb_copyarea	= ssd1307fb_copyarea,
 	.fb_imageblit	= ssd1307fb_imageblit,
-- 
2.3.0


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

* Re: [PATCHv6 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT
  2015-03-31 18:27   ` [PATCHv6 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
@ 2015-04-01 16:00     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-04-01 16:00 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Tue, Mar 31, 2015 at 08:27:10PM +0200, Thomas Niederprüm wrote:
> The 130X controllers are very similar from the configuration point of view.
> The configuration registers for the SSD1305/6/7 are bit identical (except the
> the VHCOM register and the the default values for clock setup register). This
> patch unifies the init code of the controller and adds hardware specific
> properties to DT that are needed to correctly initialize the device.
> 
> The SSD130X can be wired to the OLED panel in various ways. Even for the
> same controller this wiring can differ from one display module to another
> and can not be probed by software. The added DT properties reflect these
> hardware decisions of the display module manufacturer.
> The 'com-sequential', 'com-lrremap' and 'com-invdir' values define different
> possibilities for the COM signals pin configuration and readout direction
> of the video memory. The 'segment-no-remap' allows the inversion of the
> memory-to-pin mapping ultimately inverting the order of the controllers
> output pins. The 'prechargepX' values need to be adapted according to the
> capacitance of the OLEDs pixel cells.
> 
> So far these hardware specific bits are hard coded in the init code, making
> the driver usable only for one certain wiring of the controller. This patch
> makes the driver usable with all possible hardware setups, given a valid hw
> description in DT. If these values are not set in DT the default values,
> as they are set in the ssd1307 init code right now, are used. This implies
> that without the corresponding DT property "segment-no-remap" the segment
> remap of the ssd130X controller gets activated. Even though this is not the
> default behaviour according to the datasheet it maintains backward
> compatibility with older DTBs.
> 
> Note that the SSD1306 does not seem to be using the configuration written to
> the registers at all. Therefore this patch does not try to maintain these
> values without changes in DT. For reference an example is added to the DT
> bindings documentation that reproduces the configuration that is set in the
> current init code.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> Tested-by: Olliver Schinagl <o.schinagl@ultimaker.com>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv6 06/10] fbdev: ssd1307fb: Add support for SSD1305
  2015-03-31 18:27   ` [PATCHv6 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
@ 2015-04-01 16:01     ` Maxime Ripard
  0 siblings, 0 replies; 138+ messages in thread
From: Maxime Ripard @ 2015-04-01 16:01 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: plagnioj, tomi.valkeinen, kernel, shawn.guo, robh+dt,
	linux-fbdev, linux-kernel

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

On Tue, Mar 31, 2015 at 08:27:12PM +0200, Thomas Niederprüm wrote:
> This patch adds support for the SSD1305 OLED controller.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv6 03/10] of: Add Solomon Systech vendor prefix.
  2015-03-31 18:27   ` [PATCHv6 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
@ 2015-04-01 20:33     ` Rob Herring
  0 siblings, 0 replies; 138+ messages in thread
From: Rob Herring @ 2015-04-01 20:33 UTC (permalink / raw)
  To: Thomas Niederprüm
  Cc: Jean-Christophe Plagniol-Villard, Tomi Valkeinen, Maxime Ripard,
	kernel, Shawn Guo, Rob Herring, linux-fbdev, linux-kernel

On Tue, Mar 31, 2015 at 1:27 PM, Thomas Niederprüm
<niederp@physik.uni-kl.de> wrote:
> This patch adds the solomon prefix for Solomon Systech Limited.
>
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>

In the future, please copy devicetree list.

Acked-by: Rob Herring <robh@kernel.org>


> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index d3f4809..933c8f5 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -169,6 +169,7 @@ sitronix    Sitronix Technology Corporation
>  smsc   Standard Microsystems Corporation
>  snps   Synopsys, Inc.
>  solidrun       SolidRun
> +solomon        Solomon Systech Limited
>  sony   Sony Corporation
>  spansion       Spansion Inc.
>  sprd   Spreadtrum Communications Inc.
> --
> 2.3.0
>

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

* Re: [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-03-31 18:27   ` [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
@ 2015-05-07 10:55     ` Tomi Valkeinen
  2015-05-07 11:28       ` Shawn Guo
  0 siblings, 1 reply; 138+ messages in thread
From: Tomi Valkeinen @ 2015-05-07 10:55 UTC (permalink / raw)
  To: Thomas Niederprüm, maxime.ripard, shawn.guo, Sascha Hauer
  Cc: plagnioj, kernel, robh+dt, linux-fbdev, linux-kernel

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

Hi,

On 31/03/15 21:27, Thomas Niederprüm wrote:
> This patch updates the in tree-users of the SSD1306 controller for using
> the newly introduced DT properties.
> 
> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> ---
>  arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
> index b04b6b8..570aa33 100644
> --- a/arch/arm/boot/dts/imx28-cfa10036.dts
> +++ b/arch/arm/boot/dts/imx28-cfa10036.dts
> @@ -99,6 +99,9 @@
>  					solomon,height = <32>;
>  					solomon,width = <128>;
>  					solomon,page-offset = <0>;
> +					solomon,com-lrremap;
> +					solomon,com-invdir;
> +					solomon,com-offset = <32>;
>  				};
>  			};

Should this patch be merged separately via proper tree? I can take the
rest of the patches via fbdev tree. I can, of course, take this via
fbdev also, if I get an ack.

 Tomi


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

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

* Re: [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-05-07 10:55     ` Tomi Valkeinen
@ 2015-05-07 11:28       ` Shawn Guo
  2015-05-08 13:31         ` Maxime Ripard
  0 siblings, 1 reply; 138+ messages in thread
From: Shawn Guo @ 2015-05-07 11:28 UTC (permalink / raw)
  To: Tomi Valkeinen, maxime.ripard
  Cc: Thomas Niederprüm, Sascha Hauer, plagnioj, robh+dt,
	linux-fbdev, linux-kernel

On Thu, May 07, 2015 at 01:55:35PM +0300, Tomi Valkeinen wrote:
> Hi,
> 
> On 31/03/15 21:27, Thomas Niederprüm wrote:
> > This patch updates the in tree-users of the SSD1306 controller for using
> > the newly introduced DT properties.
> > 
> > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > ---
> >  arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
> > index b04b6b8..570aa33 100644
> > --- a/arch/arm/boot/dts/imx28-cfa10036.dts
> > +++ b/arch/arm/boot/dts/imx28-cfa10036.dts
> > @@ -99,6 +99,9 @@
> >  					solomon,height = <32>;
> >  					solomon,width = <128>;
> >  					solomon,page-offset = <0>;
> > +					solomon,com-lrremap;
> > +					solomon,com-invdir;
> > +					solomon,com-offset = <32>;
> >  				};
> >  			};
> 
> Should this patch be merged separately via proper tree? I can take the
> rest of the patches via fbdev tree. I can, of course, take this via
> fbdev also, if I get an ack.

@Maxime

I assume you're the person, right?

Shawn

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

* Re: [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-05-07 11:28       ` Shawn Guo
@ 2015-05-08 13:31         ` Maxime Ripard
  2015-05-26  7:08           ` Tomi Valkeinen
  0 siblings, 1 reply; 138+ messages in thread
From: Maxime Ripard @ 2015-05-08 13:31 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Tomi Valkeinen, Thomas Niederprüm, Sascha Hauer, plagnioj,
	robh+dt, linux-fbdev, linux-kernel

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

Hi Shawn,

On Thu, May 07, 2015 at 07:28:01PM +0800, Shawn Guo wrote:
> On Thu, May 07, 2015 at 01:55:35PM +0300, Tomi Valkeinen wrote:
> > Hi,
> > 
> > On 31/03/15 21:27, Thomas Niederprüm wrote:
> > > This patch updates the in tree-users of the SSD1306 controller for using
> > > the newly introduced DT properties.
> > > 
> > > Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
> > > ---
> > >  arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
> > > index b04b6b8..570aa33 100644
> > > --- a/arch/arm/boot/dts/imx28-cfa10036.dts
> > > +++ b/arch/arm/boot/dts/imx28-cfa10036.dts
> > > @@ -99,6 +99,9 @@
> > >  					solomon,height = <32>;
> > >  					solomon,width = <128>;
> > >  					solomon,page-offset = <0>;
> > > +					solomon,com-lrremap;
> > > +					solomon,com-invdir;
> > > +					solomon,com-offset = <32>;
> > >  				};
> > >  			};
> > 
> > Should this patch be merged separately via proper tree? I can take the
> > rest of the patches via fbdev tree. I can, of course, take this via
> > fbdev also, if I get an ack.
> 
> @Maxime
> 
> I assume you're the person, right?

I don't have this board right now to actually test, but the changes
look good.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

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

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

* Re: [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-05-08 13:31         ` Maxime Ripard
@ 2015-05-26  7:08           ` Tomi Valkeinen
  2015-05-27  3:03             ` Shawn Guo
  0 siblings, 1 reply; 138+ messages in thread
From: Tomi Valkeinen @ 2015-05-26  7:08 UTC (permalink / raw)
  To: Maxime Ripard, Shawn Guo
  Cc: Thomas Niederprüm, Sascha Hauer, plagnioj, robh+dt,
	linux-fbdev, linux-kernel

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



On 08/05/15 16:31, Maxime Ripard wrote:
> Hi Shawn,
> 
> On Thu, May 07, 2015 at 07:28:01PM +0800, Shawn Guo wrote:
>> On Thu, May 07, 2015 at 01:55:35PM +0300, Tomi Valkeinen wrote:
>>> Hi,
>>>
>>> On 31/03/15 21:27, Thomas Niederprüm wrote:
>>>> This patch updates the in tree-users of the SSD1306 controller for using
>>>> the newly introduced DT properties.
>>>>
>>>> Signed-off-by: Thomas Niederprüm <niederp@physik.uni-kl.de>
>>>> ---
>>>>  arch/arm/boot/dts/imx28-cfa10036.dts | 3 +++
>>>>  1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
>>>> index b04b6b8..570aa33 100644
>>>> --- a/arch/arm/boot/dts/imx28-cfa10036.dts
>>>> +++ b/arch/arm/boot/dts/imx28-cfa10036.dts
>>>> @@ -99,6 +99,9 @@
>>>>  					solomon,height = <32>;
>>>>  					solomon,width = <128>;
>>>>  					solomon,page-offset = <0>;
>>>> +					solomon,com-lrremap;
>>>> +					solomon,com-invdir;
>>>> +					solomon,com-offset = <32>;
>>>>  				};
>>>>  			};
>>>
>>> Should this patch be merged separately via proper tree? I can take the
>>> rest of the patches via fbdev tree. I can, of course, take this via
>>> fbdev also, if I get an ack.
>>
>> @Maxime
>>
>> I assume you're the person, right?
> 
> I don't have this board right now to actually test, but the changes
> look good.

So should I take this via fbdev tree with the rest of the patches? If
so, I want an ack from a relevant dts maintainer. get_maintainers.pl
gives Shawn as the first contact for imx28-cfa10036.dts.

 Tomi


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

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

* Re: [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306
  2015-05-26  7:08           ` Tomi Valkeinen
@ 2015-05-27  3:03             ` Shawn Guo
  0 siblings, 0 replies; 138+ messages in thread
From: Shawn Guo @ 2015-05-27  3:03 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Maxime Ripard, Thomas Niederprüm, Sascha Hauer, plagnioj,
	robh+dt, linux-fbdev, linux-kernel

On Tue, May 26, 2015 at 10:08:23AM +0300, Tomi Valkeinen wrote:
> So should I take this via fbdev tree with the rest of the patches? If
> so, I want an ack from a relevant dts maintainer. get_maintainers.pl
> gives Shawn as the first contact for imx28-cfa10036.dts.

Acked-by: Shawn Guo <shawn.guo@linaro.org>

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

* Re: [PATCHv6 00/10] Cleanup and add support for SSD1305
  2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
                     ` (9 preceding siblings ...)
  2015-03-31 18:27   ` [PATCHv6 10/10] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
@ 2015-05-27 10:15   ` Tomi Valkeinen
  10 siblings, 0 replies; 138+ messages in thread
From: Tomi Valkeinen @ 2015-05-27 10:15 UTC (permalink / raw)
  To: Thomas Niederprüm, plagnioj, maxime.ripard, kernel,
	shawn.guo, robh+dt
  Cc: linux-fbdev, linux-kernel

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



On 31/03/15 21:27, Thomas Niederprüm wrote:
> Hi,
> 
> this patch series is the result of making the ssd1307fb driver work with
> a Newhaven OLED display using the Solomon SSD1305 controller. To achieve
> this the intialization code for the SSD1306 and the SSD1307 is merged
> and based on DT configuration to reflect the various possible wirings
> of the SSD130X controller (04/10). Based on these changes it is straight
> forward to add support for the SSD1305 controller (06/10).
> 
> While working on the driver I realized that it was not possible to
> correctly mmap the video memory from userspace since the address handed
> to the userspace app is a logical one where it should be a physical one.
> Patch 01/10 fixes this. Furthermore the memory reserved by kzalloc is
> not page aligned while the address handed to userspace is aligned to the
> next page frame. This problem is fixed by using __get_free_pages() in 02/10.
> 
> Furthermore a module parameter is added to set the delay for the
> deferred io update (07/10). Also the backlight class is implemented to make
> the contrast setting available in userspace (09/10).
> 
> changes since v1 (thanks to Maxime for the feedback):
> - dedicated patch for fixing smem_start address
> - remove page reserve upon vmalloc
> - remove return value check upon display turn-off at module unload
> - use a module parameter refreshrate rather than delaydivider
> - allocate fbdefio dynamically
> - use sysfs_create_groups to create sysfs entries
> - remove contrast, vhcom and dclk properties from DT since they are
>   not part of hw description. The contrast module parameter was added
>   to set contrast at load time. vhcom and dclk stays at it's default
>   values for now.
> - add new DT properties to in tree users of ssd130X
> - rebased to apply on top of linux-next
> 
> changes since v2 (thanks to Maxime again):
> - free memory allocated by vmalloc on driver unload
> - set default values in the init code to the ones of the existing ssd1307
>   init code
> - added two ACKs (Maxime Ripard)
> 
> changes since v3:
> - use backlight class rather than dedicated sysfs files to set the 
>   contrast (Thanks to Tomi Valkeinen)
> - remove [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel
> - add new patch to blank the display (unreviewed)
> - allocate video memory through __get_free_pages() rather than vmalloc
>   (Thanks to Geert Uytterhoeven)
> - minor rewordings of the commit messages
> 
> changes since v4 (thanks to Maxime):
> - added two ACKs (Maxime Ripard)
> - fixed typo: s/REFRASHRATE/REFRESHRATE
> - updated the documentation to make clear the unit of com-offset
> - move addition of the module parameter contrast to a separate patch (09/11)
> - fix indentation errors
> - get rid of device_id in the device_info struct
> 
> changes since v5:
> - remove [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set
>   the initial contrast
> - remove unnecessary variable initialization in the deviceinfo struct as
>   pointed out by Maxime
> - make the variable dclk_div hold the actual divider rather than the
>   corresponding bit value
> - remove ret variable in ssd1307fb_blank() (thanks to Olliver Schinagl)
> - fixed bit mask for com_invdir as indicated by Olliver
> - change initialization of the charge pump as suggested by Olliver
> - change the default value for prechargep2 to 0x2 (thanks to Olliver)
> - change DT property name "com-sequential" to "com-seq"
> - added one ACK (Maxime Ripard)
> - added Tested-by Olliver Schinagl

I have queued this version for 4.2, with all the acks.

 Tomi


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

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

end of thread, other threads:[~2015-05-27 10:16 UTC | newest]

Thread overview: 138+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-06 22:28 [PATCH 0/8] Cleanup and add support for SSD1305 niederp
2015-02-06 22:28 ` [PATCH 1/8] Documentation: dts: add missing Solomon Systech vendor prefix niederp
2015-02-06 22:28 ` [PATCH 2/8] fbdev: ssd1307fb: Unify init code and make controller configurable from device tree niederp
2015-02-07 10:42   ` Maxime Ripard
2015-02-07 14:59     ` Thomas Niederprüm
2015-02-07 15:19       ` Noralf Trønnes
2015-02-09 10:37         ` Thomas Niederprüm
2015-02-12 16:58         ` Maxime Ripard
2015-02-12 16:41       ` Maxime Ripard
2015-02-14 16:12         ` Thomas Niederprüm
2015-02-23  9:43           ` Maxime Ripard
2015-02-06 22:28 ` [PATCH 3/8] fbdev: ssd1307fb: Add support for SSD1305 niederp
2015-02-06 22:28 ` [PATCH 4/8] fbdev: ssd1307fb: Use vmalloc to allocate video memory niederp
2015-02-07 11:18   ` Maxime Ripard
2015-02-07 15:35     ` Thomas Niederprüm
2015-02-12 15:11       ` Maxime Ripard
2015-02-14 14:22         ` Thomas Niederprüm
2015-02-14 15:36           ` Maxime Ripard
2015-03-10 11:28           ` Tomi Valkeinen
2015-03-13 21:31             ` Thomas Niederprüm
2015-03-14 22:02               ` Geert Uytterhoeven
2015-03-20 11:37                 ` Tomi Valkeinen
2015-03-20 12:12                   ` Geert Uytterhoeven
2015-03-20 14:47                   ` Maxime Ripard
2015-03-20 15:24                     ` Geert Uytterhoeven
2015-03-20 20:27                       ` Thomas Niederprüm
2015-03-20 15:25                     ` Tomi Valkeinen
2015-03-20 20:36                       ` Thomas Niederprüm
2015-02-06 22:28 ` [PATCH 5/8] fbdev: ssd1307fb: Add module parameter bitsperpixel niederp
2015-02-07 11:20   ` Maxime Ripard
2015-02-07 16:05     ` Thomas Niederprüm
2015-02-14 15:54       ` Maxime Ripard
2015-03-10 10:45         ` Tomi Valkeinen
2015-03-13 19:25           ` Thomas Niederprüm
2015-03-25 10:56           ` Olliver Schinagl
2015-03-25 16:02             ` Maxime Ripard
2015-02-06 22:28 ` [PATCH 6/8] fbdev: ssd1307fb: Add module parameter to set update delay of the deffered io niederp
2015-02-07 11:26   ` Maxime Ripard
2015-02-07 16:12     ` Thomas Niederprüm
2015-02-09  9:03       ` Maxime Ripard
2015-02-06 22:28 ` [PATCH 7/8] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace niederp
2015-02-07 11:43   ` Maxime Ripard
2015-02-07 16:42     ` Thomas Niederprüm
2015-02-09  8:52       ` Maxime Ripard
2015-03-10 10:49         ` Tomi Valkeinen
2015-03-13 19:21           ` Thomas Niederprüm
2015-02-06 22:28 ` [PATCH 8/8] fbdev: ssd1307fb: Turn off display on driver unload niederp
2015-02-07 11:45   ` Maxime Ripard
2015-02-07 16:49     ` Thomas Niederprüm
2015-03-01 22:27 ` [PATCHv2 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
2015-03-01 22:27   ` [PATCHv2 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
2015-03-03  7:17     ` Maxime Ripard
2015-03-01 22:27   ` [PATCHv2 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
2015-03-03  8:52     ` Maxime Ripard
2015-03-03 19:04       ` Thomas Niederprüm
2015-03-01 22:27   ` [PATCHv2 03/10] Documentation: dts: add missing Solomon Systech vendor prefix Thomas Niederprüm
2015-03-01 22:27   ` [PATCHv2 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
2015-03-05 21:49     ` Maxime Ripard
2015-03-01 22:27   ` [PATCHv2 05/10] fbdev: ssd1307fb: fix in tree users of ssd1306 Thomas Niederprüm
2015-03-03  9:31     ` Maxime Ripard
2015-03-01 22:27   ` [PATCHv2 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
2015-03-01 22:28   ` [PATCHv2 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
2015-03-05 22:12     ` Maxime Ripard
2015-03-01 22:28   ` [PATCHv2 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel Thomas Niederprüm
2015-03-01 22:28   ` [PATCHv2 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace Thomas Niederprüm
2015-03-01 22:28   ` [PATCHv2 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
2015-03-03  9:40     ` Maxime Ripard
2015-03-09 22:22 ` [PATCHv3 00/10] fbdev: ssd1307fb: Cleanup and add support for SSD1305 Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 02/10] fbdev: ssd1307fb: Use vmalloc to allocate video memory Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 07/10] fbdev: ssd1307fb: Add module parameter to set refresh rate of the display Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 08/10] fbdev: ssd1307fb: Add module parameter bitsperpixel Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 09/10] fbdev: ssd1307fb: Add sysfs handles to expose contrast and dim setting to userspace Thomas Niederprüm
2015-03-09 22:22   ` [PATCHv3 10/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
2015-03-16 17:11 ` [PATCHv4 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
2015-03-18 17:38     ` Maxime Ripard
2015-03-16 17:11   ` [PATCHv4 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
2015-03-18 19:27     ` Maxime Ripard
2015-03-20 21:12       ` Thomas Niederprüm
2015-03-24 15:24         ` Maxime Ripard
2015-03-16 17:11   ` [PATCHv4 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
2015-03-19 13:18     ` Maxime Ripard
2015-03-20 21:16       ` Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 08/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
2015-03-16 17:11   ` [PATCHv4 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
2015-03-19 13:22     ` Maxime Ripard
2015-03-16 17:11   ` [PATCHv4 10/10] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
2015-03-24 21:23 ` [PATCHv5 00/11] Cleanup and add support for SSD1305 Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 01/11] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 02/11] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 03/11] of: Add Solomon Systech vendor prefix Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 04/11] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
2015-03-24 22:14     ` Maxime Ripard
2015-03-25 20:03       ` Thomas Niederprüm
2015-03-25 15:49     ` Olliver Schinagl
2015-03-25 22:14       ` Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 05/11] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 06/11] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 07/11] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
2015-03-24 21:54     ` Maxime Ripard
2015-03-24 21:23   ` [PATCHv5 08/11] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 09/11] fbdev: ssd1307fb: Add module parameter to set the initial contrast Thomas Niederprüm
2015-03-24 22:16     ` Maxime Ripard
2015-03-25 20:10       ` Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 10/11] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
2015-03-24 21:23   ` [PATCHv5 11/11] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
2015-03-25 15:50     ` Olliver Schinagl
2015-03-25 20:33       ` Thomas Niederprüm
2015-03-25 22:00       ` Maxime Ripard
2015-03-31 18:27 ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Thomas Niederprüm
2015-03-31 18:27   ` [PATCHv6 01/10] fbdev: ssd1307fb: fix memory address smem_start Thomas Niederprüm
2015-03-31 18:27   ` [PATCHv6 02/10] fbdev: ssd1307fb: Allocate page aligned video memory Thomas Niederprüm
2015-03-31 18:27   ` [PATCHv6 03/10] of: Add Solomon Systech vendor prefix Thomas Niederprüm
2015-04-01 20:33     ` Rob Herring
2015-03-31 18:27   ` [PATCHv6 04/10] fbdev: ssd1307fb: Unify init code and obtain hw specific bits from DT Thomas Niederprüm
2015-04-01 16:00     ` Maxime Ripard
2015-03-31 18:27   ` [PATCHv6 05/10] ARM: mxs: fix in tree users of ssd1306 Thomas Niederprüm
2015-05-07 10:55     ` Tomi Valkeinen
2015-05-07 11:28       ` Shawn Guo
2015-05-08 13:31         ` Maxime Ripard
2015-05-26  7:08           ` Tomi Valkeinen
2015-05-27  3:03             ` Shawn Guo
2015-03-31 18:27   ` [PATCHv6 06/10] fbdev: ssd1307fb: Add support for SSD1305 Thomas Niederprüm
2015-04-01 16:01     ` Maxime Ripard
2015-03-31 18:27   ` [PATCHv6 07/10] fbdev: ssd1307fb: Add a module parameter to set the refresh rate Thomas Niederprüm
2015-03-31 18:27   ` [PATCHv6 08/10] fbdev: ssd1307fb: Turn off display on driver unload Thomas Niederprüm
2015-03-31 18:27   ` [PATCHv6 09/10] fbdev: ssd1307fb: add backlight controls for setting the contrast Thomas Niederprüm
2015-03-31 18:27   ` [PATCHv6 10/10] fbdev: ssd1307fb: Add blank mode Thomas Niederprüm
2015-05-27 10:15   ` [PATCHv6 00/10] Cleanup and add support for SSD1305 Tomi Valkeinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).