aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/xburst/patches-3.10/009-Add-ili8960-lcd-driver.patch
blob: 95545ed43e5e22ef34bfc238aaf16319fbfb960c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sun, 27 Jul 2014 09:38:50 +0100
Subject: [PATCH 34/53] NET: multi phy support

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 drivers/net/phy/phy.c |    9 ++++++---
 include/linux/phy.h   |    1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1000,7 +1000,8 @@ void phy_state_machine(struct work_struc
 		/* If the link is down, give up on negotiation for now */
 		if (!phydev->link) {
 			phydev->state = PHY_NOLINK;
-			netif_carrier_off(phydev->attached_dev);
+			if (!phydev->no_auto_carrier_off)
+				netif_carrier_off(phydev->attached_dev);
 			phydev->adjust_link(phydev->attached_dev);
 			break;
 		}
@@ -1083,7 +1084,8 @@ void phy_state_machine(struct work_struc
 			netif_carrier_on(phydev->attached_dev);
 		} else {
 			phydev->state = PHY_NOLINK;
-			netif_carrier_off(phydev->attached_dev);
+			if (!phydev->no_auto_carrier_off)
+				netif_carrier_off(phydev->attached_dev);
 		}
 
 		phydev->adjust_link(phydev->attached_dev);
@@ -1095,7 +1097,8 @@ void phy_state_machine(struct work_struc
 	case PHY_HALTED:
 		if (phydev->link) {
 			phydev->link = 0;
-			netif_carrier_off(phydev->attached_dev);
+			if (!phydev->no_auto_carrier_off)
+				netif_carrier_off(phydev->attached_dev);
 			phydev->adjust_link(phydev->attached_dev);
 			do_suspend = true;
 		}
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -373,6 +373,7 @@ struct phy_device {
 	bool is_pseudo_fixed_link;
 	bool has_fixups;
 	bool suspended;
+	bool no_auto_carrier_off;
 
 	enum phy_state state;
 
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
From ee3a5c779be4d1d270388203cd1c6a734a0bf4ed Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Sun, 1 Aug 2010 21:19:40 +0200
Subject: [PATCH 09/16] Add ili8960 lcd driver

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
 drivers/video/backlight/Kconfig   |    7 +
 drivers/video/backlight/Makefile  |    1 +
 drivers/video/backlight/ili8960.c |  262 +++++++++++++++++++++++++++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/video/backlight/ili8960.c

--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -59,6 +59,13 @@ config LCD_LTV350QV
 
 	  The LTV350QV panel is present on all ATSTK1000 boards.
 
+config LCD_ILI8960
+	tristate "Ilitek ili8960 LCD driver"
+	depends on LCD_CLASS_DEVICE && SPI
+	default n
+	help
+	  Driver for the Ilitek ili8960 LCD controller chip.
+
 config LCD_ILI922X
 	tristate "ILI Technology ILI9221/ILI9222 support"
 	depends on SPI
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_LCD_CLASS_DEVICE)		+= lcd.o
 obj-$(CONFIG_LCD_CORGI)			+= corgi_lcd.o
 obj-$(CONFIG_LCD_HP700)			+= jornada720_lcd.o
 obj-$(CONFIG_LCD_HX8357)		+= hx8357.o
+obj-$(CONFIG_LCD_ILI8960)		+= ili8960.o
 obj-$(CONFIG_LCD_ILI922X)		+= ili922x.o
 obj-$(CONFIG_LCD_ILI9320)		+= ili9320.o
 obj-$(CONFIG_LCD_L4F00242T03)		+= l4f00242t03.o
--- /dev/null
+++ b/drivers/video/backlight/ili8960.c
@@ -0,0 +1,262 @@
+/*
+ *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ *  Driver for Ilitek ili8960 LCD
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/lcd.h>
+#include <linux/delay.h>
+
+struct ili8960 {
+	struct spi_device *spi;
+	struct lcd_device *lcd;
+	bool enabled;
+	unsigned int brightness;
+};
+
+#define ILI8960_REG_BRIGHTNESS	0x03
+#define ILI8960_REG_POWER	0x05
+#define ILI8960_REG_CONTRAST	0x0d
+
+static int ili8960_write_reg(struct spi_device *spi, uint8_t reg,
+				uint8_t data)
+{
+	uint8_t buf[2];
+	buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f);
+	buf[1] = data;
+
+	return spi_write(spi, buf, sizeof(buf));
+}
+
+static int ili8960_programm_power(struct spi_device *spi, bool enabled)
+{
+	int ret;
+
+	if (enabled)
+		mdelay(20);
+
+	ret = ili8960_write_reg(spi, ILI8960_REG_POWER, enabled ? 0xc7 : 0xc6);
+
+	if (!enabled)
+		mdelay(20);
+
+	return ret;
+}
+
+static int ili8960_set_power(struct lcd_device *lcd, int power)
+{
+	struct ili8960 *ili8960 = lcd_get_data(lcd);
+
+	switch (power) {
+	case FB_BLANK_UNBLANK:
+		ili8960->enabled = true;
+		break;
+	default:
+		return 0;
+	}
+
+	return ili8960_programm_power(ili8960->spi, ili8960->enabled);
+}
+
+static int ili8960_early_set_power(struct lcd_device *lcd, int power)
+{
+	struct ili8960 *ili8960 = lcd_get_data(lcd);
+
+	switch (power) {
+	case FB_BLANK_UNBLANK:
+		return 0;
+	default:
+		ili8960->enabled = false;
+		break;
+	}
+
+	return ili8960_programm_power(ili8960->spi, ili8960->enabled);
+}
+
+static int ili8960_get_power(struct lcd_device *lcd)
+{
+	struct ili8960 *ili8960 = lcd_get_data(lcd);
+	return ili8960->enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
+static int ili8960_set_contrast(struct lcd_device *lcd, int contrast)
+{
+	struct ili8960 *ili8960 = lcd_get_data(lcd);
+
+	return ili8960_write_reg(ili8960->spi, ILI8960_REG_CONTRAST, contrast);
+}
+
+static int ili8960_set_mode(struct lcd_device *lcd, struct fb_videomode *mode)
+{
+	if (mode->xres != 320 && mode->yres != 240)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ili8960_set_brightness(struct ili8960 *ili8960, int brightness)
+{
+	int ret;
+
+	ret = ili8960_write_reg(ili8960->spi, ILI8960_REG_BRIGHTNESS, brightness);
+
+	if (ret == 0)
+		ili8960->brightness = brightness;
+
+	return ret;
+}
+
+static ssize_t ili8960_show_brightness(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lcd_device *ld = to_lcd_device(dev);
+	struct ili8960 *ili8960 = lcd_get_data(ld);
+
+	return sprintf(buf, "%u\n", ili8960->brightness);
+}
+
+static ssize_t ili8960_store_brightness(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lcd_device *ld = to_lcd_device(dev);
+	struct ili8960 *ili8960 = lcd_get_data(ld);
+	unsigned long brightness;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &brightness);
+	if (ret)
+		return ret;
+
+	if (brightness > 255)
+		return -EINVAL;
+
+	ili8960_set_brightness(ili8960, brightness);
+
+	return count;
+}
+
+
+static DEVICE_ATTR(brightness, 0644, ili8960_show_brightness,
+	ili8960_store_brightness);
+
+static struct lcd_ops ili8960_lcd_ops = {
+	.set_power = ili8960_set_power,
+	.early_set_power = ili8960_early_set_power,
+	.get_power = ili8960_get_power,
+	.set_contrast = ili8960_set_contrast,
+	.set_mode = ili8960_set_mode,
+};
+
+static int ili8960_probe(struct spi_device *spi)
+{
+	int ret;
+	struct ili8960 *ili8960;
+
+	ili8960 = devm_kzalloc(&spi->dev, sizeof(*ili8960), GFP_KERNEL);
+	if (!ili8960)
+		return -ENOMEM;
+
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_3;
+
+	ret = spi_setup(spi);
+	if (ret) {
+		dev_err(&spi->dev, "Failed to setup spi\n");
+		return ret;
+	}
+
+	ili8960->spi = spi;
+
+	ili8960->lcd = lcd_device_register("ili8960-lcd", &spi->dev, ili8960,
+						&ili8960_lcd_ops);
+
+	if (IS_ERR(ili8960->lcd)) {
+		ret = PTR_ERR(ili8960->lcd);
+		dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret);
+		return ret;
+	}
+
+	ili8960->lcd->props.max_contrast = 255;
+
+	ret = device_create_file(&ili8960->lcd->dev, &dev_attr_brightness);
+	if (ret)
+		goto err_unregister_lcd;
+
+	ili8960_programm_power(ili8960->spi, true);
+	ili8960->enabled = true;
+
+	spi_set_drvdata(spi, ili8960);
+
+	ili8960_write_reg(spi, 0x13, 0x01);
+
+	return 0;
+err_unregister_lcd:
+	lcd_device_unregister(ili8960->lcd);
+	return ret;
+}
+
+static int ili8960_remove(struct spi_device *spi)
+{
+	struct ili8960 *ili8960 = spi_get_drvdata(spi);
+
+	device_remove_file(&ili8960->lcd->dev, &dev_attr_brightness);
+	lcd_device_unregister(ili8960->lcd);
+
+	spi_set_drvdata(spi, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ili8960_suspend(struct spi_device *spi, pm_message_t state)
+{
+	struct ili8960 *ili8960 = spi_get_drvdata(spi);
+
+	if (ili8960->enabled)
+		ili8960_programm_power(ili8960->spi, false);
+
+	return 0;
+}
+
+static int ili8960_resume(struct spi_device *spi)
+{
+	struct ili8960 *ili8960 = spi_get_drvdata(spi);
+
+	if (ili8960->enabled)
+		ili8960_programm_power(ili8960->spi, true);
+
+	return 0;
+}
+
+#else
+#define ili8960_suspend NULL
+#define ili8960_resume NULL
+#endif
+
+static struct spi_driver ili8960_driver = {
+	.driver = {
+		.name = "ili8960",
+		.owner = THIS_MODULE,
+	},
+	.probe = ili8960_probe,
+	.remove = ili8960_remove,
+	.suspend = ili8960_suspend,
+	.resume = ili8960_resume,
+};
+module_spi_driver(ili8960_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LCD driver for Ilitek ili8960");
+MODULE_ALIAS("spi:ili8960");