summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig17
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/atmel_lcdfb.c2
-rw-r--r--drivers/video/backlight/88pm860x_bl.c18
-rw-r--r--drivers/video/backlight/adp5520_bl.c6
-rw-r--r--drivers/video/backlight/adp8860_bl.c14
-rw-r--r--drivers/video/backlight/adp8870_bl.c14
-rw-r--r--drivers/video/backlight/ams369fg06.c6
-rw-r--r--drivers/video/backlight/apple_bl.c4
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c7
-rw-r--r--drivers/video/backlight/backlight.c29
-rw-r--r--drivers/video/backlight/corgi_lcd.c26
-rw-r--r--drivers/video/backlight/da903x_bl.c15
-rw-r--r--drivers/video/backlight/da9052_bl.c2
-rw-r--r--drivers/video/backlight/ep93xx_bl.c2
-rw-r--r--drivers/video/backlight/generic_bl.c4
-rw-r--r--drivers/video/backlight/hp680_bl.c6
-rw-r--r--drivers/video/backlight/ili9320.c18
-rw-r--r--drivers/video/backlight/ili9320.h2
-rw-r--r--drivers/video/backlight/jornada720_bl.c31
-rw-r--r--drivers/video/backlight/l4f00242t03.c9
-rw-r--r--drivers/video/backlight/lcd.c8
-rw-r--r--drivers/video/backlight/ld9040.c4
-rw-r--r--drivers/video/backlight/lm3533_bl.c8
-rw-r--r--drivers/video/backlight/lm3630_bl.c10
-rw-r--r--drivers/video/backlight/lm3639_bl.c10
-rw-r--r--drivers/video/backlight/lms283gf05.c23
-rw-r--r--drivers/video/backlight/lp855x_bl.c55
-rw-r--r--drivers/video/backlight/ltv350qv.c6
-rw-r--r--drivers/video/backlight/max8925_bl.c17
-rw-r--r--drivers/video/backlight/omap1_bl.c4
-rw-r--r--drivers/video/backlight/pandora_bl.c8
-rw-r--r--drivers/video/backlight/pcf50633-backlight.c14
-rw-r--r--drivers/video/backlight/platform_lcd.c8
-rw-r--r--drivers/video/backlight/s6e63m0.c8
-rw-r--r--drivers/video/backlight/tdo24m.c39
-rw-r--r--drivers/video/backlight/tosa_bl.c13
-rw-r--r--drivers/video/backlight/tosa_lcd.c30
-rw-r--r--drivers/video/backlight/vgg2432a4.c16
-rw-r--r--drivers/video/clps711xfb.c156
-rw-r--r--drivers/video/console/newport_con.c11
-rw-r--r--drivers/video/console/softcursor.c3
-rw-r--r--drivers/video/da8xx-fb.c170
-rw-r--r--drivers/video/exynos/exynos_dp_core.c697
-rw-r--r--drivers/video/exynos/exynos_dp_core.h21
-rw-r--r--drivers/video/exynos/exynos_dp_reg.c77
-rw-r--r--drivers/video/exynos/exynos_dp_reg.h3
-rw-r--r--drivers/video/fsl-diu-fb.c201
-rw-r--r--drivers/video/imxfb.c38
-rw-r--r--drivers/video/mx3fb.c3
-rw-r--r--drivers/video/omap/lcd_inn1510.c7
-rw-r--r--drivers/video/omap/lcdc.c2
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/omap/sossi.c2
-rw-r--r--drivers/video/omap2/Kconfig7
-rw-r--r--drivers/video/omap2/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c23
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c36
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c34
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c89
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c24
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c45
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c17
-rw-r--r--drivers/video/omap2/displays/panel-taal.c72
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c33
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c20
-rw-r--r--drivers/video/omap2/dss/Kconfig35
-rw-r--r--drivers/video/omap2/dss/Makefile7
-rw-r--r--drivers/video/omap2/dss/apply.c331
-rw-r--r--drivers/video/omap2/dss/core.c72
-rw-r--r--drivers/video/omap2/dss/dispc-compat.c667
-rw-r--r--drivers/video/omap2/dss/dispc-compat.h30
-rw-r--r--drivers/video/omap2/dss/dispc.c1102
-rw-r--r--drivers/video/omap2/dss/display-sysfs.c321
-rw-r--r--drivers/video/omap2/dss/display.c386
-rw-r--r--drivers/video/omap2/dss/dpi.c126
-rw-r--r--drivers/video/omap2/dss/dsi.c247
-rw-r--r--drivers/video/omap2/dss/dss.c138
-rw-r--r--drivers/video/omap2/dss/dss.h124
-rw-r--r--drivers/video/omap2/dss/dss_features.c79
-rw-r--r--drivers/video/omap2/dss/dss_features.h12
-rw-r--r--drivers/video/omap2/dss/hdmi.c158
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c82
-rw-r--r--drivers/video/omap2/dss/manager.c39
-rw-r--r--drivers/video/omap2/dss/output.c90
-rw-r--r--drivers/video/omap2/dss/overlay.c17
-rw-r--r--drivers/video/omap2/dss/rfbi.c23
-rw-r--r--drivers/video/omap2/dss/sdi.c11
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h3
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c11
-rw-r--r--drivers/video/omap2/dss/venc.c11
-rw-r--r--drivers/video/omap2/dss/venc_panel.c19
-rw-r--r--drivers/video/omap2/omapfb/Kconfig1
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c48
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c212
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c6
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h20
-rw-r--r--drivers/video/omap2/vram.c514
-rw-r--r--drivers/video/omap2/vrfb.c142
-rw-r--r--drivers/video/s3c-fb.c24
-rw-r--r--drivers/video/sh_mipi_dsi.c69
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c74
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h1
-rw-r--r--drivers/video/ssd1307fb.c396
104 files changed, 4113 insertions, 3843 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0cff083fbbe..e7068c50880 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2045,7 +2045,7 @@ config FB_S3C_DEBUG_REGWRITE
bool "Debug register writes"
depends on FB_S3C
---help---
- Show all register writes via printk(KERN_DEBUG)
+ Show all register writes via pr_debug()
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
@@ -2444,4 +2444,19 @@ config FB_SH_MOBILE_MERAM
Up to 4 memory channels can be configured, allowing 4 RGB or
2 YCbCr framebuffers to be configured.
+config FB_SSD1307
+ tristate "Solomon SSD1307 framebuffer support"
+ depends on FB && I2C
+ depends on OF
+ depends on GENERIC_GPIO
+ select FB_SYS_FOPS
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_DEFERRED_IO
+ select PWM
+ help
+ This driver implements support for the Solomon SSD1307
+ OLED controller over I2C.
+
endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 23e948ebfab..768a137a1ba 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -161,6 +161,7 @@ obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
obj-$(CONFIG_FB_MX3) += mx3fb.o
obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
obj-$(CONFIG_FB_MXS) += mxsfb.o
+obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
# the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 94cac9f9919..12cf5f31ee8 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -19,8 +19,8 @@
#include <linux/backlight.h>
#include <linux/gfp.h>
#include <linux/module.h>
+#include <linux/platform_data/atmel.h>
-#include <mach/board.h>
#include <mach/cpu.h>
#include <asm/gpio.h>
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index b7ec34c57f4..c072ed9aea3 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -117,8 +117,8 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
data->current_brightness = value;
return 0;
out:
- dev_dbg(chip->dev, "set brightness %d failure with return "
- "value:%d\n", value, ret);
+ dev_dbg(chip->dev, "set brightness %d failure with return value: %d\n",
+ value, ret);
return ret;
}
@@ -208,22 +208,19 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle");
if (!res) {
dev_err(&pdev->dev, "No REG resource for duty cycle\n");
- ret = -ENXIO;
- goto out;
+ return -ENXIO;
}
data->reg_duty_cycle = res->start;
res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on");
if (!res) {
dev_err(&pdev->dev, "No REG resorce for always on\n");
- ret = -ENXIO;
- goto out;
+ return -ENXIO;
}
data->reg_always_on = res->start;
res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current");
if (!res) {
dev_err(&pdev->dev, "No REG resource for current\n");
- ret = -ENXIO;
- goto out;
+ return -ENXIO;
}
data->reg_current = res->start;
@@ -231,8 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
sprintf(name, "backlight-%d", pdev->id);
data->port = pdev->id;
data->chip = chip;
- data->i2c = (chip->id == CHIP_PM8606) ? chip->client \
- : chip->companion;
+ data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
data->current_brightness = MAX_BRIGHTNESS;
if (pm860x_backlight_dt_init(pdev, data, name)) {
if (pdata) {
@@ -263,8 +259,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
return 0;
out_brt:
backlight_device_unregister(bl);
-out:
- devm_kfree(&pdev->dev, data);
return ret;
}
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index df5db99af23..a1e41d4faa7 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -282,7 +282,7 @@ static const struct attribute_group adp5520_bl_attr_group = {
.attrs = adp5520_bl_attributes,
};
-static int __devinit adp5520_bl_probe(struct platform_device *pdev)
+static int adp5520_bl_probe(struct platform_device *pdev)
{
struct backlight_properties props;
struct backlight_device *bl;
@@ -333,7 +333,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit adp5520_bl_remove(struct platform_device *pdev)
+static int adp5520_bl_remove(struct platform_device *pdev)
{
struct backlight_device *bl = platform_get_drvdata(pdev);
struct adp5520_bl *data = bl_get_data(bl);
@@ -375,7 +375,7 @@ static struct platform_driver adp5520_bl_driver = {
.owner = THIS_MODULE,
},
.probe = adp5520_bl_probe,
- .remove = __devexit_p(adp5520_bl_remove),
+ .remove = adp5520_bl_remove,
.suspend = adp5520_bl_suspend,
.resume = adp5520_bl_resume,
};
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 77d1fdba597..6bb72c0cb80 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -213,7 +213,7 @@ static int adp8860_led_setup(struct adp8860_led *led)
return ret;
}
-static int __devinit adp8860_led_probe(struct i2c_client *client)
+static int adp8860_led_probe(struct i2c_client *client)
{
struct adp8860_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -295,7 +295,7 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
return ret;
}
-static int __devexit adp8860_led_remove(struct i2c_client *client)
+static int adp8860_led_remove(struct i2c_client *client)
{
struct adp8860_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -310,12 +310,12 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
return 0;
}
#else
-static int __devinit adp8860_led_probe(struct i2c_client *client)
+static int adp8860_led_probe(struct i2c_client *client)
{
return 0;
}
-static int __devexit adp8860_led_remove(struct i2c_client *client)
+static int adp8860_led_remove(struct i2c_client *client)
{
return 0;
}
@@ -650,7 +650,7 @@ static const struct attribute_group adp8860_bl_attr_group = {
.attrs = adp8860_bl_attributes,
};
-static int __devinit adp8860_probe(struct i2c_client *client,
+static int adp8860_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct backlight_device *bl;
@@ -755,7 +755,7 @@ out1:
return ret;
}
-static int __devexit adp8860_remove(struct i2c_client *client)
+static int adp8860_remove(struct i2c_client *client)
{
struct adp8860_bl *data = i2c_get_clientdata(client);
@@ -805,7 +805,7 @@ static struct i2c_driver adp8860_driver = {
.name = KBUILD_MODNAME,
},
.probe = adp8860_probe,
- .remove = __devexit_p(adp8860_remove),
+ .remove = adp8860_remove,
.suspend = adp8860_i2c_suspend,
.resume = adp8860_i2c_resume,
.id_table = adp8860_id,
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index edf7f91c8e6..63c882b8177 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -235,7 +235,7 @@ static int adp8870_led_setup(struct adp8870_led *led)
return ret;
}
-static int __devinit adp8870_led_probe(struct i2c_client *client)
+static int adp8870_led_probe(struct i2c_client *client)
{
struct adp8870_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -320,7 +320,7 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
return ret;
}
-static int __devexit adp8870_led_remove(struct i2c_client *client)
+static int adp8870_led_remove(struct i2c_client *client)
{
struct adp8870_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -335,12 +335,12 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
return 0;
}
#else
-static int __devinit adp8870_led_probe(struct i2c_client *client)
+static int adp8870_led_probe(struct i2c_client *client)
{
return 0;
}
-static int __devexit adp8870_led_remove(struct i2c_client *client)
+static int adp8870_led_remove(struct i2c_client *client)
{
return 0;
}
@@ -839,7 +839,7 @@ static const struct attribute_group adp8870_bl_attr_group = {
.attrs = adp8870_bl_attributes,
};
-static int __devinit adp8870_probe(struct i2c_client *client,
+static int adp8870_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct backlight_properties props;
@@ -929,7 +929,7 @@ out1:
return ret;
}
-static int __devexit adp8870_remove(struct i2c_client *client)
+static int adp8870_remove(struct i2c_client *client)
{
struct adp8870_bl *data = i2c_get_clientdata(client);
@@ -977,7 +977,7 @@ static struct i2c_driver adp8870_driver = {
.name = KBUILD_MODNAME,
},
.probe = adp8870_probe,
- .remove = __devexit_p(adp8870_remove),
+ .remove = adp8870_remove,
.suspend = adp8870_i2c_suspend,
.resume = adp8870_i2c_resume,
.id_table = adp8870_id,
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index 3729238e709..f57e1905236 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -474,7 +474,7 @@ static const struct backlight_ops ams369fg06_backlight_ops = {
.update_status = ams369fg06_set_brightness,
};
-static int __devinit ams369fg06_probe(struct spi_device *spi)
+static int ams369fg06_probe(struct spi_device *spi)
{
int ret = 0;
struct ams369fg06 *lcd = NULL;
@@ -548,7 +548,7 @@ out_lcd_unregister:
return ret;
}
-static int __devexit ams369fg06_remove(struct spi_device *spi)
+static int ams369fg06_remove(struct spi_device *spi)
{
struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
@@ -617,7 +617,7 @@ static struct spi_driver ams369fg06_driver = {
.owner = THIS_MODULE,
},
.probe = ams369fg06_probe,
- .remove = __devexit_p(ams369fg06_remove),
+ .remove = ams369fg06_remove,
.shutdown = ams369fg06_shutdown,
.suspend = ams369fg06_suspend,
.resume = ams369fg06_resume,
diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
index 9dc73ac3709..f088d4c0738 100644
--- a/drivers/video/backlight/apple_bl.c
+++ b/drivers/video/backlight/apple_bl.c
@@ -137,7 +137,7 @@ static const struct hw_data nvidia_chipset_data = {
.set_brightness = nvidia_chipset_set_brightness,
};
-static int __devinit apple_bl_add(struct acpi_device *dev)
+static int apple_bl_add(struct acpi_device *dev)
{
struct backlight_properties props;
struct pci_dev *host;
@@ -196,7 +196,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
return 0;
}
-static int __devexit apple_bl_remove(struct acpi_device *dev, int type)
+static int apple_bl_remove(struct acpi_device *dev, int type)
{
backlight_device_unregister(apple_backlight_device);
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index df1cbb7ef6c..de5e5e74e2a 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -106,10 +106,9 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
pwmbl->pdata->pwm_compare_max);
- dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver "
- "(%lu Hz)\n", pwmbl->pwmc.mck /
- pwmbl->pdata->pwm_compare_max /
- (1 << prescale));
+ dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver (%lu Hz)\n",
+ pwmbl->pwmc.mck / pwmbl->pdata->pwm_compare_max /
+ (1 << prescale));
return pwm_channel_enable(&pwmbl->pwmc);
}
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 297db2fa91f..345f6660d4b 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -370,6 +370,35 @@ void backlight_device_unregister(struct backlight_device *bd)
}
EXPORT_SYMBOL(backlight_device_unregister);
+#ifdef CONFIG_OF
+static int of_parent_match(struct device *dev, void *data)
+{
+ return dev->parent && dev->parent->of_node == data;
+}
+
+/**
+ * of_find_backlight_by_node() - find backlight device by device-tree node
+ * @node: device-tree node of the backlight device
+ *
+ * Returns a pointer to the backlight device corresponding to the given DT
+ * node or NULL if no such backlight device exists or if the device hasn't
+ * been probed yet.
+ *
+ * This function obtains a reference on the backlight device and it is the
+ * caller's responsibility to drop the reference by calling put_device() on
+ * the backlight device's .dev field.
+ */
+struct backlight_device *of_find_backlight_by_node(struct device_node *node)
+{
+ struct device *dev;
+
+ dev = class_find_device(backlight_class, NULL, node, of_parent_match);
+
+ return dev ? to_backlight_device(dev) : NULL;
+}
+EXPORT_SYMBOL(of_find_backlight_by_node);
+#endif
+
static void __exit backlight_class_exit(void)
{
class_destroy(backlight_class);
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index c781768ba89..e323fcbe884 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -6,8 +6,8 @@
* Based on Sharp's 2.4 Backlight Driver
*
* Copyright (c) 2008 Marvell International Ltd.
- * Converted to SPI device based LCD/Backlight device driver
- * by Eric Miao <eric.miao@marvell.com>
+ * Converted to SPI device based LCD/Backlight device driver
+ * by Eric Miao <eric.miao@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -192,7 +192,7 @@ static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode)
{
int adj;
- switch(mode) {
+ switch (mode) {
case CORGI_LCD_MODE_VGA:
/* Setting for VGA */
adj = sharpsl_param.phadadj;
@@ -409,10 +409,10 @@ static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity)
cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted;
if (gpio_is_valid(lcd->gpio_backlight_cont))
- gpio_set_value(lcd->gpio_backlight_cont, cont);
+ gpio_set_value_cansleep(lcd->gpio_backlight_cont, cont);
if (gpio_is_valid(lcd->gpio_backlight_on))
- gpio_set_value(lcd->gpio_backlight_on, intensity);
+ gpio_set_value_cansleep(lcd->gpio_backlight_on, intensity);
if (lcd->kick_battery)
lcd->kick_battery();
@@ -495,8 +495,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on,
"BL_ON");
if (err) {
- dev_err(&spi->dev, "failed to request GPIO%d for "
- "backlight_on\n", pdata->gpio_backlight_on);
+ dev_err(&spi->dev,
+ "failed to request GPIO%d for backlight_on\n",
+ pdata->gpio_backlight_on);
return err;
}
@@ -508,8 +509,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont,
"BL_CONT");
if (err) {
- dev_err(&spi->dev, "failed to request GPIO%d for "
- "backlight_cont\n", pdata->gpio_backlight_cont);
+ dev_err(&spi->dev,
+ "failed to request GPIO%d for backlight_cont\n",
+ pdata->gpio_backlight_cont);
return err;
}
@@ -529,7 +531,7 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
return 0;
}
-static int __devinit corgi_lcd_probe(struct spi_device *spi)
+static int corgi_lcd_probe(struct spi_device *spi)
{
struct backlight_properties props;
struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
@@ -590,7 +592,7 @@ err_unregister_lcd:
return ret;
}
-static int __devexit corgi_lcd_remove(struct spi_device *spi)
+static int corgi_lcd_remove(struct spi_device *spi)
{
struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
@@ -611,7 +613,7 @@ static struct spi_driver corgi_lcd_driver = {
.owner = THIS_MODULE,
},
.probe = corgi_lcd_probe,
- .remove = __devexit_p(corgi_lcd_remove),
+ .remove = corgi_lcd_remove,
.suspend = corgi_lcd_suspend,
.resume = corgi_lcd_resume,
};
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 573c7ece0fd..8179cef0730 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -2,10 +2,10 @@
* Backlight driver for Dialog Semiconductor DA9030/DA9034
*
* Copyright (C) 2008 Compulab, Ltd.
- * Mike Rapoport <mike@compulab.co.il>
+ * Mike Rapoport <mike@compulab.co.il>
*
* Copyright (C) 2006-2008 Marvell International Ltd.
- * Eric Miao <eric.miao@marvell.com>
+ * Eric Miao <eric.miao@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -164,15 +164,14 @@ static int da903x_backlight_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int da903x_backlight_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct backlight_device *bl = dev_get_drvdata(dev);
+
return da903x_backlight_set(bl, 0);
}
static int da903x_backlight_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct backlight_device *bl = dev_get_drvdata(dev);
backlight_update_status(bl);
return 0;
@@ -199,7 +198,7 @@ static struct platform_driver da903x_backlight_driver = {
module_platform_driver(da903x_backlight_driver);
MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
- "Mike Rapoport <mike@compulab.co.il>");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da903x-backlight");
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c
index ac196181fe4..842da5a3ac4 100644
--- a/drivers/video/backlight/da9052_bl.c
+++ b/drivers/video/backlight/da9052_bl.c
@@ -34,7 +34,7 @@ enum {
DA9052_TYPE_WLED3,
};
-static unsigned char wled_bank[] = {
+static const unsigned char wled_bank[] = {
DA9052_LED1_CONF_REG,
DA9052_LED2_CONF_REG,
DA9052_LED3_CONF_REG,
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index 08214e1f095..ef3e21e8f82 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -141,7 +141,7 @@ static struct platform_driver ep93xxbl_driver = {
.owner = THIS_MODULE,
},
.probe = ep93xxbl_probe,
- .remove = __devexit_p(ep93xxbl_remove),
+ .remove = ep93xxbl_remove,
.suspend = ep93xxbl_suspend,
.resume = ep93xxbl_resume,
};
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 8c660fcd250..0ae155be9c8 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -97,8 +97,8 @@ static int genericbl_probe(struct platform_device *pdev)
props.max_brightness = machinfo->max_intensity;
bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
&props);
- if (IS_ERR (bd))
- return PTR_ERR (bd);
+ if (IS_ERR(bd))
+ return PTR_ERR(bd);
platform_set_drvdata(pdev, bd);
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 38aa0027214..5cefd73526f 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -26,7 +26,7 @@
#define HP680_DEFAULT_INTENSITY 10
static int hp680bl_suspended;
-static int current_intensity = 0;
+static int current_intensity;
static DEFINE_SPINLOCK(bl_lock);
static void hp680bl_send_intensity(struct backlight_device *bd)
@@ -103,7 +103,7 @@ static const struct backlight_ops hp680bl_ops = {
.update_status = hp680bl_set_intensity,
};
-static int __devinit hp680bl_probe(struct platform_device *pdev)
+static int hp680bl_probe(struct platform_device *pdev)
{
struct backlight_properties props;
struct backlight_device *bd;
@@ -168,7 +168,7 @@ static int __init hp680bl_init(void)
static void __exit hp680bl_exit(void)
{
platform_device_unregister(hp680bl_device);
- platform_driver_unregister(&hp680bl_driver);
+ platform_driver_unregister(&hp680bl_driver);
}
module_init(hp680bl_init);
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
index 9327cd1b314..1235bf9defc 100644
--- a/drivers/video/backlight/ili9320.c
+++ b/drivers/video/backlight/ili9320.c
@@ -45,7 +45,7 @@ static inline int ili9320_write_spi(struct ili9320 *ili,
/* second message is the data to transfer */
data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE;
- data[1] = value >> 8;
+ data[1] = value >> 8;
data[2] = value;
return spi_sync(spi->dev, &spi->message);
@@ -56,11 +56,10 @@ int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value)
dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value);
return ili->write(ili, reg, value);
}
-
EXPORT_SYMBOL_GPL(ili9320_write);
int ili9320_write_regs(struct ili9320 *ili,
- struct ili9320_reg *values,
+ const struct ili9320_reg *values,
int nr_values)
{
int index;
@@ -74,7 +73,6 @@ int ili9320_write_regs(struct ili9320 *ili,
return 0;
}
-
EXPORT_SYMBOL_GPL(ili9320_write_regs);
static void ili9320_reset(struct ili9320 *lcd)
@@ -171,7 +169,7 @@ static struct lcd_ops ili9320_ops = {
.set_power = ili9320_set_power,
};
-static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+static void ili9320_setup_spi(struct ili9320 *ili,
struct spi_device *dev)
{
struct ili9320_spi *spi = &ili->access.spi;
@@ -197,7 +195,7 @@ static void __devinit ili9320_setup_spi(struct ili9320 *ili,
spi_message_add_tail(&spi->xfer[1], &spi->message);
}
-int __devinit ili9320_probe_spi(struct spi_device *spi,
+int ili9320_probe_spi(struct spi_device *spi,
struct ili9320_client *client)
{
struct ili9320_platdata *cfg = spi->dev.platform_data;
@@ -260,7 +258,6 @@ int __devinit ili9320_probe_spi(struct spi_device *spi,
return ret;
}
-
EXPORT_SYMBOL_GPL(ili9320_probe_spi);
int ili9320_remove(struct ili9320 *ili)
@@ -271,7 +268,6 @@ int ili9320_remove(struct ili9320 *ili)
return 0;
}
-
EXPORT_SYMBOL_GPL(ili9320_remove);
#ifdef CONFIG_PM
@@ -296,20 +292,17 @@ int ili9320_suspend(struct ili9320 *lcd, pm_message_t state)
return 0;
}
-
EXPORT_SYMBOL_GPL(ili9320_suspend);
int ili9320_resume(struct ili9320 *lcd)
{
dev_info(lcd->dev, "resuming from power state %d\n", lcd->power);
- if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) {
+ if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP)
ili9320_write(lcd, ILI9320_POWER1, 0x00);
- }
return ili9320_power(lcd, FB_BLANK_UNBLANK);
}
-
EXPORT_SYMBOL_GPL(ili9320_resume);
#endif
@@ -318,7 +311,6 @@ void ili9320_shutdown(struct ili9320 *lcd)
{
ili9320_power(lcd, FB_BLANK_POWERDOWN);
}
-
EXPORT_SYMBOL_GPL(ili9320_shutdown);
MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h
index e388eca7cac..e0db738f7bb 100644
--- a/drivers/video/backlight/ili9320.h
+++ b/drivers/video/backlight/ili9320.h
@@ -63,7 +63,7 @@ extern int ili9320_write(struct ili9320 *ili,
unsigned int reg, unsigned int value);
extern int ili9320_write_regs(struct ili9320 *ili,
- struct ili9320_reg *values,
+ const struct ili9320_reg *values,
int nr_values);
/* Device probe */
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 16f593b6442..fef6ce4fad7 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -48,7 +48,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd)
jornada_ssp_end();
- return (BL_MAX_BRIGHT - ret);
+ return BL_MAX_BRIGHT - ret;
}
static int jornada_bl_update_status(struct backlight_device *bd)
@@ -77,18 +77,23 @@ static int jornada_bl_update_status(struct backlight_device *bd)
goto out;
}
- /* at this point we expect that the mcu has accepted
- our command and is waiting for our new value
- please note that maximum brightness is 255,
- but due to physical layout it is equal to 0, so we simply
- invert the value (MAX VALUE - NEW VALUE). */
- if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) {
+ /*
+ * at this point we expect that the mcu has accepted
+ * our command and is waiting for our new value
+ * please note that maximum brightness is 255,
+ * but due to physical layout it is equal to 0, so we simply
+ * invert the value (MAX VALUE - NEW VALUE).
+ */
+ if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness)
+ != TXDUMMY) {
pr_err("set brightness failed\n");
ret = -ETIMEDOUT;
}
- /* If infact we get an TXDUMMY as output we are happy and dont
- make any further comments about it */
+ /*
+ * If infact we get an TXDUMMY as output we are happy and dont
+ * make any further comments about it
+ */
out:
jornada_ssp_end();
@@ -121,9 +126,11 @@ static int jornada_bl_probe(struct platform_device *pdev)
bd->props.power = FB_BLANK_UNBLANK;
bd->props.brightness = BL_DEF_BRIGHT;
- /* note. make sure max brightness is set otherwise
- you will get seemingly non-related errors when
- trying to change brightness */
+ /*
+ * note. make sure max brightness is set otherwise
+ * you will get seemingly non-related errors when
+ * trying to change brightness
+ */
jornada_bl_update_status(bd);
platform_set_drvdata(pdev, bd);
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 2d90c0648aa..9a35196d12d 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -4,7 +4,7 @@
* Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*
* Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
- * Inspired by Marek Vasut work in l4f00242t03.c
+ * Inspired by Marek Vasut work in l4f00242t03.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -33,7 +33,6 @@ struct l4f00242t03_priv {
struct regulator *core_reg;
};
-
static void l4f00242t03_reset(unsigned int gpio)
{
pr_debug("l4f00242t03_reset.\n");
@@ -150,7 +149,7 @@ static struct lcd_ops l4f_ops = {
.get_power = l4f00242t03_lcd_power_get,
};
-static int __devinit l4f00242t03_probe(struct spi_device *spi)
+static int l4f00242t03_probe(struct spi_device *spi)
{
struct l4f00242t03_priv *priv;
struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
@@ -230,7 +229,7 @@ err1:
return ret;
}
-static int __devexit l4f00242t03_remove(struct spi_device *spi)
+static int l4f00242t03_remove(struct spi_device *spi)
{
struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
@@ -260,7 +259,7 @@ static struct spi_driver l4f00242t03_driver = {
.owner = THIS_MODULE,
},
.probe = l4f00242t03_probe,
- .remove = __devexit_p(l4f00242t03_remove),
+ .remove = l4f00242t03_remove,
.shutdown = l4f00242t03_shutdown,
};
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index a5d0d024bb9..34fb6bd798c 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -108,7 +108,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr,
static ssize_t lcd_store_power(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- int rc = -ENXIO;
+ int rc;
struct lcd_device *ld = to_lcd_device(dev);
unsigned long power;
@@ -116,6 +116,8 @@ static ssize_t lcd_store_power(struct device *dev,
if (rc)
return rc;
+ rc = -ENXIO;
+
mutex_lock(&ld->ops_lock);
if (ld->ops && ld->ops->set_power) {
pr_debug("set power to %lu\n", power);
@@ -144,7 +146,7 @@ static ssize_t lcd_show_contrast(struct device *dev,
static ssize_t lcd_store_contrast(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- int rc = -ENXIO;
+ int rc;
struct lcd_device *ld = to_lcd_device(dev);
unsigned long contrast;
@@ -152,6 +154,8 @@ static ssize_t lcd_store_contrast(struct device *dev,
if (rc)
return rc;
+ rc = -ENXIO;
+
mutex_lock(&ld->ops_lock);
if (ld->ops && ld->ops->set_contrast) {
pr_debug("set contrast to %lu\n", contrast);
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 58f517fb7d4..1cb35241851 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -788,7 +788,7 @@ out_free_regulator:
return ret;
}
-static int __devexit ld9040_remove(struct spi_device *spi)
+static int ld9040_remove(struct spi_device *spi)
{
struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
@@ -847,7 +847,7 @@ static struct spi_driver ld9040_driver = {
.owner = THIS_MODULE,
},
.probe = ld9040_probe,
- .remove = __devexit_p(ld9040_remove),
+ .remove = ld9040_remove,
.shutdown = ld9040_shutdown,
.suspend = ld9040_suspend,
.resume = ld9040_resume,
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 18dca0c29c6..5d18d4d7f47 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -257,7 +257,7 @@ static struct attribute_group lm3533_bl_attribute_group = {
.attrs = lm3533_bl_attributes
};
-static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
+static int lm3533_bl_setup(struct lm3533_bl *bl,
struct lm3533_bl_platform_data *pdata)
{
int ret;
@@ -269,7 +269,7 @@ static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
}
-static int __devinit lm3533_bl_probe(struct platform_device *pdev)
+static int lm3533_bl_probe(struct platform_device *pdev)
{
struct lm3533 *lm3533;
struct lm3533_bl_platform_data *pdata;
@@ -351,7 +351,7 @@ err_unregister:
return ret;
}
-static int __devexit lm3533_bl_remove(struct platform_device *pdev)
+static int lm3533_bl_remove(struct platform_device *pdev)
{
struct lm3533_bl *bl = platform_get_drvdata(pdev);
struct backlight_device *bd = bl->bd;
@@ -406,7 +406,7 @@ static struct platform_driver lm3533_bl_driver = {
.owner = THIS_MODULE,
},
.probe = lm3533_bl_probe,
- .remove = __devexit_p(lm3533_bl_remove),
+ .remove = lm3533_bl_remove,
.shutdown = lm3533_bl_shutdown,
.suspend = lm3533_bl_suspend,
.resume = lm3533_bl_resume,
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
index dc191441796..a6d637b5c68 100644
--- a/drivers/video/backlight/lm3630_bl.c
+++ b/drivers/video/backlight/lm3630_bl.c
@@ -37,7 +37,7 @@ enum lm3630_leds {
BLED_2
};
-static const char *bled_name[] = {
+static const char * const bled_name[] = {
[BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */
[BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */
[BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */
@@ -55,7 +55,7 @@ struct lm3630_chip_data {
};
/* initialize chip */
-static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip)
+static int lm3630_chip_init(struct lm3630_chip_data *pchip)
{
int ret;
unsigned int reg_val;
@@ -349,7 +349,7 @@ static const struct regmap_config lm3630_regmap = {
.max_register = REG_MAX,
};
-static int __devinit lm3630_probe(struct i2c_client *client,
+static int lm3630_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm3630_platform_data *pdata = client->dev.platform_data;
@@ -429,7 +429,7 @@ err_chip_init:
return ret;
}
-static int __devexit lm3630_remove(struct i2c_client *client)
+static int lm3630_remove(struct i2c_client *client)
{
int ret;
struct lm3630_chip_data *pchip = i2c_get_clientdata(client);
@@ -463,7 +463,7 @@ static struct i2c_driver lm3630_i2c_driver = {
.name = LM3630_NAME,
},
.probe = lm3630_probe,
- .remove = __devexit_p(lm3630_remove),
+ .remove = lm3630_remove,
.id_table = lm3630_id,
};
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
index 585949b5705..7ab2d2a04e4 100644
--- a/drivers/video/backlight/lm3639_bl.c
+++ b/drivers/video/backlight/lm3639_bl.c
@@ -48,7 +48,7 @@ struct lm3639_chip_data {
};
/* initialize chip */
-static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip)
+static int lm3639_chip_init(struct lm3639_chip_data *pchip)
{
int ret;
unsigned int reg_val;
@@ -214,7 +214,7 @@ out_input:
}
-static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store);
+static DEVICE_ATTR(bled_mode, S_IWUSR, NULL, lm3639_bled_mode_store);
/* torch */
static void lm3639_torch_brightness_set(struct led_classdev *cdev,
@@ -299,7 +299,7 @@ static const struct regmap_config lm3639_regmap = {
.max_register = REG_MAX,
};
-static int __devinit lm3639_probe(struct i2c_client *client,
+static int lm3639_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
@@ -397,7 +397,7 @@ err_out:
return ret;
}
-static int __devexit lm3639_remove(struct i2c_client *client)
+static int lm3639_remove(struct i2c_client *client)
{
struct lm3639_chip_data *pchip = i2c_get_clientdata(client);
@@ -425,7 +425,7 @@ static struct i2c_driver lm3639_i2c_driver = {
.name = LM3639_NAME,
},
.probe = lm3639_probe,
- .remove = __devexit_p(lm3639_remove),
+ .remove = lm3639_remove,
.id_table = lm3639_id,
};
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index ea43f225419..55819b38470 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -31,7 +31,7 @@ struct lms283gf05_seq {
};
/* Magic sequences supplied by manufacturer, for details refer to datasheet */
-static struct lms283gf05_seq disp_initseq[] = {
+static const struct lms283gf05_seq disp_initseq[] = {
/* REG, VALUE, DELAY */
{ 0x07, 0x0000, 0 },
{ 0x13, 0x0000, 10 },
@@ -78,7 +78,7 @@ static struct lms283gf05_seq disp_initseq[] = {
{ 0x22, 0x0000, 0 }
};
-static struct lms283gf05_seq disp_pdwnseq[] = {
+static const struct lms283gf05_seq disp_pdwnseq[] = {
{ 0x07, 0x0016, 30 },
{ 0x07, 0x0004, 0 },
@@ -104,7 +104,7 @@ static void lms283gf05_reset(unsigned long gpio, bool inverted)
}
static void lms283gf05_toggle(struct spi_device *spi,
- struct lms283gf05_seq *seq, int sz)
+ const struct lms283gf05_seq *seq, int sz)
{
char buf[3];
int i;
@@ -150,7 +150,7 @@ static struct lcd_ops lms_ops = {
.get_power = NULL,
};
-static int __devinit lms283gf05_probe(struct spi_device *spi)
+static int lms283gf05_probe(struct spi_device *spi)
{
struct lms283gf05_state *st;
struct lms283gf05_pdata *pdata = spi->dev.platform_data;
@@ -158,13 +158,10 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
int ret = 0;
if (pdata != NULL) {
- ret = devm_gpio_request(&spi->dev, pdata->reset_gpio,
- "LMS285GF05 RESET");
- if (ret)
- return ret;
-
- ret = gpio_direction_output(pdata->reset_gpio,
- !pdata->reset_inverted);
+ ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio,
+ GPIOF_DIR_OUT | (!pdata->reset_inverted ?
+ GPIOF_INIT_HIGH : GPIOF_INIT_LOW),
+ "LMS285GF05 RESET");
if (ret)
return ret;
}
@@ -193,7 +190,7 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
return 0;
}
-static int __devexit lms283gf05_remove(struct spi_device *spi)
+static int lms283gf05_remove(struct spi_device *spi)
{
struct lms283gf05_state *st = dev_get_drvdata(&spi->dev);
@@ -208,7 +205,7 @@ static struct spi_driver lms283gf05_driver = {
.owner = THIS_MODULE,
},
.probe = lms283gf05_probe,
- .remove = __devexit_p(lms283gf05_remove),
+ .remove = lms283gf05_remove,
};
module_spi_driver(lms283gf05_driver);
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index aa6d4f71131..6e4db0c874c 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -15,6 +15,7 @@
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/platform_data/lp855x.h>
+#include <linux/pwm.h>
/* Registers */
#define BRIGHTNESS_CTRL 0x00
@@ -34,22 +35,19 @@ struct lp855x {
struct i2c_client *client;
struct backlight_device *bl;
struct device *dev;
- struct mutex xfer_lock;
struct lp855x_platform_data *pdata;
+ struct pwm_device *pwm;
};
static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data)
{
int ret;
- mutex_lock(&lp->xfer_lock);
ret = i2c_smbus_read_byte_data(lp->client, reg);
if (ret < 0) {
- mutex_unlock(&lp->xfer_lock);
dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
return ret;
}
- mutex_unlock(&lp->xfer_lock);
*data = (u8)ret;
return 0;
@@ -57,13 +55,7 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data)
static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data)
{
- int ret;
-
- mutex_lock(&lp->xfer_lock);
- ret = i2c_smbus_write_byte_data(lp->client, reg, data);
- mutex_unlock(&lp->xfer_lock);
-
- return ret;
+ return i2c_smbus_write_byte_data(lp->client, reg, data);
}
static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr)
@@ -121,6 +113,28 @@ static int lp855x_init_registers(struct lp855x *lp)
return ret;
}
+static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
+{
+ unsigned int period = lp->pdata->period_ns;
+ unsigned int duty = br * period / max_br;
+ struct pwm_device *pwm;
+
+ /* request pwm device with the consumer name */
+ if (!lp->pwm) {
+ pwm = devm_pwm_get(lp->dev, lp->chipname);
+ if (IS_ERR(pwm))
+ return;
+
+ lp->pwm = pwm;
+ }
+
+ pwm_config(lp->pwm, duty, period);
+ if (duty)
+ pwm_enable(lp->pwm);
+ else
+ pwm_disable(lp->pwm);
+}
+
static int lp855x_bl_update_status(struct backlight_device *bl)
{
struct lp855x *lp = bl_get_data(bl);
@@ -130,12 +144,10 @@ static int lp855x_bl_update_status(struct backlight_device *bl)
bl->props.brightness = 0;
if (mode == PWM_BASED) {
- struct lp855x_pwm_data *pd = &lp->pdata->pwm_data;
int br = bl->props.brightness;
int max_br = bl->props.max_brightness;
- if (pd->pwm_set_intensity)
- pd->pwm_set_intensity(br, max_br);
+ lp855x_pwm_ctrl(lp, br, max_br);
} else if (mode == REGISTER_BASED) {
u8 val = bl->props.brightness;
@@ -150,14 +162,7 @@ static int lp855x_bl_get_brightness(struct backlight_device *bl)
struct lp855x *lp = bl_get_data(bl);
enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
- if (mode == PWM_BASED) {
- struct lp855x_pwm_data *pd = &lp->pdata->pwm_data;
- int max_br = bl->props.max_brightness;
-
- if (pd->pwm_get_intensity)
- bl->props.brightness = pd->pwm_get_intensity(max_br);
-
- } else if (mode == REGISTER_BASED) {
+ if (mode == REGISTER_BASED) {
u8 val = 0;
lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val);
@@ -266,8 +271,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
lp->chip_id = id->driver_data;
i2c_set_clientdata(cl, lp);
- mutex_init(&lp->xfer_lock);
-
ret = lp855x_init_registers(lp);
if (ret) {
dev_err(lp->dev, "i2c communication err: %d", ret);
@@ -297,7 +300,7 @@ err_dev:
return ret;
}
-static int __devexit lp855x_remove(struct i2c_client *cl)
+static int lp855x_remove(struct i2c_client *cl)
{
struct lp855x *lp = i2c_get_clientdata(cl);
@@ -324,7 +327,7 @@ static struct i2c_driver lp855x_driver = {
.name = "lp855x",
},
.probe = lp855x_probe,
- .remove = __devexit_p(lp855x_remove),
+ .remove = lp855x_remove,
.id_table = lp855x_ids,
};
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 4066a5bbd82..226d813edf0 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -226,7 +226,7 @@ static struct lcd_ops ltv_ops = {
.set_power = ltv350qv_set_power,
};
-static int __devinit ltv350qv_probe(struct spi_device *spi)
+static int ltv350qv_probe(struct spi_device *spi)
{
struct ltv350qv *lcd;
struct lcd_device *ld;
@@ -261,7 +261,7 @@ out_unregister:
return ret;
}
-static int __devexit ltv350qv_remove(struct spi_device *spi)
+static int ltv350qv_remove(struct spi_device *spi)
{
struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
@@ -305,7 +305,7 @@ static struct spi_driver ltv350qv_driver = {
},
.probe = ltv350qv_probe,
- .remove = __devexit_p(ltv350qv_remove),
+ .remove = ltv350qv_remove,
.shutdown = ltv350qv_shutdown,
.suspend = ltv350qv_suspend,
.resume = ltv350qv_resume,
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index f72ba54f364..2c9bce050aa 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -101,7 +101,7 @@ static const struct backlight_ops max8925_backlight_ops = {
.get_brightness = max8925_backlight_get_brightness,
};
-static int __devinit max8925_backlight_probe(struct platform_device *pdev)
+static int max8925_backlight_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
@@ -120,15 +120,13 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_REG, 0);
if (!res) {
dev_err(&pdev->dev, "No REG resource for mode control!\n");
- ret = -ENXIO;
- goto out;
+ return -ENXIO;
}
data->reg_mode_cntl = res->start;
res = platform_get_resource(pdev, IORESOURCE_REG, 1);
if (!res) {
dev_err(&pdev->dev, "No REG resource for control!\n");
- ret = -ENXIO;
- goto out;
+ return -ENXIO;
}
data->reg_cntl = res->start;
@@ -142,8 +140,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
&max8925_backlight_ops, &props);
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
- ret = PTR_ERR(bl);
- goto out;
+ return PTR_ERR(bl);
}
bl->props.brightness = MAX_BRIGHTNESS;
@@ -166,12 +163,10 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
return 0;
out_brt:
backlight_device_unregister(bl);
-out:
- devm_kfree(&pdev->dev, data);
return ret;
}
-static int __devexit max8925_backlight_remove(struct platform_device *pdev)
+static int max8925_backlight_remove(struct platform_device *pdev)
{
struct backlight_device *bl = platform_get_drvdata(pdev);
@@ -185,7 +180,7 @@ static struct platform_driver max8925_backlight_driver = {
.owner = THIS_MODULE,
},
.probe = max8925_backlight_probe,
- .remove = __devexit_p(max8925_backlight_remove),
+ .remove = max8925_backlight_remove,
};
module_platform_driver(max8925_backlight_driver);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 9a046a4c98f..af31c269baa 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -42,12 +42,12 @@ struct omap_backlight {
struct omap_backlight_config *pdata;
};
-static void inline omapbl_send_intensity(int intensity)
+static inline void omapbl_send_intensity(int intensity)
{
omap_writeb(intensity, OMAP_PWL_ENABLE);
}
-static void inline omapbl_send_enable(int enable)
+static inline void omapbl_send_enable(int enable)
{
omap_writeb(enable, OMAP_PWL_CLK_ENABLE);
}
diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c
index 4ec30748b44..633b0a22fd6 100644
--- a/drivers/video/backlight/pandora_bl.c
+++ b/drivers/video/backlight/pandora_bl.c
@@ -71,8 +71,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
* set PWM duty cycle to max. TPS61161 seems to use this
* to calibrate it's PWM sensitivity when it starts.
*/
- twl_i2c_write_u8(TWL4030_MODULE_PWM0, MAX_VALUE,
- TWL_PWM0_OFF);
+ twl_i2c_write_u8(TWL_MODULE_PWM, MAX_VALUE, TWL_PWM0_OFF);
/* first enable clock, then PWM0 out */
twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1);
@@ -90,8 +89,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
usleep_range(2000, 10000);
}
- twl_i2c_write_u8(TWL4030_MODULE_PWM0, MIN_VALUE + brightness,
- TWL_PWM0_OFF);
+ twl_i2c_write_u8(TWL_MODULE_PWM, MIN_VALUE + brightness, TWL_PWM0_OFF);
done:
if (brightness != 0)
@@ -132,7 +130,7 @@ static int pandora_backlight_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, bl);
/* 64 cycle period, ON position 0 */
- twl_i2c_write_u8(TWL4030_MODULE_PWM0, 0x80, TWL_PWM0_ON);
+ twl_i2c_write_u8(TWL_MODULE_PWM, 0x80, TWL_PWM0_ON);
bl->props.state |= PANDORABL_WAS_OFF;
bl->props.brightness = MAX_USER_VALUE;
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index c092159f438..e87c7a3394f 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -52,7 +52,7 @@ int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit)
pcf_bl->brightness_limit = limit & 0x3f;
backlight_update_status(pcf_bl->bl);
- return 0;
+ return 0;
}
static int pcf50633_bl_update_status(struct backlight_device *bl)
@@ -99,7 +99,7 @@ static const struct backlight_ops pcf50633_bl_ops = {
.options = BL_CORE_SUSPENDRESUME,
};
-static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
+static int pcf50633_bl_probe(struct platform_device *pdev)
{
struct pcf50633_bl *pcf_bl;
struct device *parent = pdev->dev.parent;
@@ -136,8 +136,10 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
- /* Should be different from bl_props.brightness, so we do not exit
- * update_status early the first time it's called */
+ /*
+ * Should be different from bl_props.brightness, so we do not exit
+ * update_status early the first time it's called
+ */
pcf_bl->brightness = pcf_bl->bl->props.brightness + 1;
backlight_update_status(pcf_bl->bl);
@@ -145,7 +147,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
+static int pcf50633_bl_remove(struct platform_device *pdev)
{
struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
@@ -158,7 +160,7 @@ static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
static struct platform_driver pcf50633_bl_driver = {
.probe = pcf50633_bl_probe,
- .remove = __devexit_p(pcf50633_bl_remove),
+ .remove = pcf50633_bl_remove,
.driver = {
.name = "pcf50633-backlight",
},
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index ca4f5d70fe1..17a6b83f97a 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -27,7 +27,7 @@ struct platform_lcd {
struct plat_lcd_data *pdata;
unsigned int power;
- unsigned int suspended : 1;
+ unsigned int suspended:1;
};
static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd)
@@ -73,7 +73,7 @@ static struct lcd_ops platform_lcd_ops = {
.check_fb = platform_lcd_match,
};
-static int __devinit platform_lcd_probe(struct platform_device *pdev)
+static int platform_lcd_probe(struct platform_device *pdev)
{
struct plat_lcd_data *pdata;
struct platform_lcd *plcd;
@@ -112,7 +112,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
return err;
}
-static int __devexit platform_lcd_remove(struct platform_device *pdev)
+static int platform_lcd_remove(struct platform_device *pdev)
{
struct platform_lcd *plcd = platform_get_drvdata(pdev);
@@ -164,7 +164,7 @@ static struct platform_driver platform_lcd_driver = {
.of_match_table = of_match_ptr(platform_lcd_of_match),
},
.probe = platform_lcd_probe,
- .remove = __devexit_p(platform_lcd_remove),
+ .remove = platform_lcd_remove,
};
module_platform_driver(platform_lcd_driver);
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 6437ae474cf..3e1c1135f6d 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -733,7 +733,7 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
static DEVICE_ATTR(gamma_table, 0444,
s6e63m0_sysfs_show_gamma_table, NULL);
-static int __devinit s6e63m0_probe(struct spi_device *spi)
+static int s6e63m0_probe(struct spi_device *spi)
{
int ret = 0;
struct s6e63m0 *lcd = NULL;
@@ -757,7 +757,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
lcd->spi = spi;
lcd->dev = &spi->dev;
- lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
+ lcd->lcd_pd = spi->dev.platform_data;
if (!lcd->lcd_pd) {
dev_err(&spi->dev, "platform data is NULL.\n");
return -EFAULT;
@@ -825,7 +825,7 @@ out_lcd_unregister:
return ret;
}
-static int __devexit s6e63m0_remove(struct spi_device *spi)
+static int s6e63m0_remove(struct spi_device *spi)
{
struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
@@ -897,7 +897,7 @@ static struct spi_driver s6e63m0_driver = {
.owner = THIS_MODULE,
},
.probe = s6e63m0_probe,
- .remove = __devexit_p(s6e63m0_remove),
+ .remove = s6e63m0_remove,
.shutdown = s6e63m0_shutdown,
.suspend = s6e63m0_suspend,
.resume = s6e63m0_resume,
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 02444d042cd..ad2325f3d65 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -2,7 +2,7 @@
* tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
*
* Copyright (C) 2008 Marvell International Ltd.
- * Eric Miao <eric.miao@marvell.com>
+ * Eric Miao <eric.miao@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -47,7 +47,7 @@ struct tdo24m {
((x1) << 9) | 0x100 | (x2))
#define CMD_NULL (-1)
-static uint32_t lcd_panel_reset[] = {
+static const uint32_t lcd_panel_reset[] = {
CMD0(0x1), /* reset */
CMD0(0x0), /* nop */
CMD0(0x0), /* nop */
@@ -55,7 +55,7 @@ static uint32_t lcd_panel_reset[] = {
CMD_NULL,
};
-static uint32_t lcd_panel_on[] = {
+static const uint32_t lcd_panel_on[] = {
CMD0(0x29), /* Display ON */
CMD2(0xB8, 0xFF, 0xF9), /* Output Control */
CMD0(0x11), /* Sleep out */
@@ -63,7 +63,7 @@ static uint32_t lcd_panel_on[] = {
CMD_NULL,
};
-static uint32_t lcd_panel_off[] = {
+static const uint32_t lcd_panel_off[] = {
CMD0(0x28), /* Display OFF */
CMD2(0xB8, 0x80, 0x02), /* Output Control */
CMD0(0x10), /* Sleep in */
@@ -71,7 +71,7 @@ static uint32_t lcd_panel_off[] = {
CMD_NULL,
};
-static uint32_t lcd_vga_pass_through_tdo24m[] = {
+static const uint32_t lcd_vga_pass_through_tdo24m[] = {
CMD1(0xB0, 0x16),
CMD1(0xBC, 0x80),
CMD1(0xE1, 0x00),
@@ -80,7 +80,7 @@ static uint32_t lcd_vga_pass_through_tdo24m[] = {
CMD_NULL,
};
-static uint32_t lcd_qvga_pass_through_tdo24m[] = {
+static const uint32_t lcd_qvga_pass_through_tdo24m[] = {
CMD1(0xB0, 0x16),
CMD1(0xBC, 0x81),
CMD1(0xE1, 0x00),
@@ -89,8 +89,8 @@ static uint32_t lcd_qvga_pass_through_tdo24m[] = {
CMD_NULL,
};
-static uint32_t lcd_vga_transfer_tdo24m[] = {
- CMD1(0xcf, 0x02), /* Blanking period control (1) */
+static const uint32_t lcd_vga_transfer_tdo24m[] = {
+ CMD1(0xcf, 0x02), /* Blanking period control (1) */
CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
CMD1(0xd1, 0x01), /* CKV timing control on/off */
CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */
@@ -102,7 +102,7 @@ static uint32_t lcd_vga_transfer_tdo24m[] = {
CMD_NULL,
};
-static uint32_t lcd_qvga_transfer[] = {
+static const uint32_t lcd_qvga_transfer[] = {
CMD1(0xd6, 0x02), /* Blanking period control (1) */
CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */
CMD1(0xd8, 0x01), /* CKV timing control on/off */
@@ -115,7 +115,7 @@ static uint32_t lcd_qvga_transfer[] = {
CMD_NULL,
};
-static uint32_t lcd_vga_pass_through_tdo35s[] = {
+static const uint32_t lcd_vga_pass_through_tdo35s[] = {
CMD1(0xB0, 0x16),
CMD1(0xBC, 0x80),
CMD1(0xE1, 0x00),
@@ -123,7 +123,7 @@ static uint32_t lcd_vga_pass_through_tdo35s[] = {
CMD_NULL,
};
-static uint32_t lcd_qvga_pass_through_tdo35s[] = {
+static const uint32_t lcd_qvga_pass_through_tdo35s[] = {
CMD1(0xB0, 0x16),
CMD1(0xBC, 0x81),
CMD1(0xE1, 0x00),
@@ -131,8 +131,8 @@ static uint32_t lcd_qvga_pass_through_tdo35s[] = {
CMD_NULL,
};
-static uint32_t lcd_vga_transfer_tdo35s[] = {
- CMD1(0xcf, 0x02), /* Blanking period control (1) */
+static const uint32_t lcd_vga_transfer_tdo35s[] = {
+ CMD1(0xcf, 0x02), /* Blanking period control (1) */
CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
CMD1(0xd1, 0x01), /* CKV timing control on/off */
CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */
@@ -144,7 +144,7 @@ static uint32_t lcd_vga_transfer_tdo35s[] = {
CMD_NULL,
};
-static uint32_t lcd_panel_config[] = {
+static const uint32_t lcd_panel_config[] = {
CMD2(0xb8, 0xff, 0xf9), /* Output control */
CMD0(0x11), /* sleep out */
CMD1(0xba, 0x01), /* Display mode (1) */
@@ -175,10 +175,11 @@ static uint32_t lcd_panel_config[] = {
CMD_NULL,
};
-static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array)
+static int tdo24m_writes(struct tdo24m *lcd, const uint32_t *array)
{
struct spi_transfer *x = &lcd->xfer;
- uint32_t data, *p = array;
+ const uint32_t *p = array;
+ uint32_t data;
int nparams, err = 0;
for (; *p != CMD_NULL; p++) {
@@ -328,7 +329,7 @@ static struct lcd_ops tdo24m_ops = {
.set_mode = tdo24m_set_mode,
};
-static int __devinit tdo24m_probe(struct spi_device *spi)
+static int tdo24m_probe(struct spi_device *spi)
{
struct tdo24m *lcd;
struct spi_message *m;
@@ -401,7 +402,7 @@ out_unregister:
return err;
}
-static int __devexit tdo24m_remove(struct spi_device *spi)
+static int tdo24m_remove(struct spi_device *spi)
{
struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
@@ -444,7 +445,7 @@ static struct spi_driver tdo24m_driver = {
.owner = THIS_MODULE,
},
.probe = tdo24m_probe,
- .remove = __devexit_p(tdo24m_remove),
+ .remove = tdo24m_remove,
.shutdown = tdo24m_shutdown,
.suspend = tdo24m_suspend,
.resume = tdo24m_resume,
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 49342e1d20b..588682cc161 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -78,7 +78,7 @@ static const struct backlight_ops bl_ops = {
.update_status = tosa_bl_update_status,
};
-static int __devinit tosa_bl_probe(struct i2c_client *client,
+static int tosa_bl_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct backlight_properties props;
@@ -92,14 +92,12 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj;
- ret = devm_gpio_request(&client->dev, TOSA_GPIO_BL_C20MA, "backlight");
+ ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA,
+ GPIOF_OUT_INIT_LOW, "backlight");
if (ret) {
dev_dbg(&data->bl->dev, "Unable to request gpio!\n");
return ret;
}
- ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0);
- if (ret)
- return ret;
i2c_set_clientdata(client, data);
data->i2c = client;
@@ -126,7 +124,7 @@ err_reg:
return ret;
}
-static int __devexit tosa_bl_remove(struct i2c_client *client)
+static int tosa_bl_remove(struct i2c_client *client)
{
struct tosa_bl_data *data = i2c_get_clientdata(client);
@@ -163,14 +161,13 @@ static const struct i2c_device_id tosa_bl_id[] = {
{ },
};
-
static struct i2c_driver tosa_bl_driver = {
.driver = {
.name = "tosa-bl",
.owner = THIS_MODULE,
},
.probe = tosa_bl_probe,
- .remove = __devexit_p(tosa_bl_remove),
+ .remove = tosa_bl_remove,
.suspend = tosa_bl_suspend,
.resume = tosa_bl_resume,
.id_table = tosa_bl_id,
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 33047a66cc2..96bae941585 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -63,7 +63,7 @@ static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data)
int tosa_bl_enable(struct spi_device *spi, int enable)
{
/* bl_enable GP04=1 otherwise GP04=0*/
- return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00);
+ return tosa_tg_send(spi, TG_GPODR2, enable ? 0x01 : 0x00);
}
EXPORT_SYMBOL(tosa_bl_enable);
@@ -91,15 +91,17 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data)
tosa_tg_send(spi, TG_PNLCTL, value);
/* TG LCD pannel power up */
- tosa_tg_send(spi, TG_PINICTL,0x4);
+ tosa_tg_send(spi, TG_PINICTL, 0x4);
mdelay(50);
/* TG LCD GVSS */
- tosa_tg_send(spi, TG_PINICTL,0x0);
+ tosa_tg_send(spi, TG_PINICTL, 0x0);
if (!data->i2c) {
- /* after the pannel is powered up the first time, we can access the i2c bus */
- /* so probe for the DAC */
+ /*
+ * after the pannel is powered up the first time,
+ * we can access the i2c bus so probe for the DAC
+ */
struct i2c_adapter *adap = i2c_get_adapter(0);
struct i2c_board_info info = {
.type = "tosa-bl",
@@ -115,11 +117,11 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data)
struct spi_device *spi = data->spi;
/* TG LCD VHSA off */
- tosa_tg_send(spi, TG_PINICTL,0x4);
+ tosa_tg_send(spi, TG_PINICTL, 0x4);
mdelay(50);
/* TG LCD signal off */
- tosa_tg_send(spi, TG_PINICTL,0x6);
+ tosa_tg_send(spi, TG_PINICTL, 0x6);
mdelay(50);
/* TG Off */
@@ -169,7 +171,7 @@ static struct lcd_ops tosa_lcd_ops = {
.set_mode = tosa_lcd_set_mode,
};
-static int __devinit tosa_lcd_probe(struct spi_device *spi)
+static int tosa_lcd_probe(struct spi_device *spi)
{
int ret;
struct tosa_lcd_data *data;
@@ -193,17 +195,13 @@ static int __devinit tosa_lcd_probe(struct spi_device *spi)
data->spi = spi;
dev_set_drvdata(&spi->dev, data);
- ret = devm_gpio_request(&spi->dev, TOSA_GPIO_TG_ON, "tg #pwr");
+ ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON,
+ GPIOF_OUT_INIT_LOW, "tg #pwr");
if (ret < 0)
goto err_gpio_tg;
mdelay(60);
- ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0);
- if (ret < 0)
- goto err_gpio_tg;
-
- mdelay(60);
tosa_lcd_tg_init(data);
tosa_lcd_tg_on(data);
@@ -226,7 +224,7 @@ err_gpio_tg:
return ret;
}
-static int __devexit tosa_lcd_remove(struct spi_device *spi)
+static int tosa_lcd_remove(struct spi_device *spi)
{
struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
@@ -275,7 +273,7 @@ static struct spi_driver tosa_lcd_driver = {
.owner = THIS_MODULE,
},
.probe = tosa_lcd_probe,
- .remove = __devexit_p(tosa_lcd_remove),
+ .remove = tosa_lcd_remove,
.suspend = tosa_lcd_suspend,
.resume = tosa_lcd_resume,
};
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index b617fae9aa2..45e81b4cf8b 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -26,7 +26,7 @@
/* Device initialisation sequences */
-static struct ili9320_reg vgg_init1[] = {
+static const struct ili9320_reg vgg_init1[] = {
{
.address = ILI9320_POWER1,
.value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0),
@@ -43,7 +43,7 @@ static struct ili9320_reg vgg_init1[] = {
},
};
-static struct ili9320_reg vgg_init2[] = {
+static const struct ili9320_reg vgg_init2[] = {
{
.address = ILI9320_POWER1,
.value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE |
@@ -54,7 +54,7 @@ static struct ili9320_reg vgg_init2[] = {
}
};
-static struct ili9320_reg vgg_gamma[] = {
+static const struct ili9320_reg vgg_gamma[] = {
{
.address = ILI9320_GAMMA1,
.value = 0x0000,
@@ -89,7 +89,7 @@ static struct ili9320_reg vgg_gamma[] = {
};
-static struct ili9320_reg vgg_init0[] = {
+static const struct ili9320_reg vgg_init0[] = {
[0] = {
/* set direction and scan mode gate */
.address = ILI9320_DRIVER,
@@ -217,7 +217,7 @@ static int vgg2432a4_resume(struct spi_device *spi)
}
#else
#define vgg2432a4_suspend NULL
-#define vgg2432a4_resume NULL
+#define vgg2432a4_resume NULL
#endif
static struct ili9320_client vgg2432a4_client = {
@@ -227,7 +227,7 @@ static struct ili9320_client vgg2432a4_client = {
/* Device probe */
-static int __devinit vgg2432a4_probe(struct spi_device *spi)
+static int vgg2432a4_probe(struct spi_device *spi)
{
int ret;
@@ -240,7 +240,7 @@ static int __devinit vgg2432a4_probe(struct spi_device *spi)
return 0;
}
-static int __devexit vgg2432a4_remove(struct spi_device *spi)
+static int vgg2432a4_remove(struct spi_device *spi)
{
return ili9320_remove(dev_get_drvdata(&spi->dev));
}
@@ -256,7 +256,7 @@ static struct spi_driver vgg2432a4_driver = {
.owner = THIS_MODULE,
},
.probe = vgg2432a4_probe,
- .remove = __devexit_p(vgg2432a4_remove),
+ .remove = vgg2432a4_remove,
.shutdown = vgg2432a4_shutdown,
.suspend = vgg2432a4_suspend,
.resume = vgg2432a4_resume,
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index f994c8b8f10..63ecdf8f7ba 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -22,19 +22,15 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <linux/uaccess.h>
-#include <mach/syspld.h>
-
struct fb_info *cfb;
#define CMAP_MAX_SIZE 16
@@ -162,44 +158,12 @@ clps7111fb_set_par(struct fb_info *info)
static int clps7111fb_blank(int blank, struct fb_info *info)
{
- if (blank) {
- if (machine_is_edb7211()) {
- /* Turn off the LCD backlight. */
- clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
-
- /* Power off the LCD DC-DC converter. */
- clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
-
- /* Delay for a little while (half a second). */
- udelay(100);
-
- /* Power off the LCD panel. */
- clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
-
- /* Power off the LCD controller. */
- clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
- SYSCON1);
- }
- } else {
- if (machine_is_edb7211()) {
- /* Power up the LCD controller. */
- clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
- SYSCON1);
-
- /* Power up the LCD panel. */
- clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-
- /* Delay for a little while. */
- udelay(100);
+ /* Enable/Disable LCD controller. */
+ if (blank)
+ clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, SYSCON1);
+ else
+ clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, SYSCON1);
- /* Power up the LCD DC-DC converter. */
- clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
- PDDR);
-
- /* Turn on the LCD backlight. */
- clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
- }
- }
return 0;
}
@@ -214,63 +178,7 @@ static struct fb_ops clps7111fb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static int backlight_proc_show(struct seq_file *m, void *v)
-{
- if (machine_is_edb7211()) {
- seq_printf(m, "%d\n",
- (clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
- }
-
- return 0;
-}
-
-static int backlight_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, backlight_proc_show, NULL);
-}
-
-static ssize_t backlight_proc_write(struct file *file, const char *buffer,
- size_t count, loff_t *pos)
-{
- unsigned char char_value;
- int value;
-
- if (count < 1) {
- return -EINVAL;
- }
-
- if (copy_from_user(&char_value, buffer, 1))
- return -EFAULT;
-
- value = char_value - '0';
-
- if (machine_is_edb7211()) {
- unsigned char port_d;
-
- port_d = clps_readb(PDDR);
-
- if (value) {
- port_d |= EDB_PD3_LCDBL;
- } else {
- port_d &= ~EDB_PD3_LCDBL;
- }
-
- clps_writeb(port_d, PDDR);
- }
-
- return count;
-}
-
-static const struct file_operations backlight_proc_fops = {
- .owner = THIS_MODULE,
- .open = backlight_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .write = backlight_proc_write,
-};
-
-static void __init clps711x_guess_lcd_params(struct fb_info *info)
+static void __devinit clps711x_guess_lcd_params(struct fb_info *info)
{
unsigned int lcdcon, syscon, size;
unsigned long phys_base = PAGE_OFFSET;
@@ -358,7 +266,7 @@ static void __init clps711x_guess_lcd_params(struct fb_info *info)
info->fix.type = FB_TYPE_PACKED_PIXELS;
}
-int __init clps711xfb_init(void)
+static int __devinit clps711x_fb_probe(struct platform_device *pdev)
{
int err = -ENOMEM;
@@ -378,55 +286,29 @@ int __init clps711xfb_init(void)
fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
- if (!proc_create("backlight", 0444, NULL, &backlight_proc_fops)) {
- printk("Couldn't create the /proc entry for the backlight.\n");
- return -EINVAL;
- }
-
- /*
- * Power up the LCD
- */
- if (machine_is_p720t()) {
- PLD_LCDEN = PLD_LCDEN_EN;
- PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
- }
-
- if (machine_is_edb7211()) {
- /* Power up the LCD panel. */
- clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
-
- /* Delay for a little while. */
- udelay(100);
-
- /* Power up the LCD DC-DC converter. */
- clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
-
- /* Turn on the LCD backlight. */
- clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
- }
-
err = register_framebuffer(cfb);
out: return err;
}
-static void __exit clps711xfb_exit(void)
+static int __devexit clps711x_fb_remove(struct platform_device *pdev)
{
unregister_framebuffer(cfb);
kfree(cfb);
- /*
- * Power down the LCD
- */
- if (machine_is_p720t()) {
- PLD_LCDEN = 0;
- PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
- }
+ return 0;
}
-module_init(clps711xfb_init);
-module_exit(clps711xfb_exit);
+static struct platform_driver clps711x_fb_driver = {
+ .driver = {
+ .name = "video-clps711x",
+ .owner = THIS_MODULE,
+ },
+ .probe = clps711x_fb_probe,
+ .remove = __devexit_p(clps711x_fb_remove),
+};
+module_platform_driver(clps711x_fb_driver);
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
-MODULE_DESCRIPTION("CLPS711x framebuffer driver");
+MODULE_DESCRIPTION("CLPS711X framebuffer driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 6d159662904..b05afd03729 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -327,9 +327,16 @@ out_unmap:
static void newport_init(struct vc_data *vc, int init)
{
- vc->vc_cols = newport_xsize / 8;
- vc->vc_rows = newport_ysize / 16;
+ int cols, rows;
+
+ cols = newport_xsize / 8;
+ rows = newport_ysize / 16;
vc->vc_can_do_color = 1;
+ if (init) {
+ vc->vc_cols = cols;
+ vc->vc_rows = rows;
+ } else
+ vc_resize(vc, cols, rows);
}
static void newport_deinit(struct vc_data *c)
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 25f835bf3d7..46dd8f5d2e9 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -35,8 +35,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
dsize = s_pitch * cursor->image.height;
if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
- if (ops->cursor_src != NULL)
- kfree(ops->cursor_src);
+ kfree(ops->cursor_src);
ops->cursor_size = dsize + sizeof(struct fb_image);
ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 80665f66ac1..46534e00fe0 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -213,62 +213,51 @@ static struct fb_fix_screeninfo da8xx_fb_fix __devinitdata = {
.accel = FB_ACCEL_NONE
};
-struct da8xx_panel {
- const char name[25]; /* Full name <vendor>_<model> */
- unsigned short width;
- unsigned short height;
- int hfp; /* Horizontal front porch */
- int hbp; /* Horizontal back porch */
- int hsw; /* Horizontal Sync Pulse Width */
- int vfp; /* Vertical front porch */
- int vbp; /* Vertical back porch */
- int vsw; /* Vertical Sync Pulse Width */
- unsigned int pxl_clk; /* Pixel clock */
- unsigned char invert_pxl_clk; /* Invert Pixel clock */
-};
-
-static struct da8xx_panel known_lcd_panels[] = {
+static struct fb_videomode known_lcd_panels[] = {
/* Sharp LCD035Q3DG01 */
[0] = {
- .name = "Sharp_LCD035Q3DG01",
- .width = 320,
- .height = 240,
- .hfp = 8,
- .hbp = 6,
- .hsw = 0,
- .vfp = 2,
- .vbp = 2,
- .vsw = 0,
- .pxl_clk = 4608000,
- .invert_pxl_clk = 1,
+ .name = "Sharp_LCD035Q3DG01",
+ .xres = 320,
+ .yres = 240,
+ .pixclock = 4608000,
+ .left_margin = 6,
+ .right_margin = 8,
+ .upper_margin = 2,
+ .lower_margin = 2,
+ .hsync_len = 0,
+ .vsync_len = 0,
+ .sync = FB_SYNC_CLK_INVERT |
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
},
/* Sharp LK043T1DG01 */
[1] = {
- .name = "Sharp_LK043T1DG01",
- .width = 480,
- .height = 272,
- .hfp = 2,
- .hbp = 2,
- .hsw = 41,
- .vfp = 2,
- .vbp = 2,
- .vsw = 10,
- .pxl_clk = 7833600,
- .invert_pxl_clk = 0,
+ .name = "Sharp_LK043T1DG01",
+ .xres = 480,
+ .yres = 272,
+ .pixclock = 7833600,
+ .left_margin = 2,
+ .right_margin = 2,
+ .upper_margin = 2,
+ .lower_margin = 2,
+ .hsync_len = 41,
+ .vsync_len = 10,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = 0,
},
[2] = {
/* Hitachi SP10Q010 */
- .name = "SP10Q010",
- .width = 320,
- .height = 240,
- .hfp = 10,
- .hbp = 10,
- .hsw = 10,
- .vfp = 10,
- .vbp = 10,
- .vsw = 10,
- .pxl_clk = 7833600,
- .invert_pxl_clk = 0,
+ .name = "SP10Q010",
+ .xres = 320,
+ .yres = 240,
+ .pixclock = 7833600,
+ .left_margin = 10,
+ .right_margin = 10,
+ .upper_margin = 10,
+ .lower_margin = 10,
+ .hsync_len = 10,
+ .vsync_len = 10,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = 0,
},
};
@@ -399,10 +388,9 @@ static int lcd_cfg_dma(int burst_size, int fifo_th)
reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8);
break;
case 16:
+ default:
reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16);
break;
- default:
- return -EINVAL;
}
reg |= (fifo_th << 8);
@@ -447,7 +435,8 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
}
-static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
+static int lcd_cfg_display(const struct lcd_ctrl_config *cfg,
+ struct fb_videomode *panel)
{
u32 reg;
u32 reg_int;
@@ -456,7 +445,7 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
LCD_MONO_8BIT_MODE |
LCD_MONOCHROME_MODE);
- switch (cfg->p_disp_panel->panel_shade) {
+ switch (cfg->panel_shade) {
case MONOCHROME:
reg |= LCD_MONOCHROME_MODE;
if (cfg->mono_8bit_mode)
@@ -469,7 +458,9 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
break;
case COLOR_PASSIVE:
- if (cfg->stn_565_mode)
+ /* AC bias applicable only for Pasive panels */
+ lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
+ if (cfg->bpp == 12 && cfg->stn_565_mode)
reg |= LCD_STN_565_ENABLE;
break;
@@ -490,22 +481,19 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
- if (cfg->sync_ctrl)
- reg |= LCD_SYNC_CTRL;
- else
- reg &= ~LCD_SYNC_CTRL;
+ reg |= LCD_SYNC_CTRL;
if (cfg->sync_edge)
reg |= LCD_SYNC_EDGE;
else
reg &= ~LCD_SYNC_EDGE;
- if (cfg->invert_line_clock)
+ if (panel->sync & FB_SYNC_HOR_HIGH_ACT)
reg |= LCD_INVERT_LINE_CLOCK;
else
reg &= ~LCD_INVERT_LINE_CLOCK;
- if (cfg->invert_frm_clock)
+ if (panel->sync & FB_SYNC_VERT_HIGH_ACT)
reg |= LCD_INVERT_FRAME_CLOCK;
else
reg &= ~LCD_INVERT_FRAME_CLOCK;
@@ -728,7 +716,7 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
}
static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
- struct da8xx_panel *panel)
+ struct fb_videomode *panel)
{
u32 bpp;
int ret = 0;
@@ -738,7 +726,7 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
/* Calculate the divider */
lcd_calc_clk_divider(par);
- if (panel->invert_pxl_clk)
+ if (panel->sync & FB_SYNC_CLK_INVERT)
lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
else
@@ -750,30 +738,23 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
if (ret < 0)
return ret;
- /* Configure the AC bias properties. */
- lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt);
-
/* Configure the vertical and horizontal sync properties. */
- lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp);
- lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp);
+ lcd_cfg_vertical_sync(panel->lower_margin, panel->vsync_len,
+ panel->upper_margin);
+ lcd_cfg_horizontal_sync(panel->right_margin, panel->hsync_len,
+ panel->left_margin);
/* Configure for disply */
- ret = lcd_cfg_display(cfg);
+ ret = lcd_cfg_display(cfg, panel);
if (ret < 0)
return ret;
- if (QVGA != cfg->p_disp_panel->panel_type)
- return -EINVAL;
+ bpp = cfg->bpp;
- if (cfg->bpp <= cfg->p_disp_panel->max_bpp &&
- cfg->bpp >= cfg->p_disp_panel->min_bpp)
- bpp = cfg->bpp;
- else
- bpp = cfg->p_disp_panel->max_bpp;
if (bpp == 12)
bpp = 16;
- ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width,
- (unsigned int)panel->height, bpp,
+ ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres,
+ (unsigned int)panel->yres, bpp,
cfg->raster_order);
if (ret < 0)
return ret;
@@ -1235,7 +1216,7 @@ static int __devinit fb_probe(struct platform_device *device)
struct da8xx_lcdc_platform_data *fb_pdata =
device->dev.platform_data;
struct lcd_ctrl_config *lcd_cfg;
- struct da8xx_panel *lcdc_info;
+ struct fb_videomode *lcdc_info;
struct fb_info *da8xx_fb_info;
struct clk *fb_clk = NULL;
struct da8xx_fb_par *par;
@@ -1267,7 +1248,7 @@ static int __devinit fb_probe(struct platform_device *device)
goto err_request_mem;
}
- fb_clk = clk_get(&device->dev, NULL);
+ fb_clk = clk_get(&device->dev, "fck");
if (IS_ERR(fb_clk)) {
dev_err(&device->dev, "Can not get device clock\n");
ret = -ENODEV;
@@ -1283,6 +1264,7 @@ static int __devinit fb_probe(struct platform_device *device)
lcd_revision = LCD_VERSION_1;
break;
case 0x4F200800:
+ case 0x4F201000:
lcd_revision = LCD_VERSION_2;
break;
default:
@@ -1323,7 +1305,7 @@ static int __devinit fb_probe(struct platform_device *device)
#ifdef CONFIG_CPU_FREQ
par->lcd_fck_rate = clk_get_rate(fb_clk);
#endif
- par->pxl_clk = lcdc_info->pxl_clk;
+ par->pxl_clk = lcdc_info->pixclock;
if (fb_pdata->panel_power_ctrl) {
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
par->panel_power_ctrl(1);
@@ -1336,8 +1318,8 @@ static int __devinit fb_probe(struct platform_device *device)
}
/* allocate frame buffer */
- par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
- ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE);
+ par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
+ ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
par->vram_size = roundup(par->vram_size/8, ulcm);
par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
@@ -1355,10 +1337,10 @@ static int __devinit fb_probe(struct platform_device *device)
da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt;
da8xx_fb_fix.smem_start = par->vram_phys;
da8xx_fb_fix.smem_len = par->vram_size;
- da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
+ da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8;
par->dma_start = par->vram_phys;
- par->dma_end = par->dma_start + lcdc_info->height *
+ par->dma_end = par->dma_start + lcdc_info->yres *
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
@@ -1384,22 +1366,22 @@ static int __devinit fb_probe(struct platform_device *device)
/* Initialize par */
da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
- da8xx_fb_var.xres = lcdc_info->width;
- da8xx_fb_var.xres_virtual = lcdc_info->width;
+ da8xx_fb_var.xres = lcdc_info->xres;
+ da8xx_fb_var.xres_virtual = lcdc_info->xres;
- da8xx_fb_var.yres = lcdc_info->height;
- da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS;
+ da8xx_fb_var.yres = lcdc_info->yres;
+ da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
da8xx_fb_var.grayscale =
- lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0;
+ lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
- da8xx_fb_var.hsync_len = lcdc_info->hsw;
- da8xx_fb_var.vsync_len = lcdc_info->vsw;
- da8xx_fb_var.right_margin = lcdc_info->hfp;
- da8xx_fb_var.left_margin = lcdc_info->hbp;
- da8xx_fb_var.lower_margin = lcdc_info->vfp;
- da8xx_fb_var.upper_margin = lcdc_info->vbp;
+ da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
+ da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
+ da8xx_fb_var.right_margin = lcdc_info->right_margin;
+ da8xx_fb_var.left_margin = lcdc_info->left_margin;
+ da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
+ da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
/* Initialize fbinfo */
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index d55470e7541..28fd686c6b8 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -18,6 +18,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/of.h>
#include <video/exynos_dp.h>
@@ -48,10 +49,6 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
{
int timeout_loop = 0;
- exynos_dp_init_hpd(dp);
-
- usleep_range(200, 210);
-
while (exynos_dp_get_plug_in_status(dp) != 0) {
timeout_loop++;
if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
@@ -90,9 +87,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp)
*/
/* Read Extension Flag, Number of 128-byte EDID extension blocks */
- exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+ retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
EDID_EXTENSION_FLAG,
&extend_block);
+ if (retval)
+ return retval;
if (extend_block > 0) {
dev_dbg(dp->dev, "EDID data includes a single extension!\n");
@@ -181,14 +180,15 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
int retval;
/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
- exynos_dp_read_bytes_from_dpcd(dp,
- DPCD_ADDR_DPCD_REV,
- 12, buf);
+ retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_DPCD_REV,
+ 12, buf);
+ if (retval)
+ return retval;
/* Read EDID */
for (i = 0; i < 3; i++) {
retval = exynos_dp_read_edid(dp);
- if (retval == 0)
+ if (!retval)
break;
}
@@ -261,11 +261,10 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
}
}
-static void exynos_dp_link_start(struct exynos_dp_device *dp)
+static int exynos_dp_link_start(struct exynos_dp_device *dp)
{
u8 buf[4];
- int lane;
- int lane_count;
+ int lane, lane_count, pll_tries, retval;
lane_count = dp->link_train.lane_count;
@@ -275,10 +274,6 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
for (lane = 0; lane < lane_count; lane++)
dp->link_train.cr_loop[lane] = 0;
- /* Set sink to D0 (Sink Not Ready) mode. */
- exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
- DPCD_SET_POWER_STATE_D0);
-
/* Set link rate and count as you want to establish*/
exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
@@ -286,29 +281,46 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
/* Setup RX configuration */
buf[0] = dp->link_train.link_rate;
buf[1] = dp->link_train.lane_count;
- exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
+ retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
2, buf);
+ if (retval)
+ return retval;
/* Set TX pre-emphasis to minimum */
for (lane = 0; lane < lane_count; lane++)
exynos_dp_set_lane_lane_pre_emphasis(dp,
PRE_EMPHASIS_LEVEL_0, lane);
+ /* Wait for PLL lock */
+ pll_tries = 0;
+ while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+ if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+ dev_err(dp->dev, "Wait for PLL lock timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ pll_tries++;
+ usleep_range(90, 120);
+ }
+
/* Set training pattern 1 */
exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
/* Set RX training pattern */
- exynos_dp_write_byte_to_dpcd(dp,
- DPCD_ADDR_TRAINING_PATTERN_SET,
- DPCD_SCRAMBLING_DISABLED |
- DPCD_TRAINING_PATTERN_1);
+ retval = exynos_dp_write_byte_to_dpcd(dp,
+ DPCD_ADDR_TRAINING_PATTERN_SET,
+ DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1);
+ if (retval)
+ return retval;
for (lane = 0; lane < lane_count; lane++)
buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
- exynos_dp_write_bytes_to_dpcd(dp,
- DPCD_ADDR_TRAINING_LANE0_SET,
- lane_count, buf);
+
+ retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+ lane_count, buf);
+
+ return retval;
}
static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
@@ -332,18 +344,17 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
return 0;
}
-static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
+static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+ int lane_count)
{
int lane;
- u8 lane_align;
u8 lane_status;
- lane_align = link_align[2];
- if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
+ if ((link_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
return -EINVAL;
for (lane = 0; lane < lane_count; lane++) {
- lane_status = exynos_dp_get_lane_status(link_align, lane);
+ lane_status = exynos_dp_get_lane_status(link_status, lane);
lane_status &= DPCD_CHANNEL_EQ_BITS;
if (lane_status != DPCD_CHANNEL_EQ_BITS)
return -EINVAL;
@@ -427,60 +438,60 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
dp->link_train.lt_state = FAILED;
}
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
+ u8 adjust_request[2])
{
- u8 link_status[2];
- int lane;
- int lane_count;
+ int lane, lane_count;
+ u8 voltage_swing, pre_emphasis, training_lane;
- u8 adjust_request[2];
- u8 voltage_swing;
- u8 pre_emphasis;
- u8 training_lane;
+ lane_count = dp->link_train.lane_count;
+ for (lane = 0; lane < lane_count; lane++) {
+ voltage_swing = exynos_dp_get_adjust_request_voltage(
+ adjust_request, lane);
+ pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
+ adjust_request, lane);
+ training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+ DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+ if (voltage_swing == VOLTAGE_LEVEL_3)
+ training_lane |= DPCD_MAX_SWING_REACHED;
+ if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+ training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+
+ dp->link_train.training_lane[lane] = training_lane;
+ }
+}
+
+static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
+{
+ int lane, lane_count, retval;
+ u8 voltage_swing, pre_emphasis, training_lane;
+ u8 link_status[2], adjust_request[2];
usleep_range(100, 101);
lane_count = dp->link_train.lane_count;
- exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
- 2, link_status);
+ retval = exynos_dp_read_bytes_from_dpcd(dp,
+ DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+ if (retval)
+ return retval;
+
+ retval = exynos_dp_read_bytes_from_dpcd(dp,
+ DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+ if (retval)
+ return retval;
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
/* set training pattern 2 for EQ */
exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
- for (lane = 0; lane < lane_count; lane++) {
- exynos_dp_read_bytes_from_dpcd(dp,
- DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
- 2, adjust_request);
- voltage_swing = exynos_dp_get_adjust_request_voltage(
- adjust_request, lane);
- pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
- adjust_request, lane);
- training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
- DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
- if (voltage_swing == VOLTAGE_LEVEL_3)
- training_lane |= DPCD_MAX_SWING_REACHED;
- if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
- training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
-
- dp->link_train.training_lane[lane] = training_lane;
-
- exynos_dp_set_lane_link_training(dp,
- dp->link_train.training_lane[lane],
- lane);
- }
-
- exynos_dp_write_byte_to_dpcd(dp,
- DPCD_ADDR_TRAINING_PATTERN_SET,
- DPCD_SCRAMBLING_DISABLED |
- DPCD_TRAINING_PATTERN_2);
-
- exynos_dp_write_bytes_to_dpcd(dp,
- DPCD_ADDR_TRAINING_LANE0_SET,
- lane_count,
- dp->link_train.training_lane);
+ retval = exynos_dp_write_byte_to_dpcd(dp,
+ DPCD_ADDR_TRAINING_PATTERN_SET,
+ DPCD_SCRAMBLING_DISABLED |
+ DPCD_TRAINING_PATTERN_2);
+ if (retval)
+ return retval;
dev_info(dp->dev, "Link Training Clock Recovery success\n");
dp->link_train.lt_state = EQUALIZER_TRAINING;
@@ -488,152 +499,116 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
for (lane = 0; lane < lane_count; lane++) {
training_lane = exynos_dp_get_lane_link_training(
dp, lane);
- exynos_dp_read_bytes_from_dpcd(dp,
- DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
- 2, adjust_request);
voltage_swing = exynos_dp_get_adjust_request_voltage(
adjust_request, lane);
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
adjust_request, lane);
- if (voltage_swing == VOLTAGE_LEVEL_3 ||
- pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
- dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
- goto reduce_link_rate;
- }
-
- if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
- voltage_swing) &&
- (DPCD_PRE_EMPHASIS_GET(training_lane) ==
- pre_emphasis)) {
+ if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
+ voltage_swing &&
+ DPCD_PRE_EMPHASIS_GET(training_lane) ==
+ pre_emphasis)
dp->link_train.cr_loop[lane]++;
- if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
- dev_err(dp->dev, "CR Max loop\n");
- goto reduce_link_rate;
- }
- }
-
- training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
- DPCD_PRE_EMPHASIS_SET(pre_emphasis);
- if (voltage_swing == VOLTAGE_LEVEL_3)
- training_lane |= DPCD_MAX_SWING_REACHED;
- if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
- training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+ if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+ voltage_swing == VOLTAGE_LEVEL_3 ||
+ pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+ dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+ dp->link_train.cr_loop[lane],
+ voltage_swing, pre_emphasis);
+ exynos_dp_reduce_link_rate(dp);
+ return -EIO;
+ }
+ }
+ }
- dp->link_train.training_lane[lane] = training_lane;
+ exynos_dp_get_adjust_training_lane(dp, adjust_request);
- exynos_dp_set_lane_link_training(dp,
- dp->link_train.training_lane[lane], lane);
- }
+ for (lane = 0; lane < lane_count; lane++)
+ exynos_dp_set_lane_link_training(dp,
+ dp->link_train.training_lane[lane], lane);
- exynos_dp_write_bytes_to_dpcd(dp,
- DPCD_ADDR_TRAINING_LANE0_SET,
- lane_count,
+ retval = exynos_dp_write_bytes_to_dpcd(dp,
+ DPCD_ADDR_TRAINING_LANE0_SET, lane_count,
dp->link_train.training_lane);
- }
-
- return 0;
+ if (retval)
+ return retval;
-reduce_link_rate:
- exynos_dp_reduce_link_rate(dp);
- return -EIO;
+ return retval;
}
static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
{
- u8 link_status[2];
- u8 link_align[3];
- int lane;
- int lane_count;
+ int lane, lane_count, retval;
u32 reg;
-
- u8 adjust_request[2];
- u8 voltage_swing;
- u8 pre_emphasis;
- u8 training_lane;
+ u8 link_align, link_status[2], adjust_request[2];
usleep_range(400, 401);
lane_count = dp->link_train.lane_count;
- exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
- 2, link_status);
+ retval = exynos_dp_read_bytes_from_dpcd(dp,
+ DPCD_ADDR_LANE0_1_STATUS, 2, link_status);
+ if (retval)
+ return retval;
- if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
- link_align[0] = link_status[0];
- link_align[1] = link_status[1];
+ if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
+ exynos_dp_reduce_link_rate(dp);
+ return -EIO;
+ }
- exynos_dp_read_byte_from_dpcd(dp,
- DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
- &link_align[2]);
+ retval = exynos_dp_read_bytes_from_dpcd(dp,
+ DPCD_ADDR_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+ if (retval)
+ return retval;
- for (lane = 0; lane < lane_count; lane++) {
- exynos_dp_read_bytes_from_dpcd(dp,
- DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
- 2, adjust_request);
- voltage_swing = exynos_dp_get_adjust_request_voltage(
- adjust_request, lane);
- pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
- adjust_request, lane);
- training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
- DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+ retval = exynos_dp_read_byte_from_dpcd(dp,
+ DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED, &link_align);
+ if (retval)
+ return retval;
- if (voltage_swing == VOLTAGE_LEVEL_3)
- training_lane |= DPCD_MAX_SWING_REACHED;
- if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
- training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
+ exynos_dp_get_adjust_training_lane(dp, adjust_request);
- dp->link_train.training_lane[lane] = training_lane;
- }
+ if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+ /* traing pattern Set to Normal */
+ exynos_dp_training_pattern_dis(dp);
- if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
- /* traing pattern Set to Normal */
- exynos_dp_training_pattern_dis(dp);
+ dev_info(dp->dev, "Link Training success!\n");
- dev_info(dp->dev, "Link Training success!\n");
-
- exynos_dp_get_link_bandwidth(dp, &reg);
- dp->link_train.link_rate = reg;
- dev_dbg(dp->dev, "final bandwidth = %.2x\n",
- dp->link_train.link_rate);
+ exynos_dp_get_link_bandwidth(dp, &reg);
+ dp->link_train.link_rate = reg;
+ dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+ dp->link_train.link_rate);
- exynos_dp_get_lane_count(dp, &reg);
- dp->link_train.lane_count = reg;
- dev_dbg(dp->dev, "final lane count = %.2x\n",
- dp->link_train.lane_count);
+ exynos_dp_get_lane_count(dp, &reg);
+ dp->link_train.lane_count = reg;
+ dev_dbg(dp->dev, "final lane count = %.2x\n",
+ dp->link_train.lane_count);
- /* set enhanced mode if available */
- exynos_dp_set_enhanced_mode(dp);
- dp->link_train.lt_state = FINISHED;
- } else {
- /* not all locked */
- dp->link_train.eq_loop++;
+ /* set enhanced mode if available */
+ exynos_dp_set_enhanced_mode(dp);
+ dp->link_train.lt_state = FINISHED;
- if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
- dev_err(dp->dev, "EQ Max loop\n");
- goto reduce_link_rate;
- }
+ return 0;
+ }
- for (lane = 0; lane < lane_count; lane++)
- exynos_dp_set_lane_link_training(dp,
- dp->link_train.training_lane[lane],
- lane);
+ /* not all locked */
+ dp->link_train.eq_loop++;
- exynos_dp_write_bytes_to_dpcd(dp,
- DPCD_ADDR_TRAINING_LANE0_SET,
- lane_count,
- dp->link_train.training_lane);
- }
- } else {
- goto reduce_link_rate;
+ if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+ dev_err(dp->dev, "EQ Max loop\n");
+ exynos_dp_reduce_link_rate(dp);
+ return -EIO;
}
- return 0;
+ for (lane = 0; lane < lane_count; lane++)
+ exynos_dp_set_lane_link_training(dp,
+ dp->link_train.training_lane[lane], lane);
+
+ retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_LANE0_SET,
+ lane_count, dp->link_train.training_lane);
-reduce_link_rate:
- exynos_dp_reduce_link_rate(dp);
- return -EIO;
+ return retval;
}
static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
@@ -701,16 +676,17 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
{
- int retval = 0;
- int training_finished = 0;
+ int retval = 0, training_finished = 0;
dp->link_train.lt_state = START;
/* Process here */
- while (!training_finished) {
+ while (!retval && !training_finished) {
switch (dp->link_train.lt_state) {
case START:
- exynos_dp_link_start(dp);
+ retval = exynos_dp_link_start(dp);
+ if (retval)
+ dev_err(dp->dev, "LT link start failed!\n");
break;
case CLOCK_RECOVERY:
retval = exynos_dp_process_clock_recovery(dp);
@@ -729,6 +705,8 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
return -EREMOTEIO;
}
}
+ if (retval)
+ dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
return retval;
}
@@ -752,19 +730,15 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
return retval;
}
-static int exynos_dp_config_video(struct exynos_dp_device *dp,
- struct video_info *video_info)
+static int exynos_dp_config_video(struct exynos_dp_device *dp)
{
int retval = 0;
int timeout_loop = 0;
int done_count = 0;
- exynos_dp_config_video_slave_mode(dp, video_info);
+ exynos_dp_config_video_slave_mode(dp);
- exynos_dp_set_video_color_format(dp, video_info->color_depth,
- video_info->color_space,
- video_info->dynamic_range,
- video_info->ycbcr_coeff);
+ exynos_dp_set_video_color_format(dp);
if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
dev_err(dp->dev, "PLL is not locked yet.\n");
@@ -852,10 +826,213 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
{
struct exynos_dp_device *dp = arg;
- dev_err(dp->dev, "exynos_dp_irq_handler\n");
+ enum dp_irq_type irq_type;
+
+ irq_type = exynos_dp_get_irq_type(dp);
+ switch (irq_type) {
+ case DP_IRQ_TYPE_HP_CABLE_IN:
+ dev_dbg(dp->dev, "Received irq - cable in\n");
+ schedule_work(&dp->hotplug_work);
+ exynos_dp_clear_hotplug_interrupts(dp);
+ break;
+ case DP_IRQ_TYPE_HP_CABLE_OUT:
+ dev_dbg(dp->dev, "Received irq - cable out\n");
+ exynos_dp_clear_hotplug_interrupts(dp);
+ break;
+ case DP_IRQ_TYPE_HP_CHANGE:
+ /*
+ * We get these change notifications once in a while, but there
+ * is nothing we can do with them. Just ignore it for now and
+ * only handle cable changes.
+ */
+ dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
+ exynos_dp_clear_hotplug_interrupts(dp);
+ break;
+ default:
+ dev_err(dp->dev, "Received irq - unknown type!\n");
+ break;
+ }
return IRQ_HANDLED;
}
+static void exynos_dp_hotplug(struct work_struct *work)
+{
+ struct exynos_dp_device *dp;
+ int ret;
+
+ dp = container_of(work, struct exynos_dp_device, hotplug_work);
+
+ ret = exynos_dp_detect_hpd(dp);
+ if (ret) {
+ /* Cable has been disconnected, we're done */
+ return;
+ }
+
+ ret = exynos_dp_handle_edid(dp);
+ if (ret) {
+ dev_err(dp->dev, "unable to handle edid\n");
+ return;
+ }
+
+ ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
+ dp->video_info->link_rate);
+ if (ret) {
+ dev_err(dp->dev, "unable to do link train\n");
+ return;
+ }
+
+ exynos_dp_enable_scramble(dp, 1);
+ exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
+ exynos_dp_enable_enhanced_mode(dp, 1);
+
+ exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
+ exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+
+ exynos_dp_init_video(dp);
+ ret = exynos_dp_config_video(dp);
+ if (ret)
+ dev_err(dp->dev, "unable to config video\n");
+}
+
+#ifdef CONFIG_OF
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+ struct device_node *dp_node = dev->of_node;
+ struct exynos_dp_platdata *pd;
+ struct video_info *dp_video_config;
+
+ pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd) {
+ dev_err(dev, "memory allocation for pdata failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ dp_video_config = devm_kzalloc(dev,
+ sizeof(*dp_video_config), GFP_KERNEL);
+
+ if (!dp_video_config) {
+ dev_err(dev, "memory allocation for video config failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ pd->video_info = dp_video_config;
+
+ dp_video_config->h_sync_polarity =
+ of_property_read_bool(dp_node, "hsync-active-high");
+
+ dp_video_config->v_sync_polarity =
+ of_property_read_bool(dp_node, "vsync-active-high");
+
+ dp_video_config->interlaced =
+ of_property_read_bool(dp_node, "interlaced");
+
+ if (of_property_read_u32(dp_node, "samsung,color-space",
+ &dp_video_config->color_space)) {
+ dev_err(dev, "failed to get color-space\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,dynamic-range",
+ &dp_video_config->dynamic_range)) {
+ dev_err(dev, "failed to get dynamic-range\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+ &dp_video_config->ycbcr_coeff)) {
+ dev_err(dev, "failed to get ycbcr-coeff\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,color-depth",
+ &dp_video_config->color_depth)) {
+ dev_err(dev, "failed to get color-depth\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,link-rate",
+ &dp_video_config->link_rate)) {
+ dev_err(dev, "failed to get link-rate\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (of_property_read_u32(dp_node, "samsung,lane-count",
+ &dp_video_config->lane_count)) {
+ dev_err(dev, "failed to get lane-count\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return pd;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ struct device_node *dp_phy_node;
+ u32 phy_base;
+
+ dp_phy_node = of_find_node_by_name(dp->dev->of_node, "dptx-phy");
+ if (!dp_phy_node) {
+ dev_err(dp->dev, "could not find dptx-phy node\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
+ dev_err(dp->dev, "faild to get reg for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_u32(dp_phy_node, "samsung,enable-mask",
+ &dp->enable_mask)) {
+ dev_err(dp->dev, "faild to get enable-mask for dptx-phy\n");
+ return -EINVAL;
+ }
+
+ dp->phy_addr = ioremap(phy_base, SZ_4);
+ if (!dp->phy_addr) {
+ dev_err(dp->dev, "failed to ioremap dp-phy\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg |= dp->enable_mask;
+ __raw_writel(reg, dp->phy_addr);
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ reg = __raw_readl(dp->phy_addr);
+ reg &= ~(dp->enable_mask);
+ __raw_writel(reg, dp->phy_addr);
+}
+#else
+static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+{
+ return NULL;
+}
+
+static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
+{
+ return -EINVAL;
+}
+
+static void exynos_dp_phy_init(struct exynos_dp_device *dp)
+{
+ return;
+}
+
+static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
+{
+ return;
+}
+#endif /* CONFIG_OF */
+
static int __devinit exynos_dp_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -864,12 +1041,6 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
int ret = 0;
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data\n");
- return -EINVAL;
- }
-
dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
GFP_KERNEL);
if (!dp) {
@@ -879,6 +1050,22 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
dp->dev = &pdev->dev;
+ if (pdev->dev.of_node) {
+ pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+
+ ret = exynos_dp_dt_parse_phydata(dp);
+ if (ret)
+ return ret;
+ } else {
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -EINVAL;
+ }
+ }
+
dp->clock = devm_clk_get(&pdev->dev, "dp");
if (IS_ERR(dp->clock)) {
dev_err(&pdev->dev, "failed to get clock\n");
@@ -896,50 +1083,29 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
}
dp->irq = platform_get_irq(pdev, 0);
- if (!dp->irq) {
+ if (dp->irq == -ENXIO) {
dev_err(&pdev->dev, "failed to get irq\n");
return -ENODEV;
}
- ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
- "exynos-dp", dp);
- if (ret) {
- dev_err(&pdev->dev, "failed to request irq\n");
- return ret;
- }
+ INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
dp->video_info = pdata->video_info;
- if (pdata->phy_init)
- pdata->phy_init();
-
- exynos_dp_init_dp(dp);
-
- ret = exynos_dp_detect_hpd(dp);
- if (ret) {
- dev_err(&pdev->dev, "unable to detect hpd\n");
- return ret;
- }
- exynos_dp_handle_edid(dp);
-
- ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
- dp->video_info->link_rate);
- if (ret) {
- dev_err(&pdev->dev, "unable to do link train\n");
- return ret;
+ if (pdev->dev.of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
}
- exynos_dp_enable_scramble(dp, 1);
- exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
- exynos_dp_enable_enhanced_mode(dp, 1);
-
- exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
- exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
+ exynos_dp_init_dp(dp);
- exynos_dp_init_video(dp);
- ret = exynos_dp_config_video(dp, dp->video_info);
+ ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
+ "exynos-dp", dp);
if (ret) {
- dev_err(&pdev->dev, "unable to config video\n");
+ dev_err(&pdev->dev, "failed to request irq\n");
return ret;
}
@@ -953,23 +1119,41 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ disable_irq(dp->irq);
+
+ if (work_pending(&dp->hotplug_work))
+ flush_work(&dp->hotplug_work);
+
+ if (pdev->dev.of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
+
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int exynos_dp_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
- struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+ struct exynos_dp_platdata *pdata = dev->platform_data;
+ struct exynos_dp_device *dp = dev_get_drvdata(dev);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit();
+ if (work_pending(&dp->hotplug_work))
+ flush_work(&dp->hotplug_work);
+
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_exit(dp);
+ } else {
+ if (pdata->phy_exit)
+ pdata->phy_exit();
+ }
clk_disable_unprepare(dp->clock);
@@ -978,32 +1162,22 @@ static int exynos_dp_suspend(struct device *dev)
static int exynos_dp_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
- struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+ struct exynos_dp_platdata *pdata = dev->platform_data;
+ struct exynos_dp_device *dp = dev_get_drvdata(dev);
- if (pdata && pdata->phy_init)
- pdata->phy_init();
+ if (dev->of_node) {
+ if (dp->phy_addr)
+ exynos_dp_phy_init(dp);
+ } else {
+ if (pdata->phy_init)
+ pdata->phy_init();
+ }
clk_prepare_enable(dp->clock);
exynos_dp_init_dp(dp);
- exynos_dp_detect_hpd(dp);
- exynos_dp_handle_edid(dp);
-
- exynos_dp_set_link_train(dp, dp->video_info->lane_count,
- dp->video_info->link_rate);
-
- exynos_dp_enable_scramble(dp, 1);
- exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
- exynos_dp_enable_enhanced_mode(dp, 1);
-
- exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
- exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
- exynos_dp_init_video(dp);
- exynos_dp_config_video(dp, dp->video_info);
+ enable_irq(dp->irq);
return 0;
}
@@ -1013,6 +1187,12 @@ static const struct dev_pm_ops exynos_dp_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
};
+static const struct of_device_id exynos_dp_match[] = {
+ { .compatible = "samsung,exynos5-dp" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
static struct platform_driver exynos_dp_driver = {
.probe = exynos_dp_probe,
.remove = __devexit_p(exynos_dp_remove),
@@ -1020,6 +1200,7 @@ static struct platform_driver exynos_dp_driver = {
.name = "exynos-dp",
.owner = THIS_MODULE,
.pm = &exynos_dp_pm_ops,
+ .of_match_table = of_match_ptr(exynos_dp_match),
},
};
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 57b8a6531c0..6c567bbf2fb 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -13,6 +13,13 @@
#ifndef _EXYNOS_DP_CORE_H
#define _EXYNOS_DP_CORE_H
+enum dp_irq_type {
+ DP_IRQ_TYPE_HP_CABLE_IN,
+ DP_IRQ_TYPE_HP_CABLE_OUT,
+ DP_IRQ_TYPE_HP_CHANGE,
+ DP_IRQ_TYPE_UNKNOWN,
+};
+
struct link_train {
int eq_loop;
int cr_loop[4];
@@ -29,9 +36,12 @@ struct exynos_dp_device {
struct clk *clock;
unsigned int irq;
void __iomem *reg_base;
+ void __iomem *phy_addr;
+ unsigned int enable_mask;
struct video_info *video_info;
struct link_train link_train;
+ struct work_struct hotplug_work;
};
/* exynos_dp_reg.c */
@@ -50,6 +60,8 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
bool enable);
void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
void exynos_dp_init_hpd(struct exynos_dp_device *dp);
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
void exynos_dp_reset_aux(struct exynos_dp_device *dp);
void exynos_dp_init_aux(struct exynos_dp_device *dp);
int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
@@ -107,11 +119,7 @@ u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
void exynos_dp_reset_macro(struct exynos_dp_device *dp);
void exynos_dp_init_video(struct exynos_dp_device *dp);
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
- u32 color_depth,
- u32 color_space,
- u32 dynamic_range,
- u32 ycbcr_coeff);
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
enum clock_recovery_m_value_type type,
@@ -121,8 +129,7 @@ void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
void exynos_dp_start_video(struct exynos_dp_device *dp);
int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
- struct video_info *video_info);
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
index 3f5ca8a0d5e..29d9d035c73 100644
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -19,11 +19,11 @@
#include "exynos_dp_core.h"
#include "exynos_dp_reg.h"
-#define COMMON_INT_MASK_1 (0)
-#define COMMON_INT_MASK_2 (0)
-#define COMMON_INT_MASK_3 (0)
-#define COMMON_INT_MASK_4 (0)
-#define INT_STA_MASK (0)
+#define COMMON_INT_MASK_1 0
+#define COMMON_INT_MASK_2 0
+#define COMMON_INT_MASK_3 0
+#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK INT_HPD
void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
{
@@ -88,7 +88,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
{
/* Set interrupt pin assertion polarity as high */
- writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
+ writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
/* Clear pending regisers */
writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
@@ -324,7 +324,7 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
}
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
{
u32 reg;
@@ -333,12 +333,38 @@ void exynos_dp_init_hpd(struct exynos_dp_device *dp)
reg = INT_HPD;
writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
+}
+
+void exynos_dp_init_hpd(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ exynos_dp_clear_hotplug_interrupts(dp);
reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
reg &= ~(F_HPD | HPD_CTRL);
writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
}
+enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
+{
+ u32 reg;
+
+ /* Parse hotplug interrupt status register */
+ reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
+
+ if (reg & PLUG)
+ return DP_IRQ_TYPE_HP_CABLE_IN;
+
+ if (reg & HPD_LOST)
+ return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+ if (reg & HOTPLUG_CHG)
+ return DP_IRQ_TYPE_HP_CHANGE;
+
+ return DP_IRQ_TYPE_UNKNOWN;
+}
+
void exynos_dp_reset_aux(struct exynos_dp_device *dp)
{
u32 reg;
@@ -491,7 +517,7 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
int i;
int retval;
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 3; i++) {
/* Clear AUX CH data buffer */
reg = BUF_CLR;
writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
@@ -552,7 +578,7 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
else
cur_data_count = count - start_offset;
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 3; i++) {
/* Select DPCD device address */
reg = AUX_ADDR_7_0(reg_addr + start_offset);
writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
@@ -617,7 +643,7 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
cur_data_count = count - start_offset;
/* AUX CH Request Transaction process */
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 3; i++) {
/* Select DPCD device address */
reg = AUX_ADDR_7_0(reg_addr + start_offset);
writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
@@ -700,17 +726,15 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
int i;
int retval;
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 3; i++) {
/* Clear AUX CH data buffer */
reg = BUF_CLR;
writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
/* Select EDID device */
retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
- if (retval != 0) {
- dev_err(dp->dev, "Select EDID device fail!\n");
+ if (retval != 0)
continue;
- }
/*
* Set I2C transaction and read data
@@ -750,7 +774,7 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
int retval = 0;
for (i = 0; i < count; i += 16) {
- for (j = 0; j < 100; j++) {
+ for (j = 0; j < 3; j++) {
/* Clear AUX CH data buffer */
reg = BUF_CLR;
writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
@@ -1034,24 +1058,20 @@ void exynos_dp_init_video(struct exynos_dp_device *dp)
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
}
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
- u32 color_depth,
- u32 color_space,
- u32 dynamic_range,
- u32 ycbcr_coeff)
+void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
{
u32 reg;
/* Configure the input color depth, color space, dynamic range */
- reg = (dynamic_range << IN_D_RANGE_SHIFT) |
- (color_depth << IN_BPC_SHIFT) |
- (color_space << IN_COLOR_F_SHIFT);
+ reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
+ (dp->video_info->color_depth << IN_BPC_SHIFT) |
+ (dp->video_info->color_space << IN_COLOR_F_SHIFT);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
reg &= ~IN_YC_COEFFI_MASK;
- if (ycbcr_coeff)
+ if (dp->video_info->ycbcr_coeff)
reg |= IN_YC_COEFFI_ITU709;
else
reg |= IN_YC_COEFFI_ITU601;
@@ -1178,8 +1198,7 @@ int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
return 0;
}
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
- struct video_info *video_info)
+void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
{
u32 reg;
@@ -1190,17 +1209,17 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg &= ~INTERACE_SCAN_CFG;
- reg |= (video_info->interlaced << 2);
+ reg |= (dp->video_info->interlaced << 2);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg &= ~VSYNC_POLARITY_CFG;
- reg |= (video_info->v_sync_polarity << 1);
+ reg |= (dp->video_info->v_sync_polarity << 1);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg &= ~HSYNC_POLARITY_CFG;
- reg |= (video_info->h_sync_polarity << 0);
+ reg |= (dp->video_info->h_sync_polarity << 0);
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
index 1f2f014cfe8..2e9bd0e0b9f 100644
--- a/drivers/video/exynos/exynos_dp_reg.h
+++ b/drivers/video/exynos/exynos_dp_reg.h
@@ -242,7 +242,8 @@
/* EXYNOS_DP_INT_CTL */
#define SOFT_INT_CTRL (0x1 << 2)
-#define INT_POL (0x1 << 0)
+#define INT_POL1 (0x1 << 1)
+#define INT_POL0 (0x1 << 0)
/* EXYNOS_DP_SYS_CTL_1 */
#define DET_STA (0x1 << 2)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index ede9e55413f..d3fc92eaee8 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -337,13 +337,11 @@ struct mfb_info {
int registered;
unsigned long pseudo_palette[16];
struct diu_ad *ad;
- int cursor_reset;
unsigned char g_alpha;
unsigned int count;
int x_aoi_d; /* aoi display x offset to physical screen */
int y_aoi_d; /* aoi display y offset to physical screen */
struct fsl_diu_data *parent;
- u8 *edid_data;
};
/**
@@ -378,6 +376,8 @@ struct fsl_diu_data {
struct diu_ad ad[NUM_AOIS] __aligned(8);
u8 gamma[256 * 3] __aligned(32);
u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+ uint8_t edid_data[EDID_LENGTH];
+ bool has_edid;
} __aligned(32);
/* Determine the DMA address of a member of the fsl_diu_data structure */
@@ -430,6 +430,22 @@ static struct mfb_info mfb_template[] = {
},
};
+#ifdef DEBUG
+static void __attribute__ ((unused)) fsl_diu_dump(struct diu __iomem *hw)
+{
+ mb();
+ pr_debug("DIU: desc=%08x,%08x,%08x, gamma=%08x pallete=%08x "
+ "cursor=%08x curs_pos=%08x diu_mode=%08x bgnd=%08x "
+ "disp_size=%08x hsyn_para=%08x vsyn_para=%08x syn_pol=%08x "
+ "thresholds=%08x int_mask=%08x plut=%08x\n",
+ hw->desc[0], hw->desc[1], hw->desc[2], hw->gamma,
+ hw->pallete, hw->cursor, hw->curs_pos, hw->diu_mode,
+ hw->bgnd, hw->disp_size, hw->hsyn_para, hw->vsyn_para,
+ hw->syn_pol, hw->thresholds, hw->int_mask, hw->plut);
+ rmb();
+}
+#endif
+
/**
* fsl_diu_name_to_port - convert a port name to a monitor port enum
*
@@ -481,8 +497,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
switch (mfbi->index) {
case PLANE0:
- if (hw->desc[0] != ad->paddr)
- wr_reg_wa(&hw->desc[0], ad->paddr);
+ wr_reg_wa(&hw->desc[0], ad->paddr);
break;
case PLANE1_AOI0:
cmfbi = &data->mfb[2];
@@ -534,8 +549,7 @@ static void fsl_diu_disable_panel(struct fb_info *info)
switch (mfbi->index) {
case PLANE0:
- if (hw->desc[0] != data->dummy_ad.paddr)
- wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
+ wr_reg_wa(&hw->desc[0], 0);
break;
case PLANE1_AOI0:
cmfbi = &data->mfb[2];
@@ -792,7 +806,8 @@ static void update_lcdc(struct fb_info *info)
hw = data->diu_reg;
- diu_ops.set_monitor_port(data->monitor_port);
+ if (diu_ops.set_monitor_port)
+ diu_ops.set_monitor_port(data->monitor_port);
gamma_table_base = data->gamma;
/* Prep for DIU init - gamma table, cursor table */
@@ -811,12 +826,8 @@ static void update_lcdc(struct fb_info *info)
out_be32(&hw->gamma, DMA_ADDR(data, gamma));
out_be32(&hw->cursor, DMA_ADDR(data, cursor));
- out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
- out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
- out_be32(&hw->disp_size, (var->yres << 16 | var->xres));
- /* DISP SIZE */
- out_be32(&hw->wb_size, 0); /* WB SIZE */
- out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */
+ out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
+ out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
/* Horizontal and vertical configuration register */
temp = var->left_margin << 22 | /* BP_H */
@@ -833,9 +844,20 @@ static void update_lcdc(struct fb_info *info)
diu_ops.set_pixel_clock(var->pixclock);
- out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */
- out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */
+#ifndef CONFIG_PPC_MPC512x
+ /*
+ * The PLUT register is defined differently on the MPC5121 than it
+ * is on other SOCs. Unfortunately, there's no documentation that
+ * explains how it's supposed to be programmed, so for now, we leave
+ * it at the default value on the MPC5121.
+ *
+ * For other SOCs, program it for the highest priority, which will
+ * reduce the chance of underrun. Technically, we should scale the
+ * priority to match the screen resolution, but doing that properly
+ * requires delicate fine-tuning for each use-case.
+ */
out_be32(&hw->plut, 0x01F5F666);
+#endif
/* Enable the DIU */
enable_lcdc(info);
@@ -965,7 +987,6 @@ static int fsl_diu_set_par(struct fb_info *info)
hw = data->diu_reg;
set_fix(info);
- mfbi->cursor_reset = 1;
len = info->var.yres_virtual * info->fix.line_length;
/* Alloc & dealloc each time resolution/bpp change */
@@ -1107,6 +1128,12 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
if (!arg)
return -EINVAL;
+
+ dev_dbg(info->dev, "ioctl %08x (dir=%s%s type=%u nr=%u size=%u)\n", cmd,
+ _IOC_DIR(cmd) & _IOC_READ ? "R" : "",
+ _IOC_DIR(cmd) & _IOC_WRITE ? "W" : "",
+ _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
+
switch (cmd) {
case MFB_SET_PIXFMT_OLD:
dev_warn(info->dev,
@@ -1180,6 +1207,23 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd,
ad->ckmin_b = ck.blue_min;
}
break;
+#ifdef CONFIG_PPC_MPC512x
+ case MFB_SET_GAMMA: {
+ struct fsl_diu_data *data = mfbi->parent;
+
+ if (copy_from_user(data->gamma, buf, sizeof(data->gamma)))
+ return -EFAULT;
+ setbits32(&data->diu_reg->gamma, 0); /* Force table reload */
+ break;
+ }
+ case MFB_GET_GAMMA: {
+ struct fsl_diu_data *data = mfbi->parent;
+
+ if (copy_to_user(buf, data->gamma, sizeof(data->gamma)))
+ return -EFAULT;
+ break;
+ }
+#endif
default:
dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd);
return -ENOIOCTLCMD;
@@ -1206,8 +1250,22 @@ static int fsl_diu_open(struct fb_info *info, int user)
res = fsl_diu_set_par(info);
if (res < 0)
mfbi->count--;
- else
+ else {
+ struct fsl_diu_data *data = mfbi->parent;
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ /*
+ * Enable underrun detection and vertical sync
+ * interrupts.
+ */
+ clrbits32(&data->diu_reg->int_mask,
+ INT_UNDRUN | INT_VSYNC);
+#else
+ /* Enable underrun detection */
+ clrbits32(&data->diu_reg->int_mask, INT_UNDRUN);
+#endif
fsl_diu_enable_panel(info);
+ }
}
spin_unlock(&diu_lock);
@@ -1223,8 +1281,13 @@ static int fsl_diu_release(struct fb_info *info, int user)
spin_lock(&diu_lock);
mfbi->count--;
- if (mfbi->count == 0)
+ if (mfbi->count == 0) {
+ struct fsl_diu_data *data = mfbi->parent;
+
+ /* Disable interrupts */
+ out_be32(&data->diu_reg->int_mask, 0xffffffff);
fsl_diu_disable_panel(info);
+ }
spin_unlock(&diu_lock);
return res;
@@ -1248,6 +1311,7 @@ static int __devinit install_fb(struct fb_info *info)
{
int rc;
struct mfb_info *mfbi = info->par;
+ struct fsl_diu_data *data = mfbi->parent;
const char *aoi_mode, *init_aoi_mode = "320x240";
struct fb_videomode *db = fsl_diu_mode_db;
unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
@@ -1264,9 +1328,9 @@ static int __devinit install_fb(struct fb_info *info)
return rc;
if (mfbi->index == PLANE0) {
- if (mfbi->edid_data) {
+ if (data->has_edid) {
/* Now build modedb from EDID */
- fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
+ fb_edid_to_monspecs(data->edid_data, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len,
&info->modelist);
@@ -1284,7 +1348,7 @@ static int __devinit install_fb(struct fb_info *info)
* For plane 0 we continue and look into
* driver's internal modedb.
*/
- if ((mfbi->index == PLANE0) && mfbi->edid_data)
+ if ((mfbi->index == PLANE0) && data->has_edid)
has_default_mode = 0;
else
return -EINVAL;
@@ -1348,9 +1412,6 @@ static void uninstall_fb(struct fb_info *info)
if (!mfbi->registered)
return;
- if (mfbi->index == PLANE0)
- kfree(mfbi->edid_data);
-
unregister_framebuffer(info);
unmap_video_memory(info);
if (&info->cmap)
@@ -1362,7 +1423,7 @@ static void uninstall_fb(struct fb_info *info)
static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
{
struct diu __iomem *hw = dev_id;
- unsigned int status = in_be32(&hw->int_status);
+ uint32_t status = in_be32(&hw->int_status);
if (status) {
/* This is the workaround for underrun */
@@ -1387,40 +1448,6 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
return IRQ_NONE;
}
-static int request_irq_local(struct fsl_diu_data *data)
-{
- struct diu __iomem *hw = data->diu_reg;
- u32 ints;
- int ret;
-
- /* Read to clear the status */
- in_be32(&hw->int_status);
-
- ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
- if (!ret) {
- ints = INT_PARERR | INT_LS_BF_VS;
-#if !defined(CONFIG_NOT_COHERENT_CACHE)
- ints |= INT_VSYNC;
-#endif
-
- /* Read to clear the status */
- in_be32(&hw->int_status);
- out_be32(&hw->int_mask, ints);
- }
-
- return ret;
-}
-
-static void free_irq_local(struct fsl_diu_data *data)
-{
- struct diu __iomem *hw = data->diu_reg;
-
- /* Disable all LCDC interrupt */
- out_be32(&hw->int_mask, 0x1f);
-
- free_irq(data->irq, NULL);
-}
-
#ifdef CONFIG_PM
/*
* Power management hooks. Note that we won't be called from IRQ context,
@@ -1496,8 +1523,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct mfb_info *mfbi;
struct fsl_diu_data *data;
- int diu_mode;
dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
+ const void *prop;
unsigned int i;
int ret;
@@ -1541,17 +1568,13 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
mfbi->parent = data;
mfbi->ad = &data->ad[i];
+ }
- if (mfbi->index == PLANE0) {
- const u8 *prop;
- int len;
-
- /* Get EDID */
- prop = of_get_property(np, "edid", &len);
- if (prop && len == EDID_LENGTH)
- mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
- GFP_KERNEL);
- }
+ /* Get the EDID data from the device tree, if present */
+ prop = of_get_property(np, "edid", &ret);
+ if (prop && ret == EDID_LENGTH) {
+ memcpy(data->edid_data, prop, EDID_LENGTH);
+ data->has_edid = true;
}
data->diu_reg = of_iomap(np, 0);
@@ -1561,10 +1584,6 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
goto error;
}
- diu_mode = in_be32(&data->diu_reg->diu_mode);
- if (diu_mode == MFB_MODE0)
- out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
-
/* Get the IRQ of the DIU */
data->irq = irq_of_parse_and_map(np, 0);
@@ -1586,11 +1605,11 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
/*
- * Let DIU display splash screen if it was pre-initialized
- * by the bootloader, set dummy area descriptor otherwise.
+ * Let DIU continue to display splash screen if it was pre-initialized
+ * by the bootloader; otherwise, clear the display.
*/
- if (diu_mode == MFB_MODE0)
- out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
+ if (in_be32(&data->diu_reg->diu_mode) == MFB_MODE0)
+ out_be32(&data->diu_reg->desc[0], 0);
out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
@@ -1603,7 +1622,16 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
}
}
- if (request_irq_local(data)) {
+ /*
+ * Older versions of U-Boot leave interrupts enabled, so disable
+ * all of them and clear the status register.
+ */
+ out_be32(&data->diu_reg->int_mask, 0xffffffff);
+ in_be32(&data->diu_reg->int_status);
+
+ ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb",
+ &data->diu_reg);
+ if (ret) {
dev_err(&pdev->dev, "could not claim irq\n");
goto error;
}
@@ -1638,7 +1666,8 @@ static int fsl_diu_remove(struct platform_device *pdev)
data = dev_get_drvdata(&pdev->dev);
disable_lcdc(&data->fsl_diu_info[0]);
- free_irq_local(data);
+
+ free_irq(data->irq, &data->diu_reg);
for (i = 0; i < NUM_AOIS; i++)
uninstall_fb(&data->fsl_diu_info[i]);
@@ -1741,6 +1770,9 @@ static int __init fsl_diu_init(void)
coherence_data_size = be32_to_cpup(prop) * 13;
coherence_data_size /= 8;
+ pr_debug("fsl-diu-fb: coherence data size is %zu bytes\n",
+ coherence_data_size);
+
prop = of_get_property(np, "d-cache-line-size", NULL);
if (prop == NULL) {
pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' "
@@ -1750,10 +1782,17 @@ static int __init fsl_diu_init(void)
}
d_cache_line_size = be32_to_cpup(prop);
+ pr_debug("fsl-diu-fb: cache lines size is %u bytes\n",
+ d_cache_line_size);
+
of_node_put(np);
coherence_data = vmalloc(coherence_data_size);
- if (!coherence_data)
+ if (!coherence_data) {
+ pr_err("fsl-diu-fb: could not allocate coherence data "
+ "(size=%zu)\n", coherence_data_size);
return -ENOMEM;
+ }
+
#endif
ret = platform_driver_register(&fsl_diu_driver);
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cf2688de083..e501dbc966b 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -33,7 +33,6 @@
#include <linux/math64.h>
#include <linux/platform_data/video-imxfb.h>
-#include <mach/hardware.h>
/*
* Complain if VAR is out of range.
@@ -53,8 +52,8 @@
#define LCDC_SIZE 0x04
#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20)
-#define YMAX_MASK (cpu_is_mx1() ? 0x1ff : 0x3ff)
-#define SIZE_YMAX(y) ((y) & YMAX_MASK)
+#define YMAX_MASK_IMX1 0x1ff
+#define YMAX_MASK_IMX21 0x3ff
#define LCDC_VPW 0x08
#define VPW_VPW(x) ((x) & 0x3ff)
@@ -128,12 +127,18 @@ struct imxfb_rgb {
struct fb_bitfield transp;
};
+enum imxfb_type {
+ IMX1_FB,
+ IMX21_FB,
+};
+
struct imxfb_info {
struct platform_device *pdev;
void __iomem *regs;
struct clk *clk_ipg;
struct clk *clk_ahb;
struct clk *clk_per;
+ enum imxfb_type devtype;
/*
* These are the addresses we mapped
@@ -168,6 +173,24 @@ struct imxfb_info {
void (*backlight_power)(int);
};
+static struct platform_device_id imxfb_devtype[] = {
+ {
+ .name = "imx1-fb",
+ .driver_data = IMX1_FB,
+ }, {
+ .name = "imx21-fb",
+ .driver_data = IMX21_FB,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imxfb_devtype);
+
+static inline int is_imx1_fb(struct imxfb_info *fbi)
+{
+ return fbi->devtype == IMX1_FB;
+}
+
#define IMX_NAME "IMX"
/*
@@ -366,7 +389,7 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
break;
case 16:
default:
- if (cpu_is_mx1())
+ if (is_imx1_fb(fbi))
pcr |= PCR_BPIX_12;
else
pcr |= PCR_BPIX_16;
@@ -596,6 +619,7 @@ static struct fb_ops imxfb_ops = {
static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct imxfb_info *fbi = info->par;
+ u32 ymax_mask = is_imx1_fb(fbi) ? YMAX_MASK_IMX1 : YMAX_MASK_IMX21;
pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
var->xres, var->hsync_len,
@@ -617,7 +641,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
if (var->right_margin > 255)
printk(KERN_ERR "%s: invalid right_margin %d\n",
info->fix.id, var->right_margin);
- if (var->yres < 1 || var->yres > YMAX_MASK)
+ if (var->yres < 1 || var->yres > ymax_mask)
printk(KERN_ERR "%s: invalid yres %d\n",
info->fix.id, var->yres);
if (var->vsync_len > 100)
@@ -645,7 +669,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
VCR_V_WAIT_2(var->upper_margin),
fbi->regs + LCDC_VCR);
- writel(SIZE_XMAX(var->xres) | SIZE_YMAX(var->yres),
+ writel(SIZE_XMAX(var->xres) | (var->yres & ymax_mask),
fbi->regs + LCDC_SIZE);
writel(fbi->pcr, fbi->regs + LCDC_PCR);
@@ -765,6 +789,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
return -ENOMEM;
fbi = info->par;
+ fbi->devtype = pdev->id_entry->driver_data;
if (!fb_mode)
fb_mode = pdata->mode[0].mode.name;
@@ -939,6 +964,7 @@ static struct platform_driver imxfb_driver = {
.driver = {
.name = DRIVER_NAME,
},
+ .id_table = imxfb_devtype,
};
static int imxfb_setup(void)
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index ce1d452464e..73688720857 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -26,10 +26,9 @@
#include <linux/console.h>
#include <linux/clk.h>
#include <linux/mutex.h>
+#include <linux/dma/ipu-dma.h>
#include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
-#include <mach/ipu.h>
#include <linux/platform_data/video-mx3fb.h>
#include <asm/io.h>
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index b38b1dd15ce..2ee423279e3 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -23,7 +23,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <plat/fpga.h>
+#include <mach/hardware.h>
+
#include "omapfb.h"
static int innovator1510_panel_init(struct lcd_panel *panel,
@@ -38,13 +39,13 @@ static void innovator1510_panel_cleanup(struct lcd_panel *panel)
static int innovator1510_panel_enable(struct lcd_panel *panel)
{
- fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ __raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
return 0;
}
static void innovator1510_panel_disable(struct lcd_panel *panel)
{
- fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ __raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
}
static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 7767338f8b1..b52f62595f6 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -31,7 +31,7 @@
#include <linux/gfp.h>
#include <mach/lcdc.h>
-#include <plat/dma.h>
+#include <linux/omap-dma.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 4351c438b76..e31f5b33b50 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -30,7 +30,7 @@
#include <linux/uaccess.h>
#include <linux/module.h>
-#include <plat/dma.h>
+#include <linux/omap-dma.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index f79c137753d..d4e7684e704 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -25,7 +25,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <plat/dma.h>
+#include <linux/omap-dma.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index d877c361abd..b07b2b042e7 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -1,9 +1,10 @@
-config OMAP2_VRAM
- bool
-
config OMAP2_VRFB
bool
+if ARCH_OMAP2PLUS
+
source "drivers/video/omap2/dss/Kconfig"
source "drivers/video/omap2/omapfb/Kconfig"
source "drivers/video/omap2/displays/Kconfig"
+
+endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 5ddef129f79..5ea7cb9aed1 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,4 +1,3 @@
-obj-$(CONFIG_OMAP2_VRAM) += vram.o
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
obj-$(CONFIG_OMAP2_DSS) += dss/
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index c835aa70f96..65eb76c840a 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -710,27 +710,6 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static int acx_panel_suspend(struct omap_dss_device *dssdev)
-{
- dev_dbg(&dssdev->dev, "%s\n", __func__);
- acx_panel_power_off(dssdev);
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
- return 0;
-}
-
-static int acx_panel_resume(struct omap_dss_device *dssdev)
-{
- int r;
-
- dev_dbg(&dssdev->dev, "%s\n", __func__);
- r = acx_panel_power_on(dssdev);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
- return 0;
-}
-
static void acx_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -752,8 +731,6 @@ static struct omap_dss_driver acx_panel_driver = {
.enable = acx_panel_enable,
.disable = acx_panel_disable,
- .suspend = acx_panel_suspend,
- .resume = acx_panel_resume,
.set_timings = acx_panel_set_timings,
.check_timings = acx_panel_check_timings,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 88295c52681..54ca8ae2107 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -688,40 +688,6 @@ static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&drv_data->lock);
}
-static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
-
- mutex_lock(&drv_data->lock);
-
- generic_dpi_panel_power_off(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- mutex_unlock(&drv_data->lock);
-
- return 0;
-}
-
-static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
- int r;
-
- mutex_lock(&drv_data->lock);
-
- r = generic_dpi_panel_power_on(dssdev);
- if (r)
- goto err;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
- mutex_unlock(&drv_data->lock);
-
- return r;
-}
-
static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -769,8 +735,6 @@ static struct omap_dss_driver dpi_driver = {
.enable = generic_dpi_panel_enable,
.disable = generic_dpi_panel_disable,
- .suspend = generic_dpi_panel_suspend,
- .resume = generic_dpi_panel_resume,
.set_timings = generic_dpi_panel_set_timings,
.get_timings = generic_dpi_panel_get_timings,
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 90c1cabf244..ace419b801e 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -143,46 +143,12 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&ld->lock);
}
-static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
-{
- struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
-
- mutex_lock(&ld->lock);
-
- lb035q02_panel_power_off(dssdev);
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- mutex_unlock(&ld->lock);
- return 0;
-}
-
-static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
-{
- struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
- int r;
-
- mutex_lock(&ld->lock);
-
- r = lb035q02_panel_power_on(dssdev);
- if (r)
- goto err;
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- mutex_unlock(&ld->lock);
- return 0;
-err:
- mutex_unlock(&ld->lock);
- return r;
-}
-
static struct omap_dss_driver lb035q02_driver = {
.probe = lb035q02_panel_probe,
.remove = lb035q02_panel_remove,
.enable = lb035q02_panel_enable,
.disable = lb035q02_panel_disable,
- .suspend = lb035q02_panel_suspend,
- .resume = lb035q02_panel_resume,
.driver = {
.name = "lgphilips_lb035q02_panel",
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 3fc5ad081a2..d1cb722fcdb 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -574,54 +574,6 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&ddata->lock);
}
-static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = get_drv_data(dssdev);
-
- dev_dbg(&dssdev->dev, "suspend\n");
-
- mutex_lock(&ddata->lock);
-
- rfbi_bus_lock();
-
- n8x0_panel_power_off(dssdev);
-
- rfbi_bus_unlock();
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- mutex_unlock(&ddata->lock);
-
- return 0;
-}
-
-static int n8x0_panel_resume(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = get_drv_data(dssdev);
- int r;
-
- dev_dbg(&dssdev->dev, "resume\n");
-
- mutex_lock(&ddata->lock);
-
- rfbi_bus_lock();
-
- r = n8x0_panel_power_on(dssdev);
-
- rfbi_bus_unlock();
-
- if (r) {
- mutex_unlock(&ddata->lock);
- return r;
- }
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- mutex_unlock(&ddata->lock);
-
- return 0;
-}
-
static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
@@ -683,8 +635,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
.enable = n8x0_panel_enable,
.disable = n8x0_panel_disable,
- .suspend = n8x0_panel_suspend,
- .resume = n8x0_panel_resume,
.update = n8x0_panel_update,
.sync = n8x0_panel_sync,
@@ -702,18 +652,25 @@ static struct omap_dss_driver n8x0_panel_driver = {
static int mipid_spi_probe(struct spi_device *spi)
{
+ int r;
+
dev_dbg(&spi->dev, "mipid_spi_probe\n");
spi->mode = SPI_MODE_0;
s_drv_data.spidev = spi;
- return 0;
+ r = omap_dss_register_driver(&n8x0_panel_driver);
+ if (r)
+ pr_err("n8x0_panel: dss driver registration failed\n");
+
+ return r;
}
static int mipid_spi_remove(struct spi_device *spi)
{
dev_dbg(&spi->dev, "mipid_spi_remove\n");
+ omap_dss_unregister_driver(&n8x0_panel_driver);
return 0;
}
@@ -725,34 +682,6 @@ static struct spi_driver mipid_spi_driver = {
.probe = mipid_spi_probe,
.remove = __devexit_p(mipid_spi_remove),
};
+module_spi_driver(mipid_spi_driver);
-static int __init n8x0_panel_drv_init(void)
-{
- int r;
-
- r = spi_register_driver(&mipid_spi_driver);
- if (r) {
- pr_err("n8x0_panel: spi driver registration failed\n");
- return r;
- }
-
- r = omap_dss_register_driver(&n8x0_panel_driver);
- if (r) {
- pr_err("n8x0_panel: dss driver registration failed\n");
- spi_unregister_driver(&mipid_spi_driver);
- return r;
- }
-
- return 0;
-}
-
-static void __exit n8x0_panel_drv_exit(void)
-{
- spi_unregister_driver(&mipid_spi_driver);
-
- omap_dss_unregister_driver(&n8x0_panel_driver);
-}
-
-module_init(n8x0_panel_drv_init);
-module_exit(n8x0_panel_drv_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 908fd268f3d..2a79c283beb 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -236,28 +236,6 @@ static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
-{
- nec_8048_panel_power_off(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- return 0;
-}
-
-static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
-{
- int r;
-
- r = nec_8048_panel_power_on(dssdev);
- if (r)
- return r;
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- return 0;
-}
-
static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
{
return 16;
@@ -268,8 +246,6 @@ static struct omap_dss_driver nec_8048_driver = {
.remove = nec_8048_panel_remove,
.enable = nec_8048_panel_enable,
.disable = nec_8048_panel_disable,
- .suspend = nec_8048_panel_suspend,
- .resume = nec_8048_panel_resume,
.get_recommended_bpp = nec_8048_recommended_bpp,
.driver = {
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 9df87640ddd..1b94018aac3 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -50,6 +50,7 @@ struct picodlp_i2c_data {
static struct i2c_device_id picodlp_i2c_id[] = {
{ "picodlp_i2c_driver", 0 },
+ { }
};
struct picodlp_i2c_command {
@@ -503,47 +504,6 @@ static void picodlp_panel_disable(struct omap_dss_device *dssdev)
dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
}
-static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
-{
- struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-
- mutex_lock(&picod->lock);
- /* Turn off DLP Power */
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
- mutex_unlock(&picod->lock);
- dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
- " panel is not ACTIVE\n");
- return -EINVAL;
- }
-
- picodlp_panel_power_off(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
- mutex_unlock(&picod->lock);
-
- dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
- return 0;
-}
-
-static int picodlp_panel_resume(struct omap_dss_device *dssdev)
-{
- struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
- int r;
-
- mutex_lock(&picod->lock);
- if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
- mutex_unlock(&picod->lock);
- dev_err(&dssdev->dev, "unable to resume picodlp panel,"
- " panel is not ACTIVE\n");
- return -EINVAL;
- }
-
- r = picodlp_panel_power_on(dssdev);
- mutex_unlock(&picod->lock);
- dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
- return r;
-}
-
static void picodlp_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
@@ -560,9 +520,6 @@ static struct omap_dss_driver picodlp_driver = {
.get_resolution = picodlp_get_resolution,
- .suspend = picodlp_panel_suspend,
- .resume = picodlp_panel_resume,
-
.driver = {
.name = "picodlp_panel",
.owner = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 1ec3b277ff1..cada8c621e0 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -194,29 +194,12 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
-{
- sharp_ls_power_off(dssdev);
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
- return 0;
-}
-
-static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
-{
- int r;
- r = sharp_ls_power_on(dssdev);
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
- return r;
-}
-
static struct omap_dss_driver sharp_ls_driver = {
.probe = sharp_ls_panel_probe,
.remove = __exit_p(sharp_ls_panel_remove),
.enable = sharp_ls_panel_enable,
.disable = sharp_ls_panel_disable,
- .suspend = sharp_ls_panel_suspend,
- .resume = sharp_ls_panel_resume,
.driver = {
.name = "sharp_ls_panel",
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index f2f644680ca..a32407a5735 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1245,76 +1245,6 @@ static void taal_disable(struct omap_dss_device *dssdev)
mutex_unlock(&td->lock);
}
-static int taal_suspend(struct omap_dss_device *dssdev)
-{
- struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- int r;
-
- dev_dbg(&dssdev->dev, "suspend\n");
-
- mutex_lock(&td->lock);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
- r = -EINVAL;
- goto err;
- }
-
- taal_cancel_ulps_work(dssdev);
- taal_cancel_esd_work(dssdev);
-
- dsi_bus_lock(dssdev);
-
- r = taal_wake_up(dssdev);
- if (!r)
- taal_power_off(dssdev);
-
- dsi_bus_unlock(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- mutex_unlock(&td->lock);
-
- return 0;
-err:
- mutex_unlock(&td->lock);
- return r;
-}
-
-static int taal_resume(struct omap_dss_device *dssdev)
-{
- struct taal_data *td = dev_get_drvdata(&dssdev->dev);
- int r;
-
- dev_dbg(&dssdev->dev, "resume\n");
-
- mutex_lock(&td->lock);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
- r = -EINVAL;
- goto err;
- }
-
- dsi_bus_lock(dssdev);
-
- r = taal_power_on(dssdev);
-
- dsi_bus_unlock(dssdev);
-
- if (r) {
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
- } else {
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
- taal_queue_esd_work(dssdev);
- }
-
- mutex_unlock(&td->lock);
-
- return r;
-err:
- mutex_unlock(&td->lock);
- return r;
-}
-
static void taal_framedone_cb(int err, void *data)
{
struct omap_dss_device *dssdev = data;
@@ -1818,8 +1748,6 @@ static struct omap_dss_driver taal_driver = {
.enable = taal_enable,
.disable = taal_disable,
- .suspend = taal_suspend,
- .resume = taal_resume,
.update = taal_update,
.sync = taal_sync,
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 383811cf864..8281baafe1e 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -189,37 +189,6 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
mutex_unlock(&ddata->lock);
}
-static int tfp410_suspend(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
-
- mutex_lock(&ddata->lock);
-
- tfp410_power_off(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- mutex_unlock(&ddata->lock);
-
- return 0;
-}
-
-static int tfp410_resume(struct omap_dss_device *dssdev)
-{
- struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
- int r;
-
- mutex_lock(&ddata->lock);
-
- r = tfp410_power_on(dssdev);
- if (r == 0)
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- mutex_unlock(&ddata->lock);
-
- return r;
-}
-
static void tfp410_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -355,8 +324,6 @@ static struct omap_dss_driver tfp410_driver = {
.enable = tfp410_enable,
.disable = tfp410_disable,
- .suspend = tfp410_suspend,
- .resume = tfp410_resume,
.set_timings = tfp410_set_timings,
.get_timings = tfp410_get_timings,
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index b5e6dbc59f0..316b3da6d2c 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -401,24 +401,6 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}
-static int tpo_td043_suspend(struct omap_dss_device *dssdev)
-{
- dev_dbg(&dssdev->dev, "suspend\n");
-
- tpo_td043_disable_dss(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
-
- return 0;
-}
-
-static int tpo_td043_resume(struct omap_dss_device *dssdev)
-{
- dev_dbg(&dssdev->dev, "resume\n");
-
- return tpo_td043_enable_dss(dssdev);
-}
-
static int tpo_td043_probe(struct omap_dss_device *dssdev)
{
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
@@ -500,8 +482,6 @@ static struct omap_dss_driver tpo_td043_driver = {
.enable = tpo_td043_enable,
.disable = tpo_td043_disable,
- .suspend = tpo_td043_suspend,
- .resume = tpo_td043_resume,
.set_mirror = tpo_td043_set_hmirror,
.get_mirror = tpo_td043_get_hmirror,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 80f5390aa13..cb0f145c707 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,33 +1,30 @@
menuconfig OMAP2_DSS
tristate "OMAP2+ Display Subsystem support"
- depends on ARCH_OMAP2PLUS
help
OMAP2+ Display Subsystem support.
if OMAP2_DSS
-config OMAP2_VRAM_SIZE
- int "VRAM size (MB)"
- range 0 32
- default 0
+config OMAP2_DSS_DEBUG
+ bool "Debug support"
+ default n
help
- The amount of SDRAM to reserve at boot time for video RAM use.
- This VRAM will be used by omapfb and other drivers that need
- large continuous RAM area for video use.
+ This enables printing of debug messages. Alternatively, debug messages
+ can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
+ appropriate flags in <debugfs>/dynamic_debug/control.
- You can also set this with "vram=<bytes>" kernel argument, or
- in the board file.
-
-config OMAP2_DSS_DEBUG_SUPPORT
- bool "Debug support"
- default y
+config OMAP2_DSS_DEBUGFS
+ bool "Debugfs filesystem support"
+ depends on DEBUG_FS
+ default n
help
- This enables debug messages. You need to enable printing
- with 'debug' module parameter.
+ This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
+ querying about clock configuration and register configuration of dss,
+ dispc, dsi, hdmi and rfbi.
config OMAP2_DSS_COLLECT_IRQ_STATS
bool "Collect DSS IRQ statistics"
- depends on OMAP2_DSS_DEBUG_SUPPORT
+ depends on OMAP2_DSS_DEBUGFS
default n
help
Collect DSS IRQ statistics, printable via debugfs.
@@ -62,7 +59,6 @@ config OMAP2_DSS_VENC
config OMAP4_DSS_HDMI
bool "HDMI support"
- depends on ARCH_OMAP4
default y
help
HDMI Interface. This adds the High Definition Multimedia Interface.
@@ -70,11 +66,9 @@ config OMAP4_DSS_HDMI
config OMAP4_DSS_HDMI_AUDIO
bool
- depends on OMAP4_DSS_HDMI
config OMAP2_DSS_SDI
bool "SDI support"
- depends on ARCH_OMAP3
default n
help
SDI (Serial Display Interface) support.
@@ -84,7 +78,6 @@ config OMAP2_DSS_SDI
config OMAP2_DSS_DSI
bool "DSI support"
- depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
default n
help
MIPI DSI (Display Serial Interface) support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 4549869bfe1..61949ff7940 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,6 +1,10 @@
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
+# Core DSS files
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
- manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
+ output.o
+# DSS compat layer files
+omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
+ dispc-compat.o display-sysfs.o
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
@@ -8,3 +12,4 @@ omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
hdmi_panel.o ti_hdmi_4xxx_ip.o
+ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 19d66f471b4..d446bdfc4c8 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -18,6 +18,7 @@
#define DSS_SUBSYS_NAME "APPLY"
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
@@ -26,6 +27,7 @@
#include "dss.h"
#include "dss_features.h"
+#include "dispc-compat.h"
/*
* We have 4 levels of cache for the dispc settings. First two are in SW and
@@ -70,7 +72,6 @@ struct ovl_priv_data {
bool shadow_extra_info_dirty;
bool enabled;
- enum omap_channel channel;
u32 fifo_low, fifo_high;
/*
@@ -105,6 +106,9 @@ struct mgr_priv_data {
struct omap_video_timings timings;
struct dss_lcd_mgr_config lcd_config;
+
+ void (*framedone_handler)(void *);
+ void *framedone_handler_data;
};
static struct {
@@ -132,7 +136,7 @@ static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
return &dss_data.mgr_priv_data_array[mgr->id];
}
-void dss_apply_init(void)
+static void apply_init_priv(void)
{
const int num_ovls = dss_feat_get_num_ovls();
struct mgr_priv_data *mp;
@@ -414,11 +418,46 @@ static void wait_pending_extra_info_updates(void)
r = wait_for_completion_timeout(&extra_updated_completion, t);
if (r == 0)
DSSWARN("timeout in wait_pending_extra_info_updates\n");
- else if (r < 0)
- DSSERR("wait_pending_extra_info_updates failed: %d\n", r);
}
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
+{
+ return ovl->manager ?
+ (ovl->manager->output ? ovl->manager->output->device : NULL) :
+ NULL;
+}
+
+static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
+{
+ return mgr->output ? mgr->output->device : NULL;
+}
+
+static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
+{
+ unsigned long timeout = msecs_to_jiffies(500);
+ struct omap_dss_device *dssdev = mgr->get_device(mgr);
+ u32 irq;
+ int r;
+
+ r = dispc_runtime_get();
+ if (r)
+ return r;
+
+ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
+ irq = DISPC_IRQ_EVSYNC_ODD;
+ else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
+ irq = DISPC_IRQ_EVSYNC_EVEN;
+ else
+ irq = dispc_mgr_get_vsync_irq(mgr->id);
+
+ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
+
+ dispc_runtime_put();
+
+ return r;
+}
+
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
{
unsigned long timeout = msecs_to_jiffies(500);
struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -488,7 +527,7 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
return r;
}
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
{
unsigned long timeout = msecs_to_jiffies(500);
struct ovl_priv_data *op;
@@ -573,7 +612,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
struct mgr_priv_data *mp;
int r;
- DSSDBGF("%d", ovl->id);
+ DSSDBG("writing ovl %d regs", ovl->id);
if (!op->enabled || !op->info_dirty)
return;
@@ -608,7 +647,7 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
struct ovl_priv_data *op = get_ovl_priv(ovl);
struct mgr_priv_data *mp;
- DSSDBGF("%d", ovl->id);
+ DSSDBG("writing ovl %d regs extra", ovl->id);
if (!op->extra_info_dirty)
return;
@@ -617,7 +656,6 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
* disabled */
dispc_ovl_enable(ovl->id, op->enabled);
- dispc_ovl_set_channel_out(ovl->id, op->channel);
dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
mp = get_mgr_priv(ovl->manager);
@@ -632,7 +670,7 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
struct mgr_priv_data *mp = get_mgr_priv(mgr);
struct omap_overlay *ovl;
- DSSDBGF("%d", mgr->id);
+ DSSDBG("writing mgr %d regs", mgr->id);
if (!mp->enabled)
return;
@@ -658,7 +696,7 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
- DSSDBGF("%d", mgr->id);
+ DSSDBG("writing mgr %d regs extra", mgr->id);
if (!mp->extra_info_dirty)
return;
@@ -666,22 +704,8 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
dispc_mgr_set_timings(mgr->id, &mp->timings);
/* lcd_config parameters */
- if (dss_mgr_is_lcd(mgr->id)) {
- dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
-
- dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
- dispc_mgr_enable_fifohandcheck(mgr->id,
- mp->lcd_config.fifohandcheck);
-
- dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
-
- dispc_mgr_set_tft_data_lines(mgr->id,
- mp->lcd_config.video_port_width);
-
- dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
-
- dispc_mgr_set_lcd_type_tft(mgr->id);
- }
+ if (dss_mgr_is_lcd(mgr->id))
+ dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
mp->extra_info_dirty = false;
if (mp->updating)
@@ -761,7 +785,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
}
}
-void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
@@ -786,9 +810,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
if (!dss_data.irq_enabled && need_isr())
dss_register_vsync_isr();
- dispc_mgr_enable(mgr->id, true);
-
- mgr_clear_shadow_dirty(mgr);
+ dispc_mgr_enable_sync(mgr->id);
spin_unlock_irqrestore(&data_lock, flags);
}
@@ -845,7 +867,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
for (i = 0; i < num_mgrs; i++) {
struct omap_overlay_manager *mgr;
struct mgr_priv_data *mp;
- bool was_updating;
mgr = omap_dss_get_overlay_manager(i);
mp = get_mgr_priv(mgr);
@@ -853,7 +874,6 @@ static void dss_apply_irq_handler(void *data, u32 mask)
if (!mp->enabled)
continue;
- was_updating = mp->updating;
mp->updating = dispc_mgr_is_enabled(i);
if (!mgr_manual_update(mgr)) {
@@ -872,6 +892,21 @@ static void dss_apply_irq_handler(void *data, u32 mask)
if (!extra_updating)
complete_all(&extra_updated_completion);
+ /* call framedone handlers for manual update displays */
+ for (i = 0; i < num_mgrs; i++) {
+ struct omap_overlay_manager *mgr;
+ struct mgr_priv_data *mp;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ mp = get_mgr_priv(mgr);
+
+ if (!mgr_manual_update(mgr) || !mp->framedone_handler)
+ continue;
+
+ if (mask & dispc_mgr_get_framedone_irq(i))
+ mp->framedone_handler(mp->framedone_handler_data);
+ }
+
if (!need_isr())
dss_unregister_vsync_isr();
@@ -906,7 +941,7 @@ static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
mp->info = mp->user_info;
}
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
{
unsigned long flags;
struct omap_overlay *ovl;
@@ -1005,7 +1040,7 @@ static void dss_setup_fifos(void)
}
}
-int dss_mgr_enable(struct omap_overlay_manager *mgr)
+static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
@@ -1035,10 +1070,13 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
if (!mgr_manual_update(mgr))
mp->updating = true;
+ if (!dss_data.irq_enabled && need_isr())
+ dss_register_vsync_isr();
+
spin_unlock_irqrestore(&data_lock, flags);
if (!mgr_manual_update(mgr))
- dispc_mgr_enable(mgr->id, true);
+ dispc_mgr_enable_sync(mgr->id);
out:
mutex_unlock(&apply_lock);
@@ -1052,7 +1090,7 @@ err:
return r;
}
-void dss_mgr_disable(struct omap_overlay_manager *mgr)
+static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
unsigned long flags;
@@ -1063,7 +1101,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
goto out;
if (!mgr_manual_update(mgr))
- dispc_mgr_enable(mgr->id, false);
+ dispc_mgr_disable_sync(mgr->id);
spin_lock_irqsave(&data_lock, flags);
@@ -1076,7 +1114,7 @@ out:
mutex_unlock(&apply_lock);
}
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
+static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
struct omap_overlay_manager_info *info)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1097,7 +1135,7 @@ int dss_mgr_set_info(struct omap_overlay_manager *mgr,
return 0;
}
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
+static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
struct omap_overlay_manager_info *info)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1110,7 +1148,7 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
spin_unlock_irqrestore(&data_lock, flags);
}
-int dss_mgr_set_output(struct omap_overlay_manager *mgr,
+static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
struct omap_dss_output *output)
{
int r;
@@ -1142,7 +1180,7 @@ err:
return r;
}
-int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
+static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
{
int r;
struct mgr_priv_data *mp = get_mgr_priv(mgr);
@@ -1189,7 +1227,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
mp->extra_info_dirty = true;
}
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
const struct omap_video_timings *timings)
{
unsigned long flags;
@@ -1217,7 +1255,7 @@ static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
mp->extra_info_dirty = true;
}
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
const struct dss_lcd_mgr_config *config)
{
unsigned long flags;
@@ -1236,7 +1274,7 @@ out:
spin_unlock_irqrestore(&data_lock, flags);
}
-int dss_ovl_set_info(struct omap_overlay *ovl,
+static int dss_ovl_set_info(struct omap_overlay *ovl,
struct omap_overlay_info *info)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1257,7 +1295,7 @@ int dss_ovl_set_info(struct omap_overlay *ovl,
return 0;
}
-void dss_ovl_get_info(struct omap_overlay *ovl,
+static void dss_ovl_get_info(struct omap_overlay *ovl,
struct omap_overlay_info *info)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1270,7 +1308,7 @@ void dss_ovl_get_info(struct omap_overlay *ovl,
spin_unlock_irqrestore(&data_lock, flags);
}
-int dss_ovl_set_manager(struct omap_overlay *ovl,
+static int dss_ovl_set_manager(struct omap_overlay *ovl,
struct omap_overlay_manager *mgr)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
@@ -1289,45 +1327,40 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
goto err;
}
+ r = dispc_runtime_get();
+ if (r)
+ goto err;
+
spin_lock_irqsave(&data_lock, flags);
if (op->enabled) {
spin_unlock_irqrestore(&data_lock, flags);
DSSERR("overlay has to be disabled to change the manager\n");
r = -EINVAL;
- goto err;
+ goto err1;
}
- op->channel = mgr->id;
- op->extra_info_dirty = true;
+ dispc_ovl_set_channel_out(ovl->id, mgr->id);
ovl->manager = mgr;
list_add_tail(&ovl->list, &mgr->overlays);
spin_unlock_irqrestore(&data_lock, flags);
- /* XXX: When there is an overlay on a DSI manual update display, and
- * the overlay is first disabled, then moved to tv, and enabled, we
- * seem to get SYNC_LOST_DIGIT error.
- *
- * Waiting doesn't seem to help, but updating the manual update display
- * after disabling the overlay seems to fix this. This hints that the
- * overlay is perhaps somehow tied to the LCD output until the output
- * is updated.
- *
- * Userspace workaround for this is to update the LCD after disabling
- * the overlay, but before moving the overlay to TV.
- */
+ dispc_runtime_put();
mutex_unlock(&apply_lock);
return 0;
+
+err1:
+ dispc_runtime_put();
err:
mutex_unlock(&apply_lock);
return r;
}
-int dss_ovl_unset_manager(struct omap_overlay *ovl)
+static int dss_ovl_unset_manager(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
@@ -1355,9 +1388,24 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
/* wait for pending extra_info updates to ensure the ovl is disabled */
wait_pending_extra_info_updates();
+ /*
+ * For a manual update display, there is no guarantee that the overlay
+ * is really disabled in HW, we may need an extra update from this
+ * manager before the configurations can go in. Return an error if the
+ * overlay needed an update from the manager.
+ *
+ * TODO: Instead of returning an error, try to do a dummy manager update
+ * here to disable the overlay in hardware. Use the *GATED fields in
+ * the DISPC_CONFIG registers to do a dummy update.
+ */
spin_lock_irqsave(&data_lock, flags);
- op->channel = -1;
+ if (ovl_manual_update(ovl) && op->extra_info_dirty) {
+ spin_unlock_irqrestore(&data_lock, flags);
+ DSSERR("need an update to change the manager\n");
+ r = -EINVAL;
+ goto err;
+ }
ovl->manager = NULL;
list_del(&ovl->list);
@@ -1372,7 +1420,7 @@ err:
return r;
}
-bool dss_ovl_is_enabled(struct omap_overlay *ovl)
+static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
@@ -1387,7 +1435,7 @@ bool dss_ovl_is_enabled(struct omap_overlay *ovl)
return e;
}
-int dss_ovl_enable(struct omap_overlay *ovl)
+static int dss_ovl_enable(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
@@ -1437,7 +1485,7 @@ err1:
return r;
}
-int dss_ovl_disable(struct omap_overlay *ovl)
+static int dss_ovl_disable(struct omap_overlay *ovl)
{
struct ovl_priv_data *op = get_ovl_priv(ovl);
unsigned long flags;
@@ -1472,3 +1520,152 @@ err:
return r;
}
+static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
+ void (*handler)(void *), void *data)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+ if (mp->framedone_handler)
+ return -EBUSY;
+
+ mp->framedone_handler = handler;
+ mp->framedone_handler_data = data;
+
+ return 0;
+}
+
+static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
+ void (*handler)(void *), void *data)
+{
+ struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+ WARN_ON(mp->framedone_handler != handler ||
+ mp->framedone_handler_data != data);
+
+ mp->framedone_handler = NULL;
+ mp->framedone_handler_data = NULL;
+}
+
+static const struct dss_mgr_ops apply_mgr_ops = {
+ .start_update = dss_mgr_start_update_compat,
+ .enable = dss_mgr_enable_compat,
+ .disable = dss_mgr_disable_compat,
+ .set_timings = dss_mgr_set_timings_compat,
+ .set_lcd_config = dss_mgr_set_lcd_config_compat,
+ .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
+ .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
+};
+
+static int compat_refcnt;
+static DEFINE_MUTEX(compat_init_lock);
+
+int omapdss_compat_init(void)
+{
+ struct platform_device *pdev = dss_get_core_pdev();
+ struct omap_dss_device *dssdev = NULL;
+ int i, r;
+
+ mutex_lock(&compat_init_lock);
+
+ if (compat_refcnt++ > 0)
+ goto out;
+
+ apply_init_priv();
+
+ dss_init_overlay_managers(pdev);
+ dss_init_overlays(pdev);
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
+ struct omap_overlay_manager *mgr;
+
+ mgr = omap_dss_get_overlay_manager(i);
+
+ mgr->set_output = &dss_mgr_set_output;
+ mgr->unset_output = &dss_mgr_unset_output;
+ mgr->apply = &omap_dss_mgr_apply;
+ mgr->set_manager_info = &dss_mgr_set_info;
+ mgr->get_manager_info = &dss_mgr_get_info;
+ mgr->wait_for_go = &dss_mgr_wait_for_go;
+ mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+ mgr->get_device = &dss_mgr_get_device;
+ }
+
+ for (i = 0; i < omap_dss_get_num_overlays(); i++) {
+ struct omap_overlay *ovl = omap_dss_get_overlay(i);
+
+ ovl->is_enabled = &dss_ovl_is_enabled;
+ ovl->enable = &dss_ovl_enable;
+ ovl->disable = &dss_ovl_disable;
+ ovl->set_manager = &dss_ovl_set_manager;
+ ovl->unset_manager = &dss_ovl_unset_manager;
+ ovl->set_overlay_info = &dss_ovl_set_info;
+ ovl->get_overlay_info = &dss_ovl_get_info;
+ ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
+ ovl->get_device = &dss_ovl_get_device;
+ }
+
+ r = dss_install_mgr_ops(&apply_mgr_ops);
+ if (r)
+ goto err_mgr_ops;
+
+ for_each_dss_dev(dssdev) {
+ r = display_init_sysfs(pdev, dssdev);
+ /* XXX uninit sysfs files on error */
+ if (r)
+ goto err_disp_sysfs;
+ }
+
+ dispc_runtime_get();
+
+ r = dss_dispc_initialize_irq();
+ if (r)
+ goto err_init_irq;
+
+ dispc_runtime_put();
+
+out:
+ mutex_unlock(&compat_init_lock);
+
+ return 0;
+
+err_init_irq:
+ dispc_runtime_put();
+
+err_disp_sysfs:
+ dss_uninstall_mgr_ops();
+
+err_mgr_ops:
+ dss_uninit_overlay_managers(pdev);
+ dss_uninit_overlays(pdev);
+
+ compat_refcnt--;
+
+ mutex_unlock(&compat_init_lock);
+
+ return r;
+}
+EXPORT_SYMBOL(omapdss_compat_init);
+
+void omapdss_compat_uninit(void)
+{
+ struct platform_device *pdev = dss_get_core_pdev();
+ struct omap_dss_device *dssdev = NULL;
+
+ mutex_lock(&compat_init_lock);
+
+ if (--compat_refcnt > 0)
+ goto out;
+
+ dss_dispc_uninitialize_irq();
+
+ for_each_dss_dev(dssdev)
+ display_uninit_sysfs(pdev, dssdev);
+
+ dss_uninstall_mgr_ops();
+
+ dss_uninit_overlay_managers(pdev);
+ dss_uninit_overlays(pdev);
+out:
+ mutex_unlock(&compat_init_lock);
+}
+EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b2af72dc20b..f8779d4750b 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -53,15 +53,23 @@ static char *def_disp_name;
module_param_named(def_disp, def_disp_name, charp, 0);
MODULE_PARM_DESC(def_disp, "default display name");
-#ifdef DEBUG
-bool dss_debug;
-module_param_named(debug, dss_debug, bool, 0644);
-#endif
-
-const char *dss_get_default_display_name(void)
+const char *omapdss_get_default_display_name(void)
{
return core.default_display_name;
}
+EXPORT_SYMBOL(omapdss_get_default_display_name);
+
+enum omapdss_version omapdss_get_version(void)
+{
+ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
+ return pdata->version;
+}
+EXPORT_SYMBOL(omapdss_get_version);
+
+struct platform_device *dss_get_core_pdev(void)
+{
+ return core.pdev;
+}
/* REGULATORS */
@@ -93,21 +101,6 @@ struct regulator *dss_get_vdds_sdi(void)
return reg;
}
-int dss_get_ctx_loss_count(struct device *dev)
-{
- struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
- int cnt;
-
- if (!board_data->get_context_loss_count)
- return -ENOENT;
-
- cnt = board_data->get_context_loss_count(dev);
-
- WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
- return cnt;
-}
-
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
@@ -122,7 +115,7 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
{
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
- if (!board_data->dsi_enable_pads)
+ if (!board_data->dsi_disable_pads)
return;
return board_data->dsi_disable_pads(dsi_id, lane_mask);
@@ -138,7 +131,7 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
return 0;
}
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
static int dss_debug_show(struct seq_file *s, void *unused)
{
void (*func)(struct seq_file *) = s->private;
@@ -193,7 +186,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
return 0;
}
-#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#else /* CONFIG_OMAP2_DSS_DEBUGFS */
static inline int dss_initialize_debugfs(void)
{
return 0;
@@ -205,7 +198,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
{
return 0;
}
-#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
+#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
/* PLATFORM DEVICE */
static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
@@ -237,12 +230,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
core.pdev = pdev;
- dss_features_init();
-
- dss_apply_init();
-
- dss_init_overlay_managers(pdev);
- dss_init_overlays(pdev);
+ dss_features_init(omapdss_get_version());
r = dss_initialize_debugfs();
if (r)
@@ -268,9 +256,6 @@ static int omap_dss_remove(struct platform_device *pdev)
dss_uninitialize_debugfs();
- dss_uninit_overlays(pdev);
- dss_uninit_overlay_managers(pdev);
-
return 0;
}
@@ -358,15 +343,10 @@ static int dss_driver_probe(struct device *dev)
dev_name(dev), dssdev->driver_name,
dssdrv->driver.name);
- r = dss_init_device(core.pdev, dssdev);
- if (r)
- return r;
-
r = dssdrv->probe(dssdev);
if (r) {
DSSERR("driver probe failed: %d\n", r);
- dss_uninit_device(core.pdev, dssdev);
return r;
}
@@ -387,8 +367,6 @@ static int dss_driver_remove(struct device *dev)
dssdrv->remove(dssdev);
- dss_uninit_device(core.pdev, dssdev);
-
dssdev->driver = NULL;
return 0;
@@ -507,6 +485,9 @@ static int __init omap_dss_bus_register(void)
/* INIT */
static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_init_platform_driver,
+#endif
#ifdef CONFIG_OMAP2_DSS_DPI
dpi_init_platform_driver,
#endif
@@ -519,15 +500,15 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
#ifdef CONFIG_OMAP2_DSS_VENC
venc_init_platform_driver,
#endif
-#ifdef CONFIG_OMAP2_DSS_DSI
- dsi_init_platform_driver,
-#endif
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi_init_platform_driver,
#endif
};
static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_uninit_platform_driver,
+#endif
#ifdef CONFIG_OMAP2_DSS_DPI
dpi_uninit_platform_driver,
#endif
@@ -540,9 +521,6 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
#ifdef CONFIG_OMAP2_DSS_VENC
venc_uninit_platform_driver,
#endif
-#ifdef CONFIG_OMAP2_DSS_DSI
- dsi_uninit_platform_driver,
-#endif
#ifdef CONFIG_OMAP4_DSS_HDMI
hdmi_uninit_platform_driver,
#endif
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
new file mode 100644
index 00000000000..928884c9a0a
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc-compat.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "APPLY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+
+#include <video/omapdss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "dispc-compat.h"
+
+#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+ DISPC_IRQ_OCP_ERR | \
+ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+ DISPC_IRQ_SYNC_LOST | \
+ DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS 8
+
+struct omap_dispc_isr_data {
+ omap_dispc_isr_t isr;
+ void *arg;
+ u32 mask;
+};
+
+struct dispc_irq_stats {
+ unsigned long last_reset;
+ unsigned irq_count;
+ unsigned irqs[32];
+};
+
+static struct {
+ spinlock_t irq_lock;
+ u32 irq_error_mask;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+ u32 error_irqs;
+ struct work_struct error_work;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+ spinlock_t irq_stats_lock;
+ struct dispc_irq_stats irq_stats;
+#endif
+} dispc_compat;
+
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+static void dispc_dump_irqs(struct seq_file *s)
+{
+ unsigned long flags;
+ struct dispc_irq_stats stats;
+
+ spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
+
+ stats = dispc_compat.irq_stats;
+ memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
+ dispc_compat.irq_stats.last_reset = jiffies;
+
+ spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
+
+ seq_printf(s, "period %u ms\n",
+ jiffies_to_msecs(jiffies - stats.last_reset));
+
+ seq_printf(s, "irqs %d\n", stats.irq_count);
+#define PIS(x) \
+ seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
+
+ PIS(FRAMEDONE);
+ PIS(VSYNC);
+ PIS(EVSYNC_EVEN);
+ PIS(EVSYNC_ODD);
+ PIS(ACBIAS_COUNT_STAT);
+ PIS(PROG_LINE_NUM);
+ PIS(GFX_FIFO_UNDERFLOW);
+ PIS(GFX_END_WIN);
+ PIS(PAL_GAMMA_MASK);
+ PIS(OCP_ERR);
+ PIS(VID1_FIFO_UNDERFLOW);
+ PIS(VID1_END_WIN);
+ PIS(VID2_FIFO_UNDERFLOW);
+ PIS(VID2_END_WIN);
+ if (dss_feat_get_num_ovls() > 3) {
+ PIS(VID3_FIFO_UNDERFLOW);
+ PIS(VID3_END_WIN);
+ }
+ PIS(SYNC_LOST);
+ PIS(SYNC_LOST_DIGIT);
+ PIS(WAKEUP);
+ if (dss_has_feature(FEAT_MGR_LCD2)) {
+ PIS(FRAMEDONE2);
+ PIS(VSYNC2);
+ PIS(ACBIAS_COUNT_STAT2);
+ PIS(SYNC_LOST2);
+ }
+ if (dss_has_feature(FEAT_MGR_LCD3)) {
+ PIS(FRAMEDONE3);
+ PIS(VSYNC3);
+ PIS(ACBIAS_COUNT_STAT3);
+ PIS(SYNC_LOST3);
+ }
+#undef PIS
+}
+#endif
+
+/* dispc.irq_lock has to be locked by the caller */
+static void _omap_dispc_set_irqs(void)
+{
+ u32 mask;
+ int i;
+ struct omap_dispc_isr_data *isr_data;
+
+ mask = dispc_compat.irq_error_mask;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc_compat.registered_isr[i];
+
+ if (isr_data->isr == NULL)
+ continue;
+
+ mask |= isr_data->mask;
+ }
+
+ dispc_write_irqenable(mask);
+}
+
+int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+ int i;
+ int ret;
+ unsigned long flags;
+ struct omap_dispc_isr_data *isr_data;
+
+ if (isr == NULL)
+ return -EINVAL;
+
+ spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+ /* check for duplicate entry */
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc_compat.registered_isr[i];
+ if (isr_data->isr == isr && isr_data->arg == arg &&
+ isr_data->mask == mask) {
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ isr_data = NULL;
+ ret = -EBUSY;
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc_compat.registered_isr[i];
+
+ if (isr_data->isr != NULL)
+ continue;
+
+ isr_data->isr = isr;
+ isr_data->arg = arg;
+ isr_data->mask = mask;
+ ret = 0;
+
+ break;
+ }
+
+ if (ret)
+ goto err;
+
+ _omap_dispc_set_irqs();
+
+ spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+ return 0;
+err:
+ spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(omap_dispc_register_isr);
+
+int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+{
+ int i;
+ unsigned long flags;
+ int ret = -EINVAL;
+ struct omap_dispc_isr_data *isr_data;
+
+ spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc_compat.registered_isr[i];
+ if (isr_data->isr != isr || isr_data->arg != arg ||
+ isr_data->mask != mask)
+ continue;
+
+ /* found the correct isr */
+
+ isr_data->isr = NULL;
+ isr_data->arg = NULL;
+ isr_data->mask = 0;
+
+ ret = 0;
+ break;
+ }
+
+ if (ret == 0)
+ _omap_dispc_set_irqs();
+
+ spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(omap_dispc_unregister_isr);
+
+static void print_irq_status(u32 status)
+{
+ if ((status & dispc_compat.irq_error_mask) == 0)
+ return;
+
+#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
+
+ pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
+ status,
+ PIS(OCP_ERR),
+ PIS(GFX_FIFO_UNDERFLOW),
+ PIS(VID1_FIFO_UNDERFLOW),
+ PIS(VID2_FIFO_UNDERFLOW),
+ dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
+ PIS(SYNC_LOST),
+ PIS(SYNC_LOST_DIGIT),
+ dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
+ dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
+#undef PIS
+}
+
+/* Called from dss.c. Note that we don't touch clocks here,
+ * but we presume they are on because we got an IRQ. However,
+ * an irq handler may turn the clocks off, so we may not have
+ * clock later in the function. */
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
+{
+ int i;
+ u32 irqstatus, irqenable;
+ u32 handledirqs = 0;
+ u32 unhandled_errors;
+ struct omap_dispc_isr_data *isr_data;
+ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+
+ spin_lock(&dispc_compat.irq_lock);
+
+ irqstatus = dispc_read_irqstatus();
+ irqenable = dispc_read_irqenable();
+
+ /* IRQ is not for us */
+ if (!(irqstatus & irqenable)) {
+ spin_unlock(&dispc_compat.irq_lock);
+ return IRQ_NONE;
+ }
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+ spin_lock(&dispc_compat.irq_stats_lock);
+ dispc_compat.irq_stats.irq_count++;
+ dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
+ spin_unlock(&dispc_compat.irq_stats_lock);
+#endif
+
+ print_irq_status(irqstatus);
+
+ /* Ack the interrupt. Do it here before clocks are possibly turned
+ * off */
+ dispc_clear_irqstatus(irqstatus);
+ /* flush posted write */
+ dispc_read_irqstatus();
+
+ /* make a copy and unlock, so that isrs can unregister
+ * themselves */
+ memcpy(registered_isr, dispc_compat.registered_isr,
+ sizeof(registered_isr));
+
+ spin_unlock(&dispc_compat.irq_lock);
+
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &registered_isr[i];
+
+ if (!isr_data->isr)
+ continue;
+
+ if (isr_data->mask & irqstatus) {
+ isr_data->isr(isr_data->arg, irqstatus);
+ handledirqs |= isr_data->mask;
+ }
+ }
+
+ spin_lock(&dispc_compat.irq_lock);
+
+ unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
+
+ if (unhandled_errors) {
+ dispc_compat.error_irqs |= unhandled_errors;
+
+ dispc_compat.irq_error_mask &= ~unhandled_errors;
+ _omap_dispc_set_irqs();
+
+ schedule_work(&dispc_compat.error_work);
+ }
+
+ spin_unlock(&dispc_compat.irq_lock);
+
+ return IRQ_HANDLED;
+}
+
+static void dispc_error_worker(struct work_struct *work)
+{
+ int i;
+ u32 errors;
+ unsigned long flags;
+ static const unsigned fifo_underflow_bits[] = {
+ DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+ DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+ DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+ DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+ };
+
+ spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+ errors = dispc_compat.error_irqs;
+ dispc_compat.error_irqs = 0;
+ spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+ dispc_runtime_get();
+
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ unsigned bit;
+
+ ovl = omap_dss_get_overlay(i);
+ bit = fifo_underflow_bits[i];
+
+ if (bit & errors) {
+ DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
+ ovl->name);
+ dispc_ovl_enable(ovl->id, false);
+ dispc_mgr_go(ovl->manager->id);
+ msleep(50);
+ }
+ }
+
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+ unsigned bit;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ bit = dispc_mgr_get_sync_lost_irq(i);
+
+ if (bit & errors) {
+ int j;
+
+ DSSERR("SYNC_LOST on channel %s, restarting the output "
+ "with video overlays disabled\n",
+ mgr->name);
+
+ dss_mgr_disable(mgr);
+
+ for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(j);
+
+ if (ovl->id != OMAP_DSS_GFX &&
+ ovl->manager == mgr)
+ ovl->disable(ovl);
+ }
+
+ dss_mgr_enable(mgr);
+ }
+ }
+
+ if (errors & DISPC_IRQ_OCP_ERR) {
+ DSSERR("OCP_ERR\n");
+ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
+ struct omap_overlay_manager *mgr;
+
+ mgr = omap_dss_get_overlay_manager(i);
+ dss_mgr_disable(mgr);
+ }
+ }
+
+ spin_lock_irqsave(&dispc_compat.irq_lock, flags);
+ dispc_compat.irq_error_mask |= errors;
+ _omap_dispc_set_irqs();
+ spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
+
+ dispc_runtime_put();
+}
+
+int dss_dispc_initialize_irq(void)
+{
+ int r;
+
+#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
+ spin_lock_init(&dispc_compat.irq_stats_lock);
+ dispc_compat.irq_stats.last_reset = jiffies;
+ dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
+#endif
+
+ spin_lock_init(&dispc_compat.irq_lock);
+
+ memset(dispc_compat.registered_isr, 0,
+ sizeof(dispc_compat.registered_isr));
+
+ dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+ if (dss_has_feature(FEAT_MGR_LCD2))
+ dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
+ if (dss_has_feature(FEAT_MGR_LCD3))
+ dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
+ if (dss_feat_get_num_ovls() > 3)
+ dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
+
+ /*
+ * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+ * so clear it
+ */
+ dispc_clear_irqstatus(dispc_read_irqstatus());
+
+ INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
+
+ _omap_dispc_set_irqs();
+
+ r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
+ if (r) {
+ DSSERR("dispc_request_irq failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+void dss_dispc_uninitialize_irq(void)
+{
+ dispc_free_irq(&dispc_compat);
+}
+
+static void dispc_mgr_disable_isr(void *data, u32 mask)
+{
+ struct completion *compl = data;
+ complete(compl);
+}
+
+static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
+{
+ dispc_mgr_enable(channel, true);
+}
+
+static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
+{
+ DECLARE_COMPLETION_ONSTACK(framedone_compl);
+ int r;
+ u32 irq;
+
+ if (dispc_mgr_is_enabled(channel) == false)
+ return;
+
+ /*
+ * When we disable LCD output, we need to wait for FRAMEDONE to know
+ * that DISPC has finished with the LCD output.
+ */
+
+ irq = dispc_mgr_get_framedone_irq(channel);
+
+ r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+ irq);
+ if (r)
+ DSSERR("failed to register FRAMEDONE isr\n");
+
+ dispc_mgr_enable(channel, false);
+
+ /* if we couldn't register for framedone, just sleep and exit */
+ if (r) {
+ msleep(100);
+ return;
+ }
+
+ if (!wait_for_completion_timeout(&framedone_compl,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for FRAME DONE\n");
+
+ r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+ irq);
+ if (r)
+ DSSERR("failed to unregister FRAMEDONE isr\n");
+}
+
+static void dispc_digit_out_enable_isr(void *data, u32 mask)
+{
+ struct completion *compl = data;
+
+ /* ignore any sync lost interrupts */
+ if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
+ complete(compl);
+}
+
+static void dispc_mgr_enable_digit_out(void)
+{
+ DECLARE_COMPLETION_ONSTACK(vsync_compl);
+ int r;
+ u32 irq_mask;
+
+ if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
+ return;
+
+ /*
+ * Digit output produces some sync lost interrupts during the first
+ * frame when enabling. Those need to be ignored, so we register for the
+ * sync lost irq to prevent the error handler from triggering.
+ */
+
+ irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
+ dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
+
+ r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
+ irq_mask);
+ if (r) {
+ DSSERR("failed to register %x isr\n", irq_mask);
+ return;
+ }
+
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
+
+ /* wait for the first evsync */
+ if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for digit out to start\n");
+
+ r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
+ irq_mask);
+ if (r)
+ DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+static void dispc_mgr_disable_digit_out(void)
+{
+ DECLARE_COMPLETION_ONSTACK(framedone_compl);
+ int r, i;
+ u32 irq_mask;
+ int num_irqs;
+
+ if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
+ return;
+
+ /*
+ * When we disable the digit output, we need to wait for FRAMEDONE to
+ * know that DISPC has finished with the output.
+ */
+
+ irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
+ num_irqs = 1;
+
+ if (!irq_mask) {
+ /*
+ * omap 2/3 don't have framedone irq for TV, so we need to use
+ * vsyncs for this.
+ */
+
+ irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
+ /*
+ * We need to wait for both even and odd vsyncs. Note that this
+ * is not totally reliable, as we could get a vsync interrupt
+ * before we disable the output, which leads to timeout in the
+ * wait_for_completion.
+ */
+ num_irqs = 2;
+ }
+
+ r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
+ irq_mask);
+ if (r)
+ DSSERR("failed to register %x isr\n", irq_mask);
+
+ dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
+
+ /* if we couldn't register the irq, just sleep and exit */
+ if (r) {
+ msleep(100);
+ return;
+ }
+
+ for (i = 0; i < num_irqs; ++i) {
+ if (!wait_for_completion_timeout(&framedone_compl,
+ msecs_to_jiffies(100)))
+ DSSERR("timeout waiting for digit out to stop\n");
+ }
+
+ r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
+ irq_mask);
+ if (r)
+ DSSERR("failed to unregister %x isr\n", irq_mask);
+}
+
+void dispc_mgr_enable_sync(enum omap_channel channel)
+{
+ if (dss_mgr_is_lcd(channel))
+ dispc_mgr_enable_lcd_out(channel);
+ else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+ dispc_mgr_enable_digit_out();
+ else
+ WARN_ON(1);
+}
+
+void dispc_mgr_disable_sync(enum omap_channel channel)
+{
+ if (dss_mgr_is_lcd(channel))
+ dispc_mgr_disable_lcd_out(channel);
+ else if (channel == OMAP_DSS_CHANNEL_DIGIT)
+ dispc_mgr_disable_digit_out();
+ else
+ WARN_ON(1);
+}
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+ unsigned long timeout)
+{
+ void dispc_irq_wait_handler(void *data, u32 mask)
+ {
+ complete((struct completion *)data);
+ }
+
+ int r;
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
+ irqmask);
+
+ if (r)
+ return r;
+
+ timeout = wait_for_completion_interruptible_timeout(&completion,
+ timeout);
+
+ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
+
+ if (timeout == 0)
+ return -ETIMEDOUT;
+
+ if (timeout == -ERESTARTSYS)
+ return -ERESTARTSYS;
+
+ return 0;
+}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
new file mode 100644
index 00000000000..14a69b3d4fb
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc-compat.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_DISPC_COMPAT_H
+#define __OMAP2_DSS_DISPC_COMPAT_H
+
+void dispc_mgr_enable_sync(enum omap_channel channel);
+void dispc_mgr_disable_sync(enum omap_channel channel);
+
+int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
+ unsigned long timeout);
+
+int dss_dispc_initialize_irq(void);
+void dss_dispc_uninitialize_irq(void);
+
+#endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b43477a5fae..05ff2b91d9e 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -33,11 +33,9 @@
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/hardirq.h>
-#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-
-#include <plat/cpu.h>
+#include <linux/sizes.h>
#include <video/omapdss.h>
@@ -48,21 +46,6 @@
/* DISPC */
#define DISPC_SZ_REGS SZ_4K
-#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
- DISPC_IRQ_OCP_ERR | \
- DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
- DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
- DISPC_IRQ_SYNC_LOST | \
- DISPC_IRQ_SYNC_LOST_DIGIT)
-
-#define DISPC_MAX_NR_ISRS 8
-
-struct omap_dispc_isr_data {
- omap_dispc_isr_t isr;
- void *arg;
- u32 mask;
-};
-
enum omap_burst_size {
BURST_SIZE_X2 = 0,
BURST_SIZE_X4 = 1,
@@ -75,12 +58,6 @@ enum omap_burst_size {
#define REG_FLD_MOD(idx, val, start, end) \
dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
-struct dispc_irq_stats {
- unsigned long last_reset;
- unsigned irq_count;
- unsigned irqs[32];
-};
-
struct dispc_features {
u8 sw_start;
u8 fp_start;
@@ -88,19 +65,26 @@ struct dispc_features {
u16 sw_max;
u16 vp_max;
u16 hp_max;
- int (*calc_scaling) (enum omap_plane plane,
+ u8 mgr_width_start;
+ u8 mgr_height_start;
+ u16 mgr_width_max;
+ u16 mgr_height_max;
+ int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
const struct omap_video_timings *mgr_timings,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
- unsigned long (*calc_core_clk) (enum omap_plane plane,
+ unsigned long (*calc_core_clk) (unsigned long pclk,
u16 width, u16 height, u16 out_width, u16 out_height,
bool mem_to_mem);
u8 num_fifos;
/* swap GFX & WB fifos */
bool gfx_fifo_workaround:1;
+
+ /* no DISPC_IRQ_FRAMEDONETV on this SoC */
+ bool no_framedone_tv:1;
};
#define DISPC_MAX_NR_FIFOS 5
@@ -112,27 +96,15 @@ static struct {
int ctx_loss_cnt;
int irq;
- struct clk *dss_clk;
u32 fifo_size[DISPC_MAX_NR_FIFOS];
/* maps which plane is using a fifo. fifo-id -> plane-id */
int fifo_assignment[DISPC_MAX_NR_FIFOS];
- spinlock_t irq_lock;
- u32 irq_error_mask;
- struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
- u32 error_irqs;
- struct work_struct error_work;
-
bool ctx_valid;
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
const struct dispc_features *feat;
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
- spinlock_t irq_stats_lock;
- struct dispc_irq_stats irq_stats;
-#endif
} dispc;
enum omap_color_component {
@@ -188,7 +160,7 @@ static const struct {
[OMAP_DSS_CHANNEL_DIGIT] = {
.name = "DIGIT",
.vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
- .framedone_irq = 0,
+ .framedone_irq = DISPC_IRQ_FRAMEDONETV,
.sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
.reg_desc = {
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
@@ -243,7 +215,6 @@ struct color_conv_coef {
int full_range;
};
-static void _omap_dispc_set_irqs(void);
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
@@ -376,7 +347,7 @@ static void dispc_save_context(void)
if (dss_has_feature(FEAT_CORE_CLK_DIV))
SR(DIVISOR);
- dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev);
+ dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
dispc.ctx_valid = true;
DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
@@ -391,7 +362,7 @@ static void dispc_restore_context(void)
if (!dispc.ctx_valid)
return;
- ctx = dss_get_ctx_loss_count(&dispc.pdev->dev);
+ ctx = dss_get_ctx_loss_count();
if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
return;
@@ -498,7 +469,7 @@ static void dispc_restore_context(void)
if (dss_has_feature(FEAT_MGR_LCD3))
RR(CONTROL3);
/* clear spurious SYNC_LOST_DIGIT interrupts */
- dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
+ dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
/*
* enable last so IRQs won't trigger before
@@ -522,6 +493,7 @@ int dispc_runtime_get(void)
WARN_ON(r < 0);
return r < 0 ? r : 0;
}
+EXPORT_SYMBOL(dispc_runtime_get);
void dispc_runtime_put(void)
{
@@ -532,16 +504,28 @@ void dispc_runtime_put(void)
r = pm_runtime_put_sync(&dispc.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
+EXPORT_SYMBOL(dispc_runtime_put);
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
{
return mgr_desc[channel].vsync_irq;
}
+EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
{
+ if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
+ return 0;
+
return mgr_desc[channel].framedone_irq;
}
+EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
+
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
+{
+ return mgr_desc[channel].sync_lost_irq;
+}
+EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
u32 dispc_wb_get_framedone_irq(void)
{
@@ -552,28 +536,18 @@ bool dispc_mgr_go_busy(enum omap_channel channel)
{
return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
}
+EXPORT_SYMBOL(dispc_mgr_go_busy);
void dispc_mgr_go(enum omap_channel channel)
{
- bool enable_bit, go_bit;
-
- /* if the channel is not enabled, we don't need GO */
- enable_bit = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE) == 1;
-
- if (!enable_bit)
- return;
-
- go_bit = mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
-
- if (go_bit) {
- DSSERR("GO bit not down for channel %d\n", channel);
- return;
- }
+ WARN_ON(dispc_mgr_is_enabled(channel) == false);
+ WARN_ON(dispc_mgr_go_busy(channel));
DSSDBG("GO %s\n", mgr_desc[channel].name);
mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
}
+EXPORT_SYMBOL(dispc_mgr_go);
bool dispc_wb_go_busy(void)
{
@@ -977,6 +951,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
}
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
}
+EXPORT_SYMBOL(dispc_ovl_set_channel_out);
static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
{
@@ -1042,7 +1017,7 @@ static void dispc_configure_burst_sizes(void)
const int burst_size = BURST_SIZE_X8;
/* Configure burst size always to maximum size */
- for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+ for (i = 0; i < dss_feat_get_num_ovls(); ++i)
dispc_ovl_set_burst_size(i, burst_size);
}
@@ -1076,7 +1051,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
}
static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
- struct omap_dss_cpr_coefs *coefs)
+ const struct omap_dss_cpr_coefs *coefs)
{
u32 coef_r, coef_g, coef_b;
@@ -1124,7 +1099,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
{
u32 val;
- val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
+ FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
+
dispc_write_reg(DISPC_SIZE_MGR(channel), val);
}
@@ -1246,7 +1223,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
if (use_fifomerge) {
total_fifo_size = 0;
- for (i = 0; i < omap_dss_get_num_overlays(); ++i)
+ for (i = 0; i < dss_feat_get_num_ovls(); ++i)
total_fifo_size += dispc_ovl_get_fifo_size(i);
} else {
total_fifo_size = ovl_fifo_size;
@@ -1991,16 +1968,14 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
* This function is used to avoid synclosts in OMAP3, because of some
* undocumented horizontal position and timing related limitations.
*/
-static int check_horiz_timing_omap3(enum omap_plane plane,
+static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
const struct omap_video_timings *t, u16 pos_x,
u16 width, u16 height, u16 out_width, u16 out_height)
{
- int DS = DIV_ROUND_UP(height, out_height);
+ const int ds = DIV_ROUND_UP(height, out_height);
unsigned long nonactive;
static const u8 limits[3] = { 8, 10, 20 };
u64 val, blank;
- unsigned long pclk = dispc_plane_pclk_rate(plane);
- unsigned long lclk = dispc_plane_lclk_rate(plane);
int i;
nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
@@ -2022,8 +1997,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
*/
val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
- val, max(0, DS - 2) * width);
- if (val < max(0, DS - 2) * width)
+ val, max(0, ds - 2) * width);
+ if (val < max(0, ds - 2) * width)
return -EINVAL;
/*
@@ -2033,21 +2008,20 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
*/
val = div_u64((u64)nonactive * lclk, pclk);
DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
- val, max(0, DS - 1) * width);
- if (val < max(0, DS - 1) * width)
+ val, max(0, ds - 1) * width);
+ if (val < max(0, ds - 1) * width)
return -EINVAL;
return 0;
}
-static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
+static unsigned long calc_core_clk_five_taps(unsigned long pclk,
const struct omap_video_timings *mgr_timings, u16 width,
u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode)
{
u32 core_clk = 0;
u64 tmp;
- unsigned long pclk = dispc_plane_pclk_rate(plane);
if (height <= out_height && width <= out_width)
return (unsigned long) pclk;
@@ -2081,22 +2055,19 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
return core_clk;
}
-static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
{
- unsigned long pclk = dispc_plane_pclk_rate(plane);
-
if (height > out_height && width > out_width)
return pclk * 4;
else
return pclk * 2;
}
-static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
{
unsigned int hf, vf;
- unsigned long pclk = dispc_plane_pclk_rate(plane);
/*
* FIXME how to determine the 'A' factor
@@ -2119,11 +2090,9 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
return pclk * vf * hf;
}
-static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
+static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
{
- unsigned long pclk;
-
/*
* If the overlay/writeback is in mem to mem mode, there are no
* downscaling limitations with respect to pixel clock, return 1 as
@@ -2133,15 +2102,13 @@ static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
if (mem_to_mem)
return 1;
- pclk = dispc_plane_pclk_rate(plane);
-
if (width > out_width)
return DIV_ROUND_UP(pclk, out_width) * width;
else
return pclk;
}
-static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
const struct omap_video_timings *mgr_timings,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
@@ -2159,7 +2126,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
do {
in_height = DIV_ROUND_UP(height, *decim_y);
in_width = DIV_ROUND_UP(width, *decim_x);
- *core_clk = dispc.feat->calc_core_clk(plane, in_width,
+ *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
in_height, out_width, out_height, mem_to_mem);
error = (in_width > maxsinglelinewidth || !*core_clk ||
*core_clk > dispc_core_clk_rate());
@@ -2182,7 +2149,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
return 0;
}
-static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
const struct omap_video_timings *mgr_timings,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
@@ -2198,10 +2165,10 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
do {
in_height = DIV_ROUND_UP(height, *decim_y);
in_width = DIV_ROUND_UP(width, *decim_x);
- *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
+ *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
in_width, in_height, out_width, out_height, color_mode);
- error = check_horiz_timing_omap3(plane, mgr_timings,
+ error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
pos_x, in_width, in_height, out_width,
out_height);
@@ -2210,7 +2177,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
in_height < out_height * 2)
*five_taps = false;
if (!*five_taps)
- *core_clk = dispc.feat->calc_core_clk(plane, in_width,
+ *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
in_height, out_width, out_height,
mem_to_mem);
@@ -2229,8 +2196,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
}
} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
- if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
- out_width, out_height)){
+ if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
+ height, out_width, out_height)){
DSSERR("horizontal timing too tight\n");
return -EINVAL;
}
@@ -2248,7 +2215,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
return 0;
}
-static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
+static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
const struct omap_video_timings *mgr_timings,
u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode, bool *five_taps,
@@ -2260,14 +2227,14 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
u16 in_height = DIV_ROUND_UP(height, *decim_y);
const int maxsinglelinewidth =
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
- unsigned long pclk = dispc_plane_pclk_rate(plane);
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
- if (mem_to_mem)
- in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
- else
+ if (mem_to_mem) {
+ in_width_max = out_width * maxdownscale;
+ } else {
in_width_max = dispc_core_clk_rate() /
DIV_ROUND_UP(pclk, out_width);
+ }
*decim_x = DIV_ROUND_UP(width, in_width_max);
@@ -2285,12 +2252,12 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
return -EINVAL;
}
- *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
+ *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
out_width, out_height, mem_to_mem);
return 0;
}
-static int dispc_ovl_calc_scaling(enum omap_plane plane,
+static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
enum omap_overlay_caps caps,
const struct omap_video_timings *mgr_timings,
u16 width, u16 height, u16 out_width, u16 out_height,
@@ -2309,9 +2276,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
return -EINVAL;
- *x_predecim = max_decim_limit;
- *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
- dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
+ if (mem_to_mem) {
+ *x_predecim = *y_predecim = 1;
+ } else {
+ *x_predecim = max_decim_limit;
+ *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
+ dss_has_feature(FEAT_BURST_2D)) ?
+ 2 : max_decim_limit;
+ }
if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2332,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
if (decim_y > *y_predecim || out_height > height * 8)
return -EINVAL;
- ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
+ ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
out_width, out_height, color_mode, five_taps,
x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
mem_to_mem);
@@ -2355,6 +2327,47 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
return 0;
}
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
+ const struct omap_overlay_info *oi,
+ const struct omap_video_timings *timings,
+ int *x_predecim, int *y_predecim)
+{
+ enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
+ bool five_taps = true;
+ bool fieldmode = 0;
+ u16 in_height = oi->height;
+ u16 in_width = oi->width;
+ bool ilace = timings->interlace;
+ u16 out_width, out_height;
+ int pos_x = oi->pos_x;
+ unsigned long pclk = dispc_mgr_pclk_rate(channel);
+ unsigned long lclk = dispc_mgr_lclk_rate(channel);
+
+ out_width = oi->out_width == 0 ? oi->width : oi->out_width;
+ out_height = oi->out_height == 0 ? oi->height : oi->out_height;
+
+ if (ilace && oi->height == out_height)
+ fieldmode = 1;
+
+ if (ilace) {
+ if (fieldmode)
+ in_height /= 2;
+ out_height /= 2;
+
+ DSSDBG("adjusting for ilace: height %d, out_height %d\n",
+ in_height, out_height);
+ }
+
+ if (!dss_feat_color_mode_supported(plane, oi->color_mode))
+ return -EINVAL;
+
+ return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
+ in_height, out_width, out_height, oi->color_mode,
+ &five_taps, x_predecim, y_predecim, pos_x,
+ oi->rotation_type, false);
+}
+EXPORT_SYMBOL(dispc_ovl_check);
+
static int dispc_ovl_setup_common(enum omap_plane plane,
enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
@@ -2370,12 +2383,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
unsigned offset0, offset1;
s32 row_inc;
s32 pix_inc;
- u16 frame_height = height;
+ u16 frame_width, frame_height;
unsigned int field_offset = 0;
u16 in_height = height;
u16 in_width = width;
int x_predecim = 1, y_predecim = 1;
bool ilace = mgr_timings->interlace;
+ unsigned long pclk = dispc_plane_pclk_rate(plane);
+ unsigned long lclk = dispc_plane_lclk_rate(plane);
if (paddr == 0)
return -EINVAL;
@@ -2400,7 +2415,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
if (!dss_feat_color_mode_supported(plane, color_mode))
return -EINVAL;
- r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
+ r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
in_height, out_width, out_height, color_mode,
&five_taps, &x_predecim, &y_predecim, pos_x,
rotation_type, mem_to_mem);
@@ -2438,20 +2453,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
row_inc = 0;
pix_inc = 0;
+ if (plane == OMAP_DSS_WB) {
+ frame_width = out_width;
+ frame_height = out_height;
+ } else {
+ frame_width = in_width;
+ frame_height = height;
+ }
+
if (rotation_type == OMAP_DSS_ROT_TILER)
- calc_tiler_rotation_offset(screen_width, in_width,
+ calc_tiler_rotation_offset(screen_width, frame_width,
color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc,
x_predecim, y_predecim);
else if (rotation_type == OMAP_DSS_ROT_DMA)
- calc_dma_rotation_offset(rotation, mirror,
- screen_width, in_width, frame_height,
+ calc_dma_rotation_offset(rotation, mirror, screen_width,
+ frame_width, frame_height,
color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc,
x_predecim, y_predecim);
else
calc_vrfb_rotation_offset(rotation, mirror,
- screen_width, in_width, frame_height,
+ screen_width, frame_width, frame_height,
color_mode, fieldmode, field_offset,
&offset0, &offset1, &row_inc, &pix_inc,
x_predecim, y_predecim);
@@ -2505,7 +2528,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
bool mem_to_mem)
{
int r;
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
+ enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
enum omap_channel channel;
channel = dispc_ovl_get_channel_out(plane);
@@ -2516,7 +2539,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
oi->color_mode, oi->rotation, oi->mirror, channel, replication);
- r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
+ r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
@@ -2524,6 +2547,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
return r;
}
+EXPORT_SYMBOL(dispc_ovl_setup);
int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
bool mem_to_mem, const struct omap_video_timings *mgr_timings)
@@ -2584,192 +2608,39 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
return 0;
}
+EXPORT_SYMBOL(dispc_ovl_enable);
-static void dispc_disable_isr(void *data, u32 mask)
+bool dispc_ovl_enabled(enum omap_plane plane)
{
- struct completion *compl = data;
- complete(compl);
+ return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
}
+EXPORT_SYMBOL(dispc_ovl_enabled);
-static void _enable_lcd_out(enum omap_channel channel, bool enable)
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
{
mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
/* flush posted write */
mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
}
-
-static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
-{
- struct completion frame_done_completion;
- bool is_on;
- int r;
- u32 irq;
-
- /* When we disable LCD output, we need to wait until frame is done.
- * Otherwise the DSS is still working, and turning off the clocks
- * prevents DSS from going to OFF mode */
- is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
-
- irq = mgr_desc[channel].framedone_irq;
-
- if (!enable && is_on) {
- init_completion(&frame_done_completion);
-
- r = omap_dispc_register_isr(dispc_disable_isr,
- &frame_done_completion, irq);
-
- if (r)
- DSSERR("failed to register FRAMEDONE isr\n");
- }
-
- _enable_lcd_out(channel, enable);
-
- if (!enable && is_on) {
- if (!wait_for_completion_timeout(&frame_done_completion,
- msecs_to_jiffies(100)))
- DSSERR("timeout waiting for FRAME DONE\n");
-
- r = omap_dispc_unregister_isr(dispc_disable_isr,
- &frame_done_completion, irq);
-
- if (r)
- DSSERR("failed to unregister FRAMEDONE isr\n");
- }
-}
-
-static void _enable_digit_out(bool enable)
-{
- REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
- /* flush posted write */
- dispc_read_reg(DISPC_CONTROL);
-}
-
-static void dispc_mgr_enable_digit_out(bool enable)
-{
- struct completion frame_done_completion;
- enum dss_hdmi_venc_clk_source_select src;
- int r, i;
- u32 irq_mask;
- int num_irqs;
-
- if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
- return;
-
- src = dss_get_hdmi_venc_clk_source();
-
- if (enable) {
- unsigned long flags;
- /* When we enable digit output, we'll get an extra digit
- * sync lost interrupt, that we need to ignore */
- spin_lock_irqsave(&dispc.irq_lock, flags);
- dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
- _omap_dispc_set_irqs();
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
- }
-
- /* When we disable digit output, we need to wait until fields are done.
- * Otherwise the DSS is still working, and turning off the clocks
- * prevents DSS from going to OFF mode. And when enabling, we need to
- * wait for the extra sync losts */
- init_completion(&frame_done_completion);
-
- if (src == DSS_HDMI_M_PCLK && enable == false) {
- irq_mask = DISPC_IRQ_FRAMEDONETV;
- num_irqs = 1;
- } else {
- irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
- /* XXX I understand from TRM that we should only wait for the
- * current field to complete. But it seems we have to wait for
- * both fields */
- num_irqs = 2;
- }
-
- r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
- irq_mask);
- if (r)
- DSSERR("failed to register %x isr\n", irq_mask);
-
- _enable_digit_out(enable);
-
- for (i = 0; i < num_irqs; ++i) {
- if (!wait_for_completion_timeout(&frame_done_completion,
- msecs_to_jiffies(100)))
- DSSERR("timeout waiting for digit out to %s\n",
- enable ? "start" : "stop");
- }
-
- r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
- irq_mask);
- if (r)
- DSSERR("failed to unregister %x isr\n", irq_mask);
-
- if (enable) {
- unsigned long flags;
- spin_lock_irqsave(&dispc.irq_lock, flags);
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
- dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
- _omap_dispc_set_irqs();
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
- }
-}
+EXPORT_SYMBOL(dispc_mgr_enable);
bool dispc_mgr_is_enabled(enum omap_channel channel)
{
return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
}
-
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
-{
- if (dss_mgr_is_lcd(channel))
- dispc_mgr_enable_lcd_out(channel, enable);
- else if (channel == OMAP_DSS_CHANNEL_DIGIT)
- dispc_mgr_enable_digit_out(enable);
- else
- BUG();
-}
+EXPORT_SYMBOL(dispc_mgr_is_enabled);
void dispc_wb_enable(bool enable)
{
- enum omap_plane plane = OMAP_DSS_WB;
- struct completion frame_done_completion;
- bool is_on;
- int r;
- u32 irq;
-
- is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
- irq = DISPC_IRQ_FRAMEDONEWB;
-
- if (!enable && is_on) {
- init_completion(&frame_done_completion);
-
- r = omap_dispc_register_isr(dispc_disable_isr,
- &frame_done_completion, irq);
- if (r)
- DSSERR("failed to register FRAMEDONEWB isr\n");
- }
-
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
-
- if (!enable && is_on) {
- if (!wait_for_completion_timeout(&frame_done_completion,
- msecs_to_jiffies(100)))
- DSSERR("timeout waiting for FRAMEDONEWB\n");
-
- r = omap_dispc_unregister_isr(dispc_disable_isr,
- &frame_done_completion, irq);
- if (r)
- DSSERR("failed to unregister FRAMEDONEWB isr\n");
- }
+ dispc_ovl_enable(OMAP_DSS_WB, enable);
}
bool dispc_wb_is_enabled(void)
{
- enum omap_plane plane = OMAP_DSS_WB;
-
- return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
+ return dispc_ovl_enabled(OMAP_DSS_WB);
}
-void dispc_lcd_enable_signal_polarity(bool act_high)
+static void dispc_lcd_enable_signal_polarity(bool act_high)
{
if (!dss_has_feature(FEAT_LCDENABLEPOL))
return;
@@ -2793,13 +2664,13 @@ void dispc_pck_free_enable(bool enable)
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
}
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
{
mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
}
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
+static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
{
mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
}
@@ -2842,7 +2713,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
}
void dispc_mgr_setup(enum omap_channel channel,
- struct omap_overlay_manager_info *info)
+ const struct omap_overlay_manager_info *info)
{
dispc_mgr_set_default_color(channel, info->default_color);
dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
@@ -2854,8 +2725,9 @@ void dispc_mgr_setup(enum omap_channel channel,
dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
}
}
+EXPORT_SYMBOL(dispc_mgr_setup);
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
+static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
{
int code;
@@ -2880,7 +2752,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
}
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
+static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
{
u32 l;
int gpout0, gpout1;
@@ -2909,15 +2781,33 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
dispc_write_reg(DISPC_CONTROL, l);
}
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
+static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
{
mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
}
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
+ const struct dss_lcd_mgr_config *config)
+{
+ dispc_mgr_set_io_pad_mode(config->io_pad_mode);
+
+ dispc_mgr_enable_stallmode(channel, config->stallmode);
+ dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
+
+ dispc_mgr_set_clock_div(channel, &config->clock_info);
+
+ dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
+
+ dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
+
+ dispc_mgr_set_lcd_type_tft(channel);
+}
+EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
+
static bool _dispc_mgr_size_ok(u16 width, u16 height)
{
- return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
- height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
+ return width <= dispc.feat->mgr_width_max &&
+ height <= dispc.feat->mgr_height_max;
}
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -3012,7 +2902,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
/* change name to mode? */
void dispc_mgr_set_timings(enum omap_channel channel,
- struct omap_video_timings *timings)
+ const struct omap_video_timings *timings)
{
unsigned xtot, ytot;
unsigned long ht, vt;
@@ -3051,6 +2941,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
dispc_mgr_set_size(channel, t.x_res, t.y_res);
}
+EXPORT_SYMBOL(dispc_mgr_set_timings);
static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
u16 pck_div)
@@ -3078,7 +2969,7 @@ unsigned long dispc_fclk_rate(void)
switch (dss_get_dispc_clk_source()) {
case OMAP_DSS_CLK_SRC_FCK:
- r = clk_get_rate(dispc.dss_clk);
+ r = dss_get_dispc_clk_rate();
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
dsidev = dsi_get_dsidev_from_id(0);
@@ -3103,28 +2994,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
unsigned long r;
u32 l;
- l = dispc_read_reg(DISPC_DIVISORo(channel));
+ if (dss_mgr_is_lcd(channel)) {
+ l = dispc_read_reg(DISPC_DIVISORo(channel));
- lcd = FLD_GET(l, 23, 16);
+ lcd = FLD_GET(l, 23, 16);
- switch (dss_get_lcd_clk_source(channel)) {
- case OMAP_DSS_CLK_SRC_FCK:
- r = clk_get_rate(dispc.dss_clk);
- break;
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
- dsidev = dsi_get_dsidev_from_id(0);
- r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
- break;
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
- dsidev = dsi_get_dsidev_from_id(1);
- r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
- break;
- default:
- BUG();
- return 0;
- }
+ switch (dss_get_lcd_clk_source(channel)) {
+ case OMAP_DSS_CLK_SRC_FCK:
+ r = dss_get_dispc_clk_rate();
+ break;
+ case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
+ dsidev = dsi_get_dsidev_from_id(0);
+ r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+ break;
+ case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
+ dsidev = dsi_get_dsidev_from_id(1);
+ r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
+ break;
+ default:
+ BUG();
+ return 0;
+ }
- return r / lcd;
+ return r / lcd;
+ } else {
+ return dispc_fclk_rate();
+ }
}
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3174,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void)
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
{
- enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+ enum omap_channel channel;
+
+ if (plane == OMAP_DSS_WB)
+ return 0;
+
+ channel = dispc_ovl_get_channel_out(plane);
return dispc_mgr_pclk_rate(channel);
}
static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
{
- enum omap_channel channel = dispc_ovl_get_channel_out(plane);
+ enum omap_channel channel;
- if (dss_mgr_is_lcd(channel))
- return dispc_mgr_lclk_rate(channel);
- else
- return dispc_fclk_rate();
+ if (plane == OMAP_DSS_WB)
+ return 0;
+
+ channel = dispc_ovl_get_channel_out(plane);
+ return dispc_mgr_lclk_rate(channel);
}
+
static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
{
int lcd, pcd;
@@ -3246,64 +3148,6 @@ void dispc_dump_clocks(struct seq_file *s)
dispc_runtime_put();
}
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
-void dispc_dump_irqs(struct seq_file *s)
-{
- unsigned long flags;
- struct dispc_irq_stats stats;
-
- spin_lock_irqsave(&dispc.irq_stats_lock, flags);
-
- stats = dispc.irq_stats;
- memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
- dispc.irq_stats.last_reset = jiffies;
-
- spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
-
- seq_printf(s, "period %u ms\n",
- jiffies_to_msecs(jiffies - stats.last_reset));
-
- seq_printf(s, "irqs %d\n", stats.irq_count);
-#define PIS(x) \
- seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
-
- PIS(FRAMEDONE);
- PIS(VSYNC);
- PIS(EVSYNC_EVEN);
- PIS(EVSYNC_ODD);
- PIS(ACBIAS_COUNT_STAT);
- PIS(PROG_LINE_NUM);
- PIS(GFX_FIFO_UNDERFLOW);
- PIS(GFX_END_WIN);
- PIS(PAL_GAMMA_MASK);
- PIS(OCP_ERR);
- PIS(VID1_FIFO_UNDERFLOW);
- PIS(VID1_END_WIN);
- PIS(VID2_FIFO_UNDERFLOW);
- PIS(VID2_END_WIN);
- if (dss_feat_get_num_ovls() > 3) {
- PIS(VID3_FIFO_UNDERFLOW);
- PIS(VID3_END_WIN);
- }
- PIS(SYNC_LOST);
- PIS(SYNC_LOST_DIGIT);
- PIS(WAKEUP);
- if (dss_has_feature(FEAT_MGR_LCD2)) {
- PIS(FRAMEDONE2);
- PIS(VSYNC2);
- PIS(ACBIAS_COUNT_STAT2);
- PIS(SYNC_LOST2);
- }
- if (dss_has_feature(FEAT_MGR_LCD3)) {
- PIS(FRAMEDONE3);
- PIS(VSYNC3);
- PIS(ACBIAS_COUNT_STAT3);
- PIS(SYNC_LOST3);
- }
-#undef PIS
-}
-#endif
-
static void dispc_dump_regs(struct seq_file *s)
{
int i, j;
@@ -3353,7 +3197,7 @@ static void dispc_dump_regs(struct seq_file *s)
#define DISPC_REG(i, name) name(i)
#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
- 48 - strlen(#r) - strlen(p_names[i]), " ", \
+ (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
dispc_read_reg(DISPC_REG(i, r)))
p_names = mgr_names;
@@ -3430,7 +3274,7 @@ static void dispc_dump_regs(struct seq_file *s)
#define DISPC_REG(plane, name, i) name(plane, i)
#define DUMPREG(plane, name, i) \
seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
- 46 - strlen(#name) - strlen(p_names[plane]), " ", \
+ (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
dispc_read_reg(DISPC_REG(plane, name, i)))
/* Video pipeline coefficient registers */
@@ -3533,7 +3377,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
}
void dispc_mgr_set_clock_div(enum omap_channel channel,
- struct dispc_clock_info *cinfo)
+ const struct dispc_clock_info *cinfo)
{
DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
@@ -3557,403 +3401,34 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
return 0;
}
-/* dispc.irq_lock has to be locked by the caller */
-static void _omap_dispc_set_irqs(void)
+u32 dispc_read_irqstatus(void)
{
- u32 mask;
- u32 old_mask;
- int i;
- struct omap_dispc_isr_data *isr_data;
-
- mask = dispc.irq_error_mask;
-
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
- isr_data = &dispc.registered_isr[i];
-
- if (isr_data->isr == NULL)
- continue;
-
- mask |= isr_data->mask;
- }
-
- old_mask = dispc_read_reg(DISPC_IRQENABLE);
- /* clear the irqstatus for newly enabled irqs */
- dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
-
- dispc_write_reg(DISPC_IRQENABLE, mask);
-}
-
-int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
-{
- int i;
- int ret;
- unsigned long flags;
- struct omap_dispc_isr_data *isr_data;
-
- if (isr == NULL)
- return -EINVAL;
-
- spin_lock_irqsave(&dispc.irq_lock, flags);
-
- /* check for duplicate entry */
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
- isr_data = &dispc.registered_isr[i];
- if (isr_data->isr == isr && isr_data->arg == arg &&
- isr_data->mask == mask) {
- ret = -EINVAL;
- goto err;
- }
- }
-
- isr_data = NULL;
- ret = -EBUSY;
-
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
- isr_data = &dispc.registered_isr[i];
-
- if (isr_data->isr != NULL)
- continue;
-
- isr_data->isr = isr;
- isr_data->arg = arg;
- isr_data->mask = mask;
- ret = 0;
-
- break;
- }
-
- if (ret)
- goto err;
-
- _omap_dispc_set_irqs();
-
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
- return 0;
-err:
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
- return ret;
+ return dispc_read_reg(DISPC_IRQSTATUS);
}
-EXPORT_SYMBOL(omap_dispc_register_isr);
+EXPORT_SYMBOL(dispc_read_irqstatus);
-int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
+void dispc_clear_irqstatus(u32 mask)
{
- int i;
- unsigned long flags;
- int ret = -EINVAL;
- struct omap_dispc_isr_data *isr_data;
-
- spin_lock_irqsave(&dispc.irq_lock, flags);
-
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
- isr_data = &dispc.registered_isr[i];
- if (isr_data->isr != isr || isr_data->arg != arg ||
- isr_data->mask != mask)
- continue;
-
- /* found the correct isr */
-
- isr_data->isr = NULL;
- isr_data->arg = NULL;
- isr_data->mask = 0;
-
- ret = 0;
- break;
- }
-
- if (ret == 0)
- _omap_dispc_set_irqs();
-
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
- return ret;
+ dispc_write_reg(DISPC_IRQSTATUS, mask);
}
-EXPORT_SYMBOL(omap_dispc_unregister_isr);
+EXPORT_SYMBOL(dispc_clear_irqstatus);
-#ifdef DEBUG
-static void print_irq_status(u32 status)
+u32 dispc_read_irqenable(void)
{
- if ((status & dispc.irq_error_mask) == 0)
- return;
-
- printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
-
-#define PIS(x) \
- if (status & DISPC_IRQ_##x) \
- printk(#x " ");
- PIS(GFX_FIFO_UNDERFLOW);
- PIS(OCP_ERR);
- PIS(VID1_FIFO_UNDERFLOW);
- PIS(VID2_FIFO_UNDERFLOW);
- if (dss_feat_get_num_ovls() > 3)
- PIS(VID3_FIFO_UNDERFLOW);
- PIS(SYNC_LOST);
- PIS(SYNC_LOST_DIGIT);
- if (dss_has_feature(FEAT_MGR_LCD2))
- PIS(SYNC_LOST2);
- if (dss_has_feature(FEAT_MGR_LCD3))
- PIS(SYNC_LOST3);
-#undef PIS
-
- printk("\n");
+ return dispc_read_reg(DISPC_IRQENABLE);
}
-#endif
+EXPORT_SYMBOL(dispc_read_irqenable);
-/* Called from dss.c. Note that we don't touch clocks here,
- * but we presume they are on because we got an IRQ. However,
- * an irq handler may turn the clocks off, so we may not have
- * clock later in the function. */
-static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
+void dispc_write_irqenable(u32 mask)
{
- int i;
- u32 irqstatus, irqenable;
- u32 handledirqs = 0;
- u32 unhandled_errors;
- struct omap_dispc_isr_data *isr_data;
- struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
-
- spin_lock(&dispc.irq_lock);
-
- irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
- irqenable = dispc_read_reg(DISPC_IRQENABLE);
-
- /* IRQ is not for us */
- if (!(irqstatus & irqenable)) {
- spin_unlock(&dispc.irq_lock);
- return IRQ_NONE;
- }
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
- spin_lock(&dispc.irq_stats_lock);
- dispc.irq_stats.irq_count++;
- dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
- spin_unlock(&dispc.irq_stats_lock);
-#endif
-
-#ifdef DEBUG
- if (dss_debug)
- print_irq_status(irqstatus);
-#endif
- /* Ack the interrupt. Do it here before clocks are possibly turned
- * off */
- dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
- /* flush posted write */
- dispc_read_reg(DISPC_IRQSTATUS);
-
- /* make a copy and unlock, so that isrs can unregister
- * themselves */
- memcpy(registered_isr, dispc.registered_isr,
- sizeof(registered_isr));
-
- spin_unlock(&dispc.irq_lock);
-
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
- isr_data = &registered_isr[i];
-
- if (!isr_data->isr)
- continue;
-
- if (isr_data->mask & irqstatus) {
- isr_data->isr(isr_data->arg, irqstatus);
- handledirqs |= isr_data->mask;
- }
- }
-
- spin_lock(&dispc.irq_lock);
-
- unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
-
- if (unhandled_errors) {
- dispc.error_irqs |= unhandled_errors;
-
- dispc.irq_error_mask &= ~unhandled_errors;
- _omap_dispc_set_irqs();
-
- schedule_work(&dispc.error_work);
- }
-
- spin_unlock(&dispc.irq_lock);
-
- return IRQ_HANDLED;
-}
-
-static void dispc_error_worker(struct work_struct *work)
-{
- int i;
- u32 errors;
- unsigned long flags;
- static const unsigned fifo_underflow_bits[] = {
- DISPC_IRQ_GFX_FIFO_UNDERFLOW,
- DISPC_IRQ_VID1_FIFO_UNDERFLOW,
- DISPC_IRQ_VID2_FIFO_UNDERFLOW,
- DISPC_IRQ_VID3_FIFO_UNDERFLOW,
- };
-
- spin_lock_irqsave(&dispc.irq_lock, flags);
- errors = dispc.error_irqs;
- dispc.error_irqs = 0;
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
- dispc_runtime_get();
-
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- unsigned bit;
-
- ovl = omap_dss_get_overlay(i);
- bit = fifo_underflow_bits[i];
-
- if (bit & errors) {
- DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
- ovl->name);
- dispc_ovl_enable(ovl->id, false);
- dispc_mgr_go(ovl->manager->id);
- msleep(50);
- }
- }
-
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
- struct omap_overlay_manager *mgr;
- unsigned bit;
-
- mgr = omap_dss_get_overlay_manager(i);
- bit = mgr_desc[i].sync_lost_irq;
-
- if (bit & errors) {
- struct omap_dss_device *dssdev = mgr->get_device(mgr);
- bool enable;
-
- DSSERR("SYNC_LOST on channel %s, restarting the output "
- "with video overlays disabled\n",
- mgr->name);
-
- enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
- dssdev->driver->disable(dssdev);
-
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl;
- ovl = omap_dss_get_overlay(i);
-
- if (ovl->id != OMAP_DSS_GFX &&
- ovl->manager == mgr)
- dispc_ovl_enable(ovl->id, false);
- }
-
- dispc_mgr_go(mgr->id);
- msleep(50);
-
- if (enable)
- dssdev->driver->enable(dssdev);
- }
- }
-
- if (errors & DISPC_IRQ_OCP_ERR) {
- DSSERR("OCP_ERR\n");
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
- struct omap_overlay_manager *mgr;
- struct omap_dss_device *dssdev;
+ u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
- mgr = omap_dss_get_overlay_manager(i);
- dssdev = mgr->get_device(mgr);
-
- if (dssdev && dssdev->driver)
- dssdev->driver->disable(dssdev);
- }
- }
-
- spin_lock_irqsave(&dispc.irq_lock, flags);
- dispc.irq_error_mask |= errors;
- _omap_dispc_set_irqs();
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
-
- dispc_runtime_put();
-}
-
-int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
-{
- void dispc_irq_wait_handler(void *data, u32 mask)
- {
- complete((struct completion *)data);
- }
-
- int r;
- DECLARE_COMPLETION_ONSTACK(completion);
-
- r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
- irqmask);
-
- if (r)
- return r;
-
- timeout = wait_for_completion_timeout(&completion, timeout);
-
- omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
- if (timeout == 0)
- return -ETIMEDOUT;
-
- if (timeout == -ERESTARTSYS)
- return -ERESTARTSYS;
-
- return 0;
-}
-
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
- unsigned long timeout)
-{
- void dispc_irq_wait_handler(void *data, u32 mask)
- {
- complete((struct completion *)data);
- }
-
- int r;
- DECLARE_COMPLETION_ONSTACK(completion);
-
- r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
- irqmask);
-
- if (r)
- return r;
-
- timeout = wait_for_completion_interruptible_timeout(&completion,
- timeout);
-
- omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
-
- if (timeout == 0)
- return -ETIMEDOUT;
-
- if (timeout == -ERESTARTSYS)
- return -ERESTARTSYS;
-
- return 0;
-}
-
-static void _omap_dispc_initialize_irq(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dispc.irq_lock, flags);
-
- memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
-
- dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
- if (dss_has_feature(FEAT_MGR_LCD2))
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
- if (dss_has_feature(FEAT_MGR_LCD3))
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
- if (dss_feat_get_num_ovls() > 3)
- dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
-
- /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
- * so clear it */
- dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
-
- _omap_dispc_set_irqs();
+ /* clear the irqstatus for newly enabled irqs */
+ dispc_clear_irqstatus((mask ^ old_mask) & mask);
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
+ dispc_write_reg(DISPC_IRQENABLE, mask);
}
+EXPORT_SYMBOL(dispc_write_irqenable);
void dispc_enable_sidle(void)
{
@@ -4000,9 +3475,14 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
.sw_max = 64,
.vp_max = 255,
.hp_max = 256,
+ .mgr_width_start = 10,
+ .mgr_height_start = 26,
+ .mgr_width_max = 2048,
+ .mgr_height_max = 2048,
.calc_scaling = dispc_ovl_calc_scaling_24xx,
.calc_core_clk = calc_core_clk_24xx,
.num_fifos = 3,
+ .no_framedone_tv = true,
};
static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
@@ -4012,9 +3492,14 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
.sw_max = 64,
.vp_max = 255,
.hp_max = 256,
+ .mgr_width_start = 10,
+ .mgr_height_start = 26,
+ .mgr_width_max = 2048,
+ .mgr_height_max = 2048,
.calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3,
+ .no_framedone_tv = true,
};
static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
@@ -4024,9 +3509,14 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
.sw_max = 256,
.vp_max = 4095,
.hp_max = 4096,
+ .mgr_width_start = 10,
+ .mgr_height_start = 26,
+ .mgr_width_max = 2048,
+ .mgr_height_max = 2048,
.calc_scaling = dispc_ovl_calc_scaling_34xx,
.calc_core_clk = calc_core_clk_34xx,
.num_fifos = 3,
+ .no_framedone_tv = true,
};
static const struct dispc_features omap44xx_dispc_feats __initconst = {
@@ -4036,35 +3526,70 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
.sw_max = 256,
.vp_max = 4095,
.hp_max = 4096,
+ .mgr_width_start = 10,
+ .mgr_height_start = 26,
+ .mgr_width_max = 2048,
+ .mgr_height_max = 2048,
+ .calc_scaling = dispc_ovl_calc_scaling_44xx,
+ .calc_core_clk = calc_core_clk_44xx,
+ .num_fifos = 5,
+ .gfx_fifo_workaround = true,
+};
+
+static const struct dispc_features omap54xx_dispc_feats __initconst = {
+ .sw_start = 7,
+ .fp_start = 19,
+ .bp_start = 31,
+ .sw_max = 256,
+ .vp_max = 4095,
+ .hp_max = 4096,
+ .mgr_width_start = 11,
+ .mgr_height_start = 27,
+ .mgr_width_max = 4096,
+ .mgr_height_max = 4096,
.calc_scaling = dispc_ovl_calc_scaling_44xx,
.calc_core_clk = calc_core_clk_44xx,
.num_fifos = 5,
.gfx_fifo_workaround = true,
};
-static int __init dispc_init_features(struct device *dev)
+static int __init dispc_init_features(struct platform_device *pdev)
{
const struct dispc_features *src;
struct dispc_features *dst;
- dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
- dev_err(dev, "Failed to allocate DISPC Features\n");
+ dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
return -ENOMEM;
}
- if (cpu_is_omap24xx()) {
+ switch (omapdss_get_version()) {
+ case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dispc_feats;
- } else if (cpu_is_omap34xx()) {
- if (omap_rev() < OMAP3430_REV_ES3_0)
- src = &omap34xx_rev1_0_dispc_feats;
- else
- src = &omap34xx_rev3_0_dispc_feats;
- } else if (cpu_is_omap44xx()) {
- src = &omap44xx_dispc_feats;
- } else if (soc_is_omap54xx()) {
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ src = &omap34xx_rev1_0_dispc_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_OMAP3630:
+ case OMAPDSS_VER_AM35xx:
+ src = &omap34xx_rev3_0_dispc_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
src = &omap44xx_dispc_feats;
- } else {
+ break;
+
+ case OMAPDSS_VER_OMAP5:
+ src = &omap54xx_dispc_feats;
+ break;
+
+ default:
return -ENODEV;
}
@@ -4074,29 +3599,32 @@ static int __init dispc_init_features(struct device *dev)
return 0;
}
+int dispc_request_irq(irq_handler_t handler, void *dev_id)
+{
+ return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
+ IRQF_SHARED, "OMAP DISPC", dev_id);
+}
+EXPORT_SYMBOL(dispc_request_irq);
+
+void dispc_free_irq(void *dev_id)
+{
+ devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
+}
+EXPORT_SYMBOL(dispc_free_irq);
+
/* DISPC HW IP initialisation */
static int __init omap_dispchw_probe(struct platform_device *pdev)
{
u32 rev;
int r = 0;
struct resource *dispc_mem;
- struct clk *clk;
dispc.pdev = pdev;
- r = dispc_init_features(&dispc.pdev->dev);
+ r = dispc_init_features(dispc.pdev);
if (r)
return r;
- spin_lock_init(&dispc.irq_lock);
-
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
- spin_lock_init(&dispc.irq_stats_lock);
- dispc.irq_stats.last_reset = jiffies;
-#endif
-
- INIT_WORK(&dispc.error_work, dispc_error_worker);
-
dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
if (!dispc_mem) {
DSSERR("can't get IORESOURCE_MEM DISPC\n");
@@ -4116,22 +3644,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
return -ENODEV;
}
- r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
- IRQF_SHARED, "OMAP DISPC", dispc.pdev);
- if (r < 0) {
- DSSERR("request_irq failed\n");
- return r;
- }
-
- clk = clk_get(&pdev->dev, "fck");
- if (IS_ERR(clk)) {
- DSSERR("can't get fck\n");
- r = PTR_ERR(clk);
- return r;
- }
-
- dispc.dss_clk = clk;
-
pm_runtime_enable(&pdev->dev);
r = dispc_runtime_get();
@@ -4140,8 +3652,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
_omap_dispc_initial_config();
- _omap_dispc_initialize_irq();
-
rev = dispc_read_reg(DISPC_REVISION);
dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
@@ -4150,14 +3660,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
dss_debugfs_create_file("dispc", dispc_dump_regs);
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
- dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
-#endif
return 0;
err_runtime_get:
pm_runtime_disable(&pdev->dev);
- clk_put(dispc.dss_clk);
return r;
}
@@ -4165,8 +3671,6 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
- clk_put(dispc.dss_clk);
-
return 0;
}
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c
new file mode 100644
index 00000000000..18211a9ab35
--- /dev/null
+++ b/drivers/video/omap2/dss/display-sysfs.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ *
+ * Some code and ideas taken from drivers/video/omap/ driver
+ * by Imre Deak.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+
+#include <video/omapdss.h>
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t display_enabled_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
+}
+
+static ssize_t display_enabled_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int r;
+ bool enabled;
+
+ r = strtobool(buf, &enabled);
+ if (r)
+ return r;
+
+ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
+ if (enabled) {
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ return r;
+ } else {
+ dssdev->driver->disable(dssdev);
+ }
+ }
+
+ return size;
+}
+
+static ssize_t display_tear_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ dssdev->driver->get_te ?
+ dssdev->driver->get_te(dssdev) : 0);
+}
+
+static ssize_t display_tear_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int r;
+ bool te;
+
+ if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
+ return -ENOENT;
+
+ r = strtobool(buf, &te);
+ if (r)
+ return r;
+
+ r = dssdev->driver->enable_te(dssdev, te);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_timings_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_video_timings t;
+
+ if (!dssdev->driver->get_timings)
+ return -ENOENT;
+
+ dssdev->driver->get_timings(dssdev, &t);
+
+ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+ t.pixel_clock,
+ t.x_res, t.hfp, t.hbp, t.hsw,
+ t.y_res, t.vfp, t.vbp, t.vsw);
+}
+
+static ssize_t display_timings_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ struct omap_video_timings t = dssdev->panel.timings;
+ int r, found;
+
+ if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
+ return -ENOENT;
+
+ found = 0;
+#ifdef CONFIG_OMAP2_DSS_VENC
+ if (strncmp("pal", buf, 3) == 0) {
+ t = omap_dss_pal_timings;
+ found = 1;
+ } else if (strncmp("ntsc", buf, 4) == 0) {
+ t = omap_dss_ntsc_timings;
+ found = 1;
+ }
+#endif
+ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
+ &t.pixel_clock,
+ &t.x_res, &t.hfp, &t.hbp, &t.hsw,
+ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+ return -EINVAL;
+
+ r = dssdev->driver->check_timings(dssdev, &t);
+ if (r)
+ return r;
+
+ dssdev->driver->disable(dssdev);
+ dssdev->driver->set_timings(dssdev, &t);
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_rotate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int rotate;
+ if (!dssdev->driver->get_rotate)
+ return -ENOENT;
+ rotate = dssdev->driver->get_rotate(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
+}
+
+static ssize_t display_rotate_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int rot, r;
+
+ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
+ return -ENOENT;
+
+ r = kstrtoint(buf, 0, &rot);
+ if (r)
+ return r;
+
+ r = dssdev->driver->set_rotate(dssdev, rot);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_mirror_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int mirror;
+ if (!dssdev->driver->get_mirror)
+ return -ENOENT;
+ mirror = dssdev->driver->get_mirror(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
+}
+
+static ssize_t display_mirror_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int r;
+ bool mirror;
+
+ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
+ return -ENOENT;
+
+ r = strtobool(buf, &mirror);
+ if (r)
+ return r;
+
+ r = dssdev->driver->set_mirror(dssdev, mirror);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static ssize_t display_wss_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ unsigned int wss;
+
+ if (!dssdev->driver->get_wss)
+ return -ENOENT;
+
+ wss = dssdev->driver->get_wss(dssdev);
+
+ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
+}
+
+static ssize_t display_wss_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ u32 wss;
+ int r;
+
+ if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
+ return -ENOENT;
+
+ r = kstrtou32(buf, 0, &wss);
+ if (r)
+ return r;
+
+ if (wss > 0xfffff)
+ return -EINVAL;
+
+ r = dssdev->driver->set_wss(dssdev, wss);
+ if (r)
+ return r;
+
+ return size;
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+ display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
+ display_tear_show, display_tear_store);
+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+ display_timings_show, display_timings_store);
+static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
+ display_rotate_show, display_rotate_store);
+static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
+ display_mirror_show, display_mirror_store);
+static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
+ display_wss_show, display_wss_store);
+
+static struct device_attribute *display_sysfs_attrs[] = {
+ &dev_attr_enabled,
+ &dev_attr_tear_elim,
+ &dev_attr_timings,
+ &dev_attr_rotate,
+ &dev_attr_mirror,
+ &dev_attr_wss,
+ NULL
+};
+
+int display_init_sysfs(struct platform_device *pdev,
+ struct omap_dss_device *dssdev)
+{
+ struct device_attribute *attr;
+ int i, r;
+
+ /* create device sysfs files */
+ i = 0;
+ while ((attr = display_sysfs_attrs[i++]) != NULL) {
+ r = device_create_file(&dssdev->dev, attr);
+ if (r) {
+ for (i = i - 2; i >= 0; i--) {
+ attr = display_sysfs_attrs[i];
+ device_remove_file(&dssdev->dev, attr);
+ }
+
+ DSSERR("failed to create sysfs file\n");
+ return r;
+ }
+ }
+
+ /* create display? sysfs links */
+ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
+ dev_name(&dssdev->dev));
+ if (r) {
+ while ((attr = display_sysfs_attrs[i++]) != NULL)
+ device_remove_file(&dssdev->dev, attr);
+
+ DSSERR("failed to create sysfs display link\n");
+ return r;
+ }
+
+ return 0;
+}
+
+void display_uninit_sysfs(struct platform_device *pdev,
+ struct omap_dss_device *dssdev)
+{
+ struct device_attribute *attr;
+ int i = 0;
+
+ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
+
+ while ((attr = display_sysfs_attrs[i++]) != NULL)
+ device_remove_file(&dssdev->dev, attr);
+}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index ccf8550fafd..0aa8ad8f966 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -31,250 +31,6 @@
#include "dss.h"
#include "dss_features.h"
-static ssize_t display_enabled_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
-}
-
-static ssize_t display_enabled_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- int r;
- bool enabled;
-
- r = strtobool(buf, &enabled);
- if (r)
- return r;
-
- if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
- if (enabled) {
- r = dssdev->driver->enable(dssdev);
- if (r)
- return r;
- } else {
- dssdev->driver->disable(dssdev);
- }
- }
-
- return size;
-}
-
-static ssize_t display_tear_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- return snprintf(buf, PAGE_SIZE, "%d\n",
- dssdev->driver->get_te ?
- dssdev->driver->get_te(dssdev) : 0);
-}
-
-static ssize_t display_tear_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- int r;
- bool te;
-
- if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
- return -ENOENT;
-
- r = strtobool(buf, &te);
- if (r)
- return r;
-
- r = dssdev->driver->enable_te(dssdev, te);
- if (r)
- return r;
-
- return size;
-}
-
-static ssize_t display_timings_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- struct omap_video_timings t;
-
- if (!dssdev->driver->get_timings)
- return -ENOENT;
-
- dssdev->driver->get_timings(dssdev, &t);
-
- return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
- t.pixel_clock,
- t.x_res, t.hfp, t.hbp, t.hsw,
- t.y_res, t.vfp, t.vbp, t.vsw);
-}
-
-static ssize_t display_timings_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- struct omap_video_timings t = dssdev->panel.timings;
- int r, found;
-
- if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
- return -ENOENT;
-
- found = 0;
-#ifdef CONFIG_OMAP2_DSS_VENC
- if (strncmp("pal", buf, 3) == 0) {
- t = omap_dss_pal_timings;
- found = 1;
- } else if (strncmp("ntsc", buf, 4) == 0) {
- t = omap_dss_ntsc_timings;
- found = 1;
- }
-#endif
- if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
- &t.pixel_clock,
- &t.x_res, &t.hfp, &t.hbp, &t.hsw,
- &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
- return -EINVAL;
-
- r = dssdev->driver->check_timings(dssdev, &t);
- if (r)
- return r;
-
- dssdev->driver->disable(dssdev);
- dssdev->driver->set_timings(dssdev, &t);
- r = dssdev->driver->enable(dssdev);
- if (r)
- return r;
-
- return size;
-}
-
-static ssize_t display_rotate_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- int rotate;
- if (!dssdev->driver->get_rotate)
- return -ENOENT;
- rotate = dssdev->driver->get_rotate(dssdev);
- return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
-}
-
-static ssize_t display_rotate_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- int rot, r;
-
- if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
- return -ENOENT;
-
- r = kstrtoint(buf, 0, &rot);
- if (r)
- return r;
-
- r = dssdev->driver->set_rotate(dssdev, rot);
- if (r)
- return r;
-
- return size;
-}
-
-static ssize_t display_mirror_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- int mirror;
- if (!dssdev->driver->get_mirror)
- return -ENOENT;
- mirror = dssdev->driver->get_mirror(dssdev);
- return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
-}
-
-static ssize_t display_mirror_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- int r;
- bool mirror;
-
- if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
- return -ENOENT;
-
- r = strtobool(buf, &mirror);
- if (r)
- return r;
-
- r = dssdev->driver->set_mirror(dssdev, mirror);
- if (r)
- return r;
-
- return size;
-}
-
-static ssize_t display_wss_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- unsigned int wss;
-
- if (!dssdev->driver->get_wss)
- return -ENOENT;
-
- wss = dssdev->driver->get_wss(dssdev);
-
- return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
-}
-
-static ssize_t display_wss_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct omap_dss_device *dssdev = to_dss_device(dev);
- u32 wss;
- int r;
-
- if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
- return -ENOENT;
-
- r = kstrtou32(buf, 0, &wss);
- if (r)
- return r;
-
- if (wss > 0xfffff)
- return -EINVAL;
-
- r = dssdev->driver->set_wss(dssdev, wss);
- if (r)
- return r;
-
- return size;
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
- display_enabled_show, display_enabled_store);
-static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
- display_tear_show, display_tear_store);
-static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
- display_timings_show, display_timings_store);
-static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
- display_rotate_show, display_rotate_store);
-static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
- display_mirror_show, display_mirror_store);
-static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
- display_wss_show, display_wss_store);
-
-static struct device_attribute *display_sysfs_attrs[] = {
- &dev_attr_enabled,
- &dev_attr_tear_elim,
- &dev_attr_timings,
- &dev_attr_rotate,
- &dev_attr_mirror,
- &dev_attr_wss,
- NULL
-};
-
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
@@ -320,136 +76,8 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
}
EXPORT_SYMBOL(omapdss_default_get_timings);
-/*
- * Connect dssdev to a manager if the manager is free or if force is specified.
- * Connect all overlays to that manager if they are free or if force is
- * specified.
- */
-static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
-{
- struct omap_dss_output *out;
- struct omap_overlay_manager *mgr;
- int i, r;
-
- out = omapdss_get_output_from_dssdev(dssdev);
-
- WARN_ON(dssdev->output);
- WARN_ON(out->device);
-
- r = omapdss_output_set_device(out, dssdev);
- if (r) {
- DSSERR("failed to connect output to new device\n");
- return r;
- }
-
- mgr = omap_dss_get_overlay_manager(dssdev->channel);
-
- if (mgr->output && !force)
- return 0;
-
- if (mgr->output)
- mgr->unset_output(mgr);
-
- r = mgr->set_output(mgr, out);
- if (r) {
- DSSERR("failed to connect manager to output of new device\n");
-
- /* remove the output-device connection we just made */
- omapdss_output_unset_device(out);
- return r;
- }
-
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
- struct omap_overlay *ovl = omap_dss_get_overlay(i);
-
- if (!ovl->manager || force) {
- if (ovl->manager)
- ovl->unset_manager(ovl);
-
- r = ovl->set_manager(ovl, mgr);
- if (r) {
- DSSERR("failed to set initial overlay\n");
- return r;
- }
- }
- }
-
- return 0;
-}
-
-static void dss_uninit_connections(struct omap_dss_device *dssdev)
-{
- if (dssdev->output) {
- struct omap_overlay_manager *mgr = dssdev->output->manager;
-
- if (mgr)
- mgr->unset_output(mgr);
-
- omapdss_output_unset_device(dssdev->output);
- }
-}
-
-int dss_init_device(struct platform_device *pdev,
- struct omap_dss_device *dssdev)
-{
- struct device_attribute *attr;
- int i, r;
- const char *def_disp_name = dss_get_default_display_name();
- bool force;
-
- force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
- dss_init_connections(dssdev, force);
-
- /* create device sysfs files */
- i = 0;
- while ((attr = display_sysfs_attrs[i++]) != NULL) {
- r = device_create_file(&dssdev->dev, attr);
- if (r) {
- for (i = i - 2; i >= 0; i--) {
- attr = display_sysfs_attrs[i];
- device_remove_file(&dssdev->dev, attr);
- }
-
- dss_uninit_connections(dssdev);
-
- DSSERR("failed to create sysfs file\n");
- return r;
- }
- }
-
- /* create display? sysfs links */
- r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
- dev_name(&dssdev->dev));
- if (r) {
- while ((attr = display_sysfs_attrs[i++]) != NULL)
- device_remove_file(&dssdev->dev, attr);
-
- dss_uninit_connections(dssdev);
-
- DSSERR("failed to create sysfs display link\n");
- return r;
- }
-
- return 0;
-}
-
-void dss_uninit_device(struct platform_device *pdev,
- struct omap_dss_device *dssdev)
-{
- struct device_attribute *attr;
- int i = 0;
-
- sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
-
- while ((attr = display_sysfs_attrs[i++]) != NULL)
- device_remove_file(&dssdev->dev, attr);
-
- dss_uninit_connections(dssdev);
-}
-
static int dss_suspend_device(struct device *dev, void *data)
{
- int r;
struct omap_dss_device *dssdev = to_dss_device(dev);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
@@ -457,15 +85,7 @@ static int dss_suspend_device(struct device *dev, void *data)
return 0;
}
- if (!dssdev->driver->suspend) {
- DSSERR("display '%s' doesn't implement suspend\n",
- dssdev->name);
- return -ENOSYS;
- }
-
- r = dssdev->driver->suspend(dssdev);
- if (r)
- return r;
+ dssdev->driver->disable(dssdev);
dssdev->activate_after_resume = true;
@@ -492,8 +112,8 @@ static int dss_resume_device(struct device *dev, void *data)
int r;
struct omap_dss_device *dssdev = to_dss_device(dev);
- if (dssdev->activate_after_resume && dssdev->driver->resume) {
- r = dssdev->driver->resume(dssdev);
+ if (dssdev->activate_after_resume) {
+ r = dssdev->driver->enable(dssdev);
if (r)
return r;
}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 56748cf8760..4af136a04e5 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -49,34 +49,53 @@ static struct {
struct omap_dss_output output;
} dpi;
-static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
+static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
{
- int dsi_module;
-
- dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
+ /*
+ * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
+ * would also be used for DISPC fclk. Meaning, when the DPI output is
+ * disabled, DISPC clock will be disabled, and TV out will stop.
+ */
+ switch (omapdss_get_version()) {
+ case OMAPDSS_VER_OMAP24xx:
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_OMAP3630:
+ case OMAPDSS_VER_AM35xx:
+ return NULL;
+ default:
+ break;
+ }
- return dsi_get_dsidev_from_id(dsi_module);
+ switch (channel) {
+ case OMAP_DSS_CHANNEL_LCD:
+ return dsi_get_dsidev_from_id(0);
+ case OMAP_DSS_CHANNEL_LCD2:
+ return dsi_get_dsidev_from_id(1);
+ default:
+ return NULL;
+ }
}
-static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
+static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
{
- if (dssdev->clocks.dispc.dispc_fclk_src ==
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
- dssdev->clocks.dispc.dispc_fclk_src ==
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
- dssdev->clocks.dispc.channel.lcd_clk_src ==
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
- dssdev->clocks.dispc.channel.lcd_clk_src ==
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
- return true;
- else
- return false;
+ switch (channel) {
+ case OMAP_DSS_CHANNEL_LCD:
+ return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
+ case OMAP_DSS_CHANNEL_LCD2:
+ return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+ default:
+ /* this shouldn't happen */
+ WARN_ON(1);
+ return OMAP_DSS_CLK_SRC_FCK;
+ }
}
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
unsigned long pck_req, unsigned long *fck, int *lck_div,
int *pck_div)
{
+ struct omap_overlay_manager *mgr = dssdev->output->manager;
struct dsi_clock_info dsi_cinfo;
struct dispc_clock_info dispc_cinfo;
int r;
@@ -90,7 +109,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
if (r)
return r;
- dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
+ dss_select_lcd_clk_source(mgr->id,
+ dpi_get_alt_clk_src(mgr->id));
dpi.mgr_config.clock_info = dispc_cinfo;
@@ -135,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
unsigned long pck;
int r = 0;
- if (dpi_use_dsi_pll(dssdev))
+ if (dpi.dsidev)
r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
&lck_div, &pck_div);
else
@@ -214,7 +234,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_src_sel;
- if (dpi_use_dsi_pll(dssdev)) {
+ if (dpi.dsidev) {
r = dsi_runtime_get(dpi.dsidev);
if (r)
goto err_get_dsi;
@@ -242,10 +262,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
err_mgr_enable:
err_set_mode:
- if (dpi_use_dsi_pll(dssdev))
+ if (dpi.dsidev)
dsi_pll_uninit(dpi.dsidev, true);
err_dsi_pll_init:
- if (dpi_use_dsi_pll(dssdev))
+ if (dpi.dsidev)
dsi_runtime_put(dpi.dsidev);
err_get_dsi:
err_src_sel:
@@ -271,8 +291,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
dss_mgr_disable(mgr);
- if (dpi_use_dsi_pll(dssdev)) {
- dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+ if (dpi.dsidev) {
+ dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
dsi_pll_uninit(dpi.dsidev, true);
dsi_runtime_put(dpi.dsidev);
}
@@ -311,13 +331,13 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
unsigned long pck;
struct dispc_clock_info dispc_cinfo;
- if (dss_mgr_check_timings(mgr, timings))
+ if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
return -EINVAL;
if (timings->pixel_clock == 0)
return -EINVAL;
- if (dpi_use_dsi_pll(dssdev)) {
+ if (dpi.dsidev) {
struct dsi_clock_info dsi_cinfo;
r = dsi_pll_calc_clock_div_pck(dpi.dsidev,
timings->pixel_clock * 1000,
@@ -359,8 +379,32 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
}
EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
+static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
+{
+ int r;
+
+ /* do initial setup with the PLL to see if it is operational */
+
+ r = dsi_runtime_get(dsidev);
+ if (r)
+ return r;
+
+ r = dsi_pll_init(dsidev, 0, 1);
+ if (r) {
+ dsi_runtime_put(dsidev);
+ return r;
+ }
+
+ dsi_pll_uninit(dsidev, true);
+ dsi_runtime_put(dsidev);
+
+ return 0;
+}
+
static int __init dpi_init_display(struct omap_dss_device *dssdev)
{
+ struct platform_device *dsidev;
+
DSSDBG("init_display\n");
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
@@ -377,19 +421,30 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
dpi.vdds_dsi_reg = vdds_dsi;
}
- if (dpi_use_dsi_pll(dssdev)) {
- enum omap_dss_clk_source dispc_fclk_src =
- dssdev->clocks.dispc.dispc_fclk_src;
- dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
+ /*
+ * XXX We shouldn't need dssdev->channel for this. The dsi pll clock
+ * source for DPI is SoC integration detail, not something that should
+ * be configured in the dssdev
+ */
+ dsidev = dpi_get_dsidev(dssdev->channel);
+
+ if (dsidev && dpi_verify_dsi_pll(dsidev)) {
+ dsidev = NULL;
+ DSSWARN("DSI PLL not operational\n");
}
+ if (dsidev)
+ DSSDBG("using DSI PLL for DPI clock\n");
+
+ dpi.dsidev = dsidev;
+
return 0;
}
static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = dss_get_default_display_name();
+ const char *def_disp_name = omapdss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
@@ -438,9 +493,18 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev)
return;
}
+ r = omapdss_output_set_device(&dpi.output, dssdev);
+ if (r) {
+ DSSERR("failed to connect output to new device: %s\n",
+ dssdev->name);
+ dss_put_device(dssdev);
+ return;
+ }
+
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ omapdss_output_unset_device(&dpi.output);
dss_put_device(dssdev);
return;
}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index bee92846cfa..28d41d16b7b 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -45,7 +45,6 @@
#include "dss.h"
#include "dss_features.h"
-/*#define VERBOSE_IRQ*/
#define DSI_CATCH_MISSING_TE
struct dsi_reg { u16 idx; };
@@ -535,42 +534,38 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
}
#endif
+static int verbose_irq;
+
static void print_irq_status(u32 status)
{
if (status == 0)
return;
-#ifndef VERBOSE_IRQ
- if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+ if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0)
return;
-#endif
- printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
-#define PIS(x) \
- if (status & DSI_IRQ_##x) \
- printk(#x " ");
-#ifdef VERBOSE_IRQ
- PIS(VC0);
- PIS(VC1);
- PIS(VC2);
- PIS(VC3);
-#endif
- PIS(WAKEUP);
- PIS(RESYNC);
- PIS(PLL_LOCK);
- PIS(PLL_UNLOCK);
- PIS(PLL_RECALL);
- PIS(COMPLEXIO_ERR);
- PIS(HS_TX_TIMEOUT);
- PIS(LP_RX_TIMEOUT);
- PIS(TE_TRIGGER);
- PIS(ACK_TRIGGER);
- PIS(SYNC_LOST);
- PIS(LDO_POWER_GOOD);
- PIS(TA_TIMEOUT);
+#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : ""
+
+ pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ status,
+ verbose_irq ? PIS(VC0) : "",
+ verbose_irq ? PIS(VC1) : "",
+ verbose_irq ? PIS(VC2) : "",
+ verbose_irq ? PIS(VC3) : "",
+ PIS(WAKEUP),
+ PIS(RESYNC),
+ PIS(PLL_LOCK),
+ PIS(PLL_UNLOCK),
+ PIS(PLL_RECALL),
+ PIS(COMPLEXIO_ERR),
+ PIS(HS_TX_TIMEOUT),
+ PIS(LP_RX_TIMEOUT),
+ PIS(TE_TRIGGER),
+ PIS(ACK_TRIGGER),
+ PIS(SYNC_LOST),
+ PIS(LDO_POWER_GOOD),
+ PIS(TA_TIMEOUT));
#undef PIS
-
- printk("\n");
}
static void print_irq_status_vc(int channel, u32 status)
@@ -578,28 +573,24 @@ static void print_irq_status_vc(int channel, u32 status)
if (status == 0)
return;
-#ifndef VERBOSE_IRQ
- if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+ if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
return;
-#endif
- printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
-#define PIS(x) \
- if (status & DSI_VC_IRQ_##x) \
- printk(#x " ");
- PIS(CS);
- PIS(ECC_CORR);
-#ifdef VERBOSE_IRQ
- PIS(PACKET_SENT);
-#endif
- PIS(FIFO_TX_OVF);
- PIS(FIFO_RX_OVF);
- PIS(BTA);
- PIS(ECC_NO_CORR);
- PIS(FIFO_TX_UDF);
- PIS(PP_BUSY_CHANGE);
+#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : ""
+
+ pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n",
+ channel,
+ status,
+ PIS(CS),
+ PIS(ECC_CORR),
+ PIS(ECC_NO_CORR),
+ verbose_irq ? PIS(PACKET_SENT) : "",
+ PIS(BTA),
+ PIS(FIFO_TX_OVF),
+ PIS(FIFO_RX_OVF),
+ PIS(FIFO_TX_UDF),
+ PIS(PP_BUSY_CHANGE));
#undef PIS
- printk("\n");
}
static void print_irq_status_cio(u32 status)
@@ -607,34 +598,31 @@ static void print_irq_status_cio(u32 status)
if (status == 0)
return;
- printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
-
-#define PIS(x) \
- if (status & DSI_CIO_IRQ_##x) \
- printk(#x " ");
- PIS(ERRSYNCESC1);
- PIS(ERRSYNCESC2);
- PIS(ERRSYNCESC3);
- PIS(ERRESC1);
- PIS(ERRESC2);
- PIS(ERRESC3);
- PIS(ERRCONTROL1);
- PIS(ERRCONTROL2);
- PIS(ERRCONTROL3);
- PIS(STATEULPS1);
- PIS(STATEULPS2);
- PIS(STATEULPS3);
- PIS(ERRCONTENTIONLP0_1);
- PIS(ERRCONTENTIONLP1_1);
- PIS(ERRCONTENTIONLP0_2);
- PIS(ERRCONTENTIONLP1_2);
- PIS(ERRCONTENTIONLP0_3);
- PIS(ERRCONTENTIONLP1_3);
- PIS(ULPSACTIVENOT_ALL0);
- PIS(ULPSACTIVENOT_ALL1);
+#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : ""
+
+ pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ status,
+ PIS(ERRSYNCESC1),
+ PIS(ERRSYNCESC2),
+ PIS(ERRSYNCESC3),
+ PIS(ERRESC1),
+ PIS(ERRESC2),
+ PIS(ERRESC3),
+ PIS(ERRCONTROL1),
+ PIS(ERRCONTROL2),
+ PIS(ERRCONTROL3),
+ PIS(STATEULPS1),
+ PIS(STATEULPS2),
+ PIS(STATEULPS3),
+ PIS(ERRCONTENTIONLP0_1),
+ PIS(ERRCONTENTIONLP1_1),
+ PIS(ERRCONTENTIONLP0_2),
+ PIS(ERRCONTENTIONLP1_2),
+ PIS(ERRCONTENTIONLP0_3),
+ PIS(ERRCONTENTIONLP1_3),
+ PIS(ULPSACTIVENOT_ALL0),
+ PIS(ULPSACTIVENOT_ALL1));
#undef PIS
-
- printk("\n");
}
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -1116,28 +1104,16 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
}
}
-#ifdef DEBUG
static void _dsi_print_reset_status(struct platform_device *dsidev)
{
u32 l;
int b0, b1, b2;
- if (!dss_debug)
- return;
-
/* A dummy read using the SCP interface to any DSIPHY register is
* required after DSIPHY reset to complete the reset of the DSI complex
* I/O. */
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
- printk(KERN_DEBUG "DSI resets: ");
-
- l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
- printk("PLL (%d) ", FLD_GET(l, 0, 0));
-
- l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
- printk("CIO (%d) ", FLD_GET(l, 29, 29));
-
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
b0 = 28;
b1 = 27;
@@ -1148,18 +1124,21 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
b2 = 26;
}
- l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
- printk("PHY (%x%x%x, %d, %d, %d)\n",
- FLD_GET(l, b0, b0),
- FLD_GET(l, b1, b1),
- FLD_GET(l, b2, b2),
- FLD_GET(l, 29, 29),
- FLD_GET(l, 30, 30),
- FLD_GET(l, 31, 31));
+#define DSI_FLD_GET(fld, start, end)\
+ FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end)
+
+ pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n",
+ DSI_FLD_GET(PLL_STATUS, 0, 0),
+ DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29),
+ DSI_FLD_GET(DSIPHY_CFG5, b0, b0),
+ DSI_FLD_GET(DSIPHY_CFG5, b1, b1),
+ DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
+ DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
+ DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
+ DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
+
+#undef DSI_FLD_GET
}
-#else
-#define _dsi_print_reset_status(x)
-#endif
static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
{
@@ -1407,6 +1386,11 @@ retry:
cur.dsi_pll_hsdiv_dispc_clk =
cur.clkin4ddr / cur.regm_dispc;
+ if (cur.regm_dispc > 1 &&
+ cur.regm_dispc % 2 != 0 &&
+ req_pck >= 1000000)
+ continue;
+
/* this will narrow down the search a bit,
* but still give pixclocks below what was
* requested */
@@ -1621,7 +1605,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
u8 regn_start, regn_end, regm_start, regm_end;
u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
- DSSDBGF();
+ DSSDBG("DSI PLL clock config starts");
dsi->current_cinfo.clkin = cinfo->clkin;
dsi->current_cinfo.fint = cinfo->fint;
@@ -1757,11 +1741,21 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
DSSDBG("PLL init\n");
+ /*
+ * It seems that on many OMAPs we need to enable both to have a
+ * functional HSDivider.
+ */
+ enable_hsclk = enable_hsdiv = true;
+
if (dsi->vdds_dsi_reg == NULL) {
struct regulator *vdds_dsi;
vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
+ /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+ if (IS_ERR(vdds_dsi))
+ vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
if (IS_ERR(vdds_dsi)) {
DSSERR("can't get VDDS_DSI regulator\n");
return PTR_ERR(vdds_dsi);
@@ -2440,7 +2434,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
int r;
u32 l;
- DSSDBGF();
+ DSSDBG("DSI CIO init starts");
r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
if (r)
@@ -2791,7 +2785,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
{
u32 r;
- DSSDBGF("%d", channel);
+ DSSDBG("Initial config of virtual channel %d", channel);
r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
@@ -2823,7 +2817,7 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
if (dsi->vc[channel].source == source)
return 0;
- DSSDBGF("%d", channel);
+ DSSDBG("Source config of virtual channel %d", channel);
dsi_sync_vc(dsidev, channel);
@@ -3581,7 +3575,7 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
int r, i;
unsigned mask;
- DSSDBGF();
+ DSSDBG("Entering ULPS");
WARN_ON(!dsi_bus_is_locked(dsidev));
@@ -4285,7 +4279,7 @@ int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
unsigned long pck;
int r;
- DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
+ DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
mutex_lock(&dsi->lock);
@@ -4541,7 +4535,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
}
-static void dsi_framedone_irq_callback(void *data, u32 mask)
+static void dsi_framedone_irq_callback(void *data)
{
struct platform_device *dsidev = (struct platform_device *) data;
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4615,7 +4609,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_overlay_manager *mgr = dssdev->output->manager;
int r;
- u32 irq = 0;
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
dsi->timings.hsw = 1;
@@ -4625,12 +4618,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
dsi->timings.vfp = 0;
dsi->timings.vbp = 0;
- irq = dispc_mgr_get_framedone_irq(mgr->id);
-
- r = omap_dispc_register_isr(dsi_framedone_irq_callback,
- (void *) dsidev, irq);
+ r = dss_mgr_register_framedone_handler(mgr,
+ dsi_framedone_irq_callback, dsidev);
if (r) {
- DSSERR("can't get FRAMEDONE irq\n");
+ DSSERR("can't register FRAMEDONE handler\n");
goto err;
}
@@ -4668,8 +4659,8 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
return 0;
err1:
if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
- omap_dispc_unregister_isr(dsi_framedone_irq_callback,
- (void *) dsidev, irq);
+ dss_mgr_unregister_framedone_handler(mgr,
+ dsi_framedone_irq_callback, dsidev);
err:
return r;
}
@@ -4680,14 +4671,9 @@ static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_overlay_manager *mgr = dssdev->output->manager;
- if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
- u32 irq;
-
- irq = dispc_mgr_get_framedone_irq(mgr->id);
-
- omap_dispc_unregister_isr(dsi_framedone_irq_callback,
- (void *) dsidev, irq);
- }
+ if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
+ dss_mgr_unregister_framedone_handler(mgr,
+ dsi_framedone_irq_callback, dsidev);
}
static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4730,7 +4716,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
if (r)
goto err1;
- dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
dss_select_lcd_clk_source(mgr->id,
dssdev->clocks.dispc.channel.lcd_clk_src);
@@ -4765,7 +4750,6 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
err3:
dsi_cio_uninit(dsidev);
err2:
- dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
@@ -4792,7 +4776,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dsi_vc_enable(dsidev, 2, 0);
dsi_vc_enable(dsidev, 3, 0);
- dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
dsi_cio_uninit(dsidev);
@@ -4981,6 +4964,10 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
+ /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
+ if (IS_ERR(vdds_dsi))
+ vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
+
if (IS_ERR(vdds_dsi)) {
DSSERR("can't get VDDS_DSI regulator\n");
return PTR_ERR(vdds_dsi);
@@ -5121,7 +5108,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
- const char *def_disp_name = dss_get_default_display_name();
+ const char *def_disp_name = omapdss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
@@ -5151,6 +5138,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p
static void __init dsi_probe_pdata(struct platform_device *dsidev)
{
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
int r;
@@ -5173,9 +5161,18 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
return;
}
+ r = omapdss_output_set_device(&dsi->output, dssdev);
+ if (r) {
+ DSSERR("failed to connect output to new device: %s\n",
+ dssdev->name);
+ dss_put_device(dssdev);
+ return;
+ }
+
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ omapdss_output_unset_device(&dsi->output);
dss_put_device(dssdev);
return;
}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 5f6eea801b0..054c2a22b3f 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -32,11 +32,10 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/gfp.h>
+#include <linux/sizes.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
-
#include "dss.h"
#include "dss_features.h"
@@ -78,6 +77,7 @@ static struct {
struct clk *dpll4_m4_ck;
struct clk *dss_clk;
+ unsigned long dss_clk_rate;
unsigned long cache_req_pck;
unsigned long cache_prate;
@@ -98,6 +98,8 @@ static const char * const dss_generic_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
+ [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
+ [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
};
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -153,6 +155,21 @@ static void dss_restore_context(void)
#undef SR
#undef RR
+int dss_get_ctx_loss_count(void)
+{
+ struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
+ int cnt;
+
+ if (!board_data->get_context_loss_count)
+ return -ENOENT;
+
+ cnt = board_data->get_context_loss_count(&dss.pdev->dev);
+
+ WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
+
+ return cnt;
+}
+
void dss_sdi_init(int datapairs)
{
u32 l;
@@ -303,7 +320,7 @@ static void dss_dump_regs(struct seq_file *s)
#undef DUMPREG
}
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
+static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
{
struct platform_device *dsidev;
int b;
@@ -374,8 +391,10 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
struct platform_device *dsidev;
int b, ix, pos;
- if (!dss_has_feature(FEAT_LCD_CLK_SRC))
+ if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
+ dss_select_dispc_clk_source(clk_src);
return;
+ }
switch (clk_src) {
case OMAP_DSS_CLK_SRC_FCK:
@@ -431,6 +450,29 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
}
}
+/* calculate clock rates using dividers in cinfo */
+int dss_calc_clock_rates(struct dss_clock_info *cinfo)
+{
+ if (dss.dpll4_m4_ck) {
+ unsigned long prate;
+
+ if (cinfo->fck_div > dss.feat->fck_div_max ||
+ cinfo->fck_div == 0)
+ return -EINVAL;
+
+ prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
+
+ cinfo->fck = prate / cinfo->fck_div *
+ dss.feat->dss_fck_multiplier;
+ } else {
+ if (cinfo->fck_div != 0)
+ return -EINVAL;
+ cinfo->fck = clk_get_rate(dss.dss_clk);
+ }
+
+ return 0;
+}
+
int dss_set_clock_div(struct dss_clock_info *cinfo)
{
if (dss.dpll4_m4_ck) {
@@ -448,6 +490,10 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
return -EINVAL;
}
+ dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
+ WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch");
+
DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
return 0;
@@ -461,6 +507,41 @@ unsigned long dss_get_dpll4_rate(void)
return 0;
}
+unsigned long dss_get_dispc_clk_rate(void)
+{
+ return dss.dss_clk_rate;
+}
+
+static int dss_setup_default_clock(void)
+{
+ unsigned long max_dss_fck, prate;
+ unsigned fck_div;
+ struct dss_clock_info dss_cinfo = { 0 };
+ int r;
+
+ if (dss.dpll4_m4_ck == NULL)
+ return 0;
+
+ max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+
+ prate = dss_get_dpll4_rate();
+
+ fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
+ max_dss_fck);
+
+ dss_cinfo.fck_div = fck_div;
+
+ r = dss_calc_clock_rates(&dss_cinfo);
+ if (r)
+ return r;
+
+ r = dss_set_clock_div(&dss_cinfo);
+ if (r)
+ return r;
+
+ return 0;
+}
+
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
struct dispc_clock_info *dispc_cinfo)
{
@@ -750,7 +831,7 @@ static void dss_runtime_put(void)
}
/* DEBUGFS */
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
void dss_debug_dump_clocks(struct seq_file *s)
{
dss_dump_clocks(s);
@@ -796,29 +877,45 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
.dpi_select_source = &dss_dpi_select_source_omap5,
};
-static int __init dss_init_features(struct device *dev)
+static int __init dss_init_features(struct platform_device *pdev)
{
const struct dss_features *src;
struct dss_features *dst;
- dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
- dev_err(dev, "Failed to allocate local DSS Features\n");
+ dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
return -ENOMEM;
}
- if (cpu_is_omap24xx())
+ switch (omapdss_get_version()) {
+ case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dss_feats;
- else if (cpu_is_omap3630())
- src = &omap3630_dss_feats;
- else if (cpu_is_omap34xx())
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_AM35xx:
src = &omap34xx_dss_feats;
- else if (cpu_is_omap44xx())
+ break;
+
+ case OMAPDSS_VER_OMAP3630:
+ src = &omap3630_dss_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
src = &omap44xx_dss_feats;
- else if (soc_is_omap54xx())
+ break;
+
+ case OMAPDSS_VER_OMAP5:
src = &omap54xx_dss_feats;
- else
+ break;
+
+ default:
return -ENODEV;
+ }
memcpy(dst, src, sizeof(*dst));
dss.feat = dst;
@@ -835,7 +932,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
dss.pdev = pdev;
- r = dss_init_features(&dss.pdev->dev);
+ r = dss_init_features(dss.pdev);
if (r)
return r;
@@ -856,15 +953,23 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
if (r)
return r;
+ r = dss_setup_default_clock();
+ if (r)
+ goto err_setup_clocks;
+
pm_runtime_enable(&pdev->dev);
r = dss_runtime_get();
if (r)
goto err_runtime_get;
+ dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
+
/* Select DPLL */
REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+ dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+
#ifdef CONFIG_OMAP2_DSS_VENC
REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
@@ -888,6 +993,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
err_runtime_get:
pm_runtime_disable(&pdev->dev);
+err_setup_clocks:
dss_put_clocks();
return r;
}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 6728892f9da..610c8e563da 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -23,44 +23,20 @@
#ifndef __OMAP2_DSS_H
#define __OMAP2_DSS_H
-#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
-#define DEBUG
-#endif
+#include <linux/interrupt.h>
-#ifdef DEBUG
-extern bool dss_debug;
-#ifdef DSS_SUBSYS_NAME
-#define DSSDBG(format, ...) \
- if (dss_debug) \
- printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
- ## __VA_ARGS__)
-#else
-#define DSSDBG(format, ...) \
- if (dss_debug) \
- printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
+#ifdef pr_fmt
+#undef pr_fmt
#endif
#ifdef DSS_SUBSYS_NAME
-#define DSSDBGF(format, ...) \
- if (dss_debug) \
- printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
- ": %s(" format ")\n", \
- __func__, \
- ## __VA_ARGS__)
+#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt
#else
-#define DSSDBGF(format, ...) \
- if (dss_debug) \
- printk(KERN_DEBUG "omapdss: " \
- ": %s(" format ")\n", \
- __func__, \
- ## __VA_ARGS__)
-#endif
-
-#else /* DEBUG */
-#define DSSDBG(format, ...)
-#define DSSDBGF(format, ...)
+#define pr_fmt(fmt) fmt
#endif
+#define DSSDBG(format, ...) \
+ pr_debug(format, ## __VA_ARGS__)
#ifdef DSS_SUBSYS_NAME
#define DSSERR(format, ...) \
@@ -186,11 +162,10 @@ struct seq_file;
struct platform_device;
/* core */
-const char *dss_get_default_display_name(void);
+struct platform_device *dss_get_core_pdev(void);
struct bus_type *dss_get_bus(void);
struct regulator *dss_get_vdds_dsi(void);
struct regulator *dss_get_vdds_sdi(void);
-int dss_get_ctx_loss_count(struct device *dev);
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
@@ -204,55 +179,18 @@ void dss_put_device(struct omap_dss_device *dssdev);
void dss_copy_device_pdata(struct omap_dss_device *dst,
const struct omap_dss_device *src);
-/* apply */
-void dss_apply_init(void);
-int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
-void dss_mgr_start_update(struct omap_overlay_manager *mgr);
-int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
-
-int dss_mgr_enable(struct omap_overlay_manager *mgr);
-void dss_mgr_disable(struct omap_overlay_manager *mgr);
-int dss_mgr_set_info(struct omap_overlay_manager *mgr,
- struct omap_overlay_manager_info *info);
-void dss_mgr_get_info(struct omap_overlay_manager *mgr,
- struct omap_overlay_manager_info *info);
-int dss_mgr_set_device(struct omap_overlay_manager *mgr,
- struct omap_dss_device *dssdev);
-int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
-int dss_mgr_set_output(struct omap_overlay_manager *mgr,
- struct omap_dss_output *output);
-int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
-void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
- const struct omap_video_timings *timings);
-void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
- const struct dss_lcd_mgr_config *config);
-const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
-
-bool dss_ovl_is_enabled(struct omap_overlay *ovl);
-int dss_ovl_enable(struct omap_overlay *ovl);
-int dss_ovl_disable(struct omap_overlay *ovl);
-int dss_ovl_set_info(struct omap_overlay *ovl,
- struct omap_overlay_info *info);
-void dss_ovl_get_info(struct omap_overlay *ovl,
- struct omap_overlay_info *info);
-int dss_ovl_set_manager(struct omap_overlay *ovl,
- struct omap_overlay_manager *mgr);
-int dss_ovl_unset_manager(struct omap_overlay *ovl);
-
/* output */
void dss_register_output(struct omap_dss_output *out);
void dss_unregister_output(struct omap_dss_output *out);
-struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
/* display */
int dss_suspend_all_devices(void);
int dss_resume_all_devices(void);
void dss_disable_all_devices(void);
-int dss_init_device(struct platform_device *pdev,
+int display_init_sysfs(struct platform_device *pdev,
struct omap_dss_device *dssdev);
-void dss_uninit_device(struct platform_device *pdev,
+void display_uninit_sysfs(struct platform_device *pdev,
struct omap_dss_device *dssdev);
/* manager */
@@ -299,21 +237,23 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
int dss_init_platform_driver(void) __init;
void dss_uninit_platform_driver(void);
+unsigned long dss_get_dispc_clk_rate(void);
int dss_dpi_select_source(enum omap_channel channel);
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
-#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
void dss_debug_dump_clocks(struct seq_file *s);
#endif
+int dss_get_ctx_loss_count(void);
+
void dss_sdi_init(int datapairs);
int dss_sdi_enable(void);
void dss_sdi_disable(void);
-void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
void dss_select_dsi_clk_source(int dsi_module,
enum omap_dss_clk_source clk_src);
void dss_select_lcd_clk_source(enum omap_channel channel,
@@ -326,6 +266,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
void dss_set_dac_pwrdn_bgz(bool enable);
unsigned long dss_get_dpll4_rate(void);
+int dss_calc_clock_rates(struct dss_clock_info *cinfo);
int dss_set_clock_div(struct dss_clock_info *cinfo);
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
struct dispc_clock_info *dispc_cinfo);
@@ -413,8 +354,6 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
}
static inline struct platform_device *dsi_get_dsidev_from_id(int module)
{
- WARN("%s: DSI not compiled in, returning platform device as NULL\n",
- __func__);
return NULL;
}
#endif
@@ -427,15 +366,10 @@ void dpi_uninit_platform_driver(void) __exit;
int dispc_init_platform_driver(void) __init;
void dispc_uninit_platform_driver(void) __exit;
void dispc_dump_clocks(struct seq_file *s);
-void dispc_irq_handler(void);
-
-int dispc_runtime_get(void);
-void dispc_runtime_put(void);
void dispc_enable_sidle(void);
void dispc_disable_sidle(void);
-void dispc_lcd_enable_signal_polarity(bool act_high);
void dispc_lcd_enable_signal(bool enable);
void dispc_pck_free_enable(bool enable);
void dispc_enable_fifomerge(bool enable);
@@ -455,36 +389,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
bool manual_update);
-int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
- bool replication, const struct omap_video_timings *mgr_timings,
- bool mem_to_mem);
-int dispc_ovl_enable(enum omap_plane plane, bool enable);
-void dispc_ovl_set_channel_out(enum omap_plane plane,
- enum omap_channel channel);
-
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
-u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
-u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
-bool dispc_mgr_go_busy(enum omap_channel channel);
-void dispc_mgr_go(enum omap_channel channel);
-bool dispc_mgr_is_enabled(enum omap_channel channel);
-void dispc_mgr_enable(enum omap_channel channel, bool enable);
-bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel);
-void dispc_mgr_set_timings(enum omap_channel channel,
- struct omap_video_timings *timings);
+
unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
unsigned long dispc_core_clk_rate(void);
void dispc_mgr_set_clock_div(enum omap_channel channel,
- struct dispc_clock_info *cinfo);
+ const struct dispc_clock_info *cinfo);
int dispc_mgr_get_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
-void dispc_mgr_setup(enum omap_channel channel,
- struct omap_overlay_manager_info *info);
u32 dispc_wb_get_framedone_irq(void);
bool dispc_wb_go_busy(void);
@@ -536,6 +448,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
#endif
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index acbc1e1efba..18688c12e30 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -18,12 +18,12 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
#include "dss.h"
#include "dss_features.h"
@@ -430,8 +430,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
* scaler cannot scale a image with width more than 768.
*/
[FEAT_PARAM_LINEWIDTH] = { 1, 768 },
- [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
- [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const struct dss_param_range omap3_dss_param_range[] = {
@@ -446,8 +444,6 @@ static const struct dss_param_range omap3_dss_param_range[] = {
[FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
- [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
- [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const struct dss_param_range omap4_dss_param_range[] = {
@@ -462,8 +458,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
- [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
- [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const struct dss_param_range omap5_dss_param_range[] = {
@@ -478,8 +472,6 @@ static const struct dss_param_range omap5_dss_param_range[] = {
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
- [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
- [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
};
static const enum dss_feat_id omap2_dss_feat_list[] = {
@@ -821,14 +813,25 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.audio_start = ti_hdmi_4xxx_audio_start,
.audio_stop = ti_hdmi_4xxx_audio_stop,
.audio_config = ti_hdmi_4xxx_audio_config,
+ .audio_get_dma_port = ti_hdmi_4xxx_audio_get_dma_port,
#endif
};
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+ enum omapdss_version version)
{
- if (cpu_is_omap44xx())
+ switch (version) {
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
ip_data->ops = &omap4_hdmi_functions;
+ break;
+ default:
+ ip_data->ops = NULL;
+ }
+
+ WARN_ON(ip_data->ops == NULL);
}
#endif
@@ -837,11 +840,13 @@ int dss_feat_get_num_mgrs(void)
{
return omap_current_dss_features->num_mgrs;
}
+EXPORT_SYMBOL(dss_feat_get_num_mgrs);
int dss_feat_get_num_ovls(void)
{
return omap_current_dss_features->num_ovls;
}
+EXPORT_SYMBOL(dss_feat_get_num_ovls);
int dss_feat_get_num_wbs(void)
{
@@ -862,16 +867,19 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
{
return omap_current_dss_features->supported_displays[channel];
}
+EXPORT_SYMBOL(dss_feat_get_supported_displays);
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
{
return omap_current_dss_features->supported_outputs[channel];
}
+EXPORT_SYMBOL(dss_feat_get_supported_outputs);
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
{
return omap_current_dss_features->supported_color_modes[plane];
}
+EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
{
@@ -929,29 +937,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
return omap_current_dss_features->supported_rotation_types & rot_type;
}
-void dss_features_init(void)
+void dss_features_init(enum omapdss_version version)
{
- if (cpu_is_omap24xx())
+ switch (version) {
+ case OMAPDSS_VER_OMAP24xx:
omap_current_dss_features = &omap2_dss_features;
- else if (cpu_is_omap3630())
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ omap_current_dss_features = &omap3430_dss_features;
+ break;
+
+ case OMAPDSS_VER_OMAP3630:
omap_current_dss_features = &omap3630_dss_features;
- else if (cpu_is_omap34xx()) {
- if (soc_is_am35xx()) {
- omap_current_dss_features = &am35xx_dss_features;
- } else {
- omap_current_dss_features = &omap3430_dss_features;
- }
- }
- else if (omap_rev() == OMAP4430_REV_ES1_0)
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
omap_current_dss_features = &omap4430_es1_0_dss_features;
- else if (omap_rev() == OMAP4430_REV_ES2_0 ||
- omap_rev() == OMAP4430_REV_ES2_1 ||
- omap_rev() == OMAP4430_REV_ES2_2)
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES2:
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
- else if (cpu_is_omap44xx())
+ break;
+
+ case OMAPDSS_VER_OMAP4:
omap_current_dss_features = &omap4_dss_features;
- else if (soc_is_omap54xx())
+ break;
+
+ case OMAPDSS_VER_OMAP5:
omap_current_dss_features = &omap5_dss_features;
- else
+ break;
+
+ case OMAPDSS_VER_AM35xx:
+ omap_current_dss_features = &am35xx_dss_features;
+ break;
+
+ default:
DSSWARN("Unsupported OMAP version");
+ break;
+ }
}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 9218113b5e8..489b9bec4a6 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -98,19 +98,12 @@ enum dss_range_param {
FEAT_PARAM_DSI_FCK,
FEAT_PARAM_DOWNSCALE,
FEAT_PARAM_LINEWIDTH,
- FEAT_PARAM_MGR_WIDTH,
- FEAT_PARAM_MGR_HEIGHT,
};
/* DSS Feature Functions */
-int dss_feat_get_num_mgrs(void);
-int dss_feat_get_num_ovls(void);
int dss_feat_get_num_wbs(void);
unsigned long dss_feat_get_param_min(enum dss_range_param param);
unsigned long dss_feat_get_param_max(enum dss_range_param param);
-enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
-enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
-enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode);
@@ -123,8 +116,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
-void dss_features_init(void);
+void dss_features_init(enum omapdss_version version);
#if defined(CONFIG_OMAP4_DSS_HDMI)
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+ enum omapdss_version version);
#endif
#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 8c9b8b3b7f7..769d0828581 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -60,6 +60,7 @@
static struct {
struct mutex lock;
struct platform_device *pdev;
+
struct hdmi_ip_data ip_data;
struct clk *sys_clk;
@@ -295,6 +296,12 @@ static const struct hdmi_config vesa_timings[] = {
false, },
{ 0x55, HDMI_DVI },
},
+ {
+ { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
+ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
+ false, },
+ { 0x44, HDMI_DVI },
+ },
};
static int hdmi_runtime_get(void)
@@ -333,13 +340,17 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
DSSDBG("init_display\n");
- dss_init_hdmi_ip_ops(&hdmi.ip_data);
+ dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version());
if (hdmi.vdda_hdmi_dac_reg == NULL) {
struct regulator *reg;
reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
+ /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */
+ if (IS_ERR(reg))
+ reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
+
if (IS_ERR(reg)) {
DSSERR("can't get VDDA_HDMI_DAC regulator\n");
return PTR_ERR(reg);
@@ -355,7 +366,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
return 0;
}
-static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
+static void hdmi_uninit_display(struct omap_dss_device *dssdev)
{
DSSDBG("uninit_display\n");
@@ -398,7 +409,8 @@ static bool hdmi_timings_compare(struct omap_video_timings *timing1,
{
int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
- if ((timing2->pixel_clock == timing1->pixel_clock) &&
+ if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) ==
+ DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) &&
(timing2->x_res == timing1->x_res) &&
(timing2->y_res == timing1->y_res)) {
@@ -500,12 +512,9 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
}
-static int hdmi_power_on(struct omap_dss_device *dssdev)
+static int hdmi_power_on_core(struct omap_dss_device *dssdev)
{
int r;
- struct omap_video_timings *p;
- struct omap_overlay_manager *mgr = dssdev->output->manager;
- unsigned long phy;
gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
gpio_set_value(hdmi.ls_oe_gpio, 1);
@@ -521,6 +530,38 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
if (r)
goto err_runtime_get;
+ /* Make selection of HDMI in DSS */
+ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
+
+ return 0;
+
+err_runtime_get:
+ regulator_disable(hdmi.vdda_hdmi_dac_reg);
+err_vdac_enable:
+ gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+ gpio_set_value(hdmi.ls_oe_gpio, 0);
+ return r;
+}
+
+static void hdmi_power_off_core(struct omap_dss_device *dssdev)
+{
+ hdmi_runtime_put();
+ regulator_disable(hdmi.vdda_hdmi_dac_reg);
+ gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
+ gpio_set_value(hdmi.ls_oe_gpio, 0);
+}
+
+static int hdmi_power_on_full(struct omap_dss_device *dssdev)
+{
+ int r;
+ struct omap_video_timings *p;
+ struct omap_overlay_manager *mgr = dssdev->output->manager;
+ unsigned long phy;
+
+ r = hdmi_power_on_core(dssdev);
+ if (r)
+ return r;
+
dss_mgr_disable(mgr);
p = &hdmi.ip_data.cfg.timings;
@@ -548,17 +589,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
- /* Make selection of HDMI in DSS */
- dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
-
- /* Select the dispc clock source as PRCM clock, to ensure that it is not
- * DSI PLL source as the clock selected by DSI PLL might not be
- * sufficient for the resolution selected / that can be changed
- * dynamically by user. This can be moved to single location , say
- * Boardfile.
- */
- dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
-
/* bypass TV gamma table */
dispc_enable_gamma_table(0);
@@ -582,16 +612,11 @@ err_vid_enable:
err_phy_enable:
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
err_pll_enable:
- hdmi_runtime_put();
-err_runtime_get:
- regulator_disable(hdmi.vdda_hdmi_dac_reg);
-err_vdac_enable:
- gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
- gpio_set_value(hdmi.ls_oe_gpio, 0);
+ hdmi_power_off_core(dssdev);
return -EIO;
}
-static void hdmi_power_off(struct omap_dss_device *dssdev)
+static void hdmi_power_off_full(struct omap_dss_device *dssdev)
{
struct omap_overlay_manager *mgr = dssdev->output->manager;
@@ -600,12 +625,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
- hdmi_runtime_put();
-
- regulator_disable(hdmi.vdda_hdmi_dac_reg);
- gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
- gpio_set_value(hdmi.ls_oe_gpio, 0);
+ hdmi_power_off_core(dssdev);
}
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -715,7 +736,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
goto err0;
}
- r = hdmi_power_on(dssdev);
+ r = hdmi_power_on_full(dssdev);
if (r) {
DSSERR("failed to power on device\n");
goto err1;
@@ -737,13 +758,48 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
mutex_lock(&hdmi.lock);
- hdmi_power_off(dssdev);
+ hdmi_power_off_full(dssdev);
omap_dss_stop_device(dssdev);
mutex_unlock(&hdmi.lock);
}
+int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ DSSDBG("ENTER omapdss_hdmi_core_enable\n");
+
+ mutex_lock(&hdmi.lock);
+
+ hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
+
+ r = hdmi_power_on_core(dssdev);
+ if (r) {
+ DSSERR("failed to power on device\n");
+ goto err0;
+ }
+
+ mutex_unlock(&hdmi.lock);
+ return 0;
+
+err0:
+ mutex_unlock(&hdmi.lock);
+ return r;
+}
+
+void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev)
+{
+ DSSDBG("Enter omapdss_hdmi_core_disable\n");
+
+ mutex_lock(&hdmi.lock);
+
+ hdmi_power_off_core(dssdev);
+
+ mutex_unlock(&hdmi.lock);
+}
+
static int hdmi_get_clocks(struct platform_device *pdev)
{
struct clk *clk;
@@ -912,7 +968,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = dss_get_default_display_name();
+ const char *def_disp_name = omapdss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
@@ -970,9 +1026,19 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
return;
}
+ r = omapdss_output_set_device(&hdmi.output, dssdev);
+ if (r) {
+ DSSERR("failed to connect output to new device: %s\n",
+ dssdev->name);
+ dss_put_device(dssdev);
+ return;
+ }
+
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ omapdss_output_unset_device(&hdmi.output);
+ hdmi_uninit_display(dssdev);
dss_put_device(dssdev);
return;
}
@@ -999,22 +1065,22 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
/* HDMI HW IP initialisation */
static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
{
- struct resource *hdmi_mem;
+ struct resource *res;
int r;
hdmi.pdev = pdev;
mutex_init(&hdmi.lock);
+ mutex_init(&hdmi.ip_data.lock);
- hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
- if (!hdmi_mem) {
+ res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
+ if (!res) {
DSSERR("can't get IORESOURCE_MEM HDMI\n");
return -EINVAL;
}
/* Base address taken from platform */
- hdmi.ip_data.base_wp = ioremap(hdmi_mem->start,
- resource_size(hdmi_mem));
+ hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res);
if (!hdmi.ip_data.base_wp) {
DSSERR("can't ioremap WP\n");
return -ENOMEM;
@@ -1022,7 +1088,7 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
r = hdmi_get_clocks(pdev);
if (r) {
- iounmap(hdmi.ip_data.base_wp);
+ DSSERR("can't get clocks\n");
return r;
}
@@ -1033,9 +1099,11 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
hdmi.ip_data.phy_offset = HDMI_PHY;
- mutex_init(&hdmi.ip_data.lock);
-
- hdmi_panel_init();
+ r = hdmi_panel_init();
+ if (r) {
+ DSSERR("can't init panel\n");
+ goto err_panel_init;
+ }
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
@@ -1044,6 +1112,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi_probe_pdata(pdev);
return 0;
+
+err_panel_init:
+ hdmi_put_clocks();
+ return r;
}
static int __exit hdmi_remove_child(struct device *dev, void *data)
@@ -1067,8 +1139,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
hdmi_put_clocks();
- iounmap(hdmi.ip_data.base_wp);
-
return 0;
}
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 69fb115bab3..dfb8eda81b6 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -280,58 +280,6 @@ static void hdmi_panel_disable(struct omap_dss_device *dssdev)
mutex_unlock(&hdmi.lock);
}
-static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
-{
- int r = 0;
-
- mutex_lock(&hdmi.lock);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
- r = -EINVAL;
- goto err;
- }
-
- /*
- * TODO: notify audio users that the display was suspended. For now,
- * disable audio locally to not break our audio state machine.
- */
- hdmi_panel_audio_disable(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
- omapdss_hdmi_display_disable(dssdev);
-
-err:
- mutex_unlock(&hdmi.lock);
-
- return r;
-}
-
-static int hdmi_panel_resume(struct omap_dss_device *dssdev)
-{
- int r = 0;
-
- mutex_lock(&hdmi.lock);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
- r = -EINVAL;
- goto err;
- }
-
- r = omapdss_hdmi_display_enable(dssdev);
- if (r) {
- DSSERR("failed to power on\n");
- goto err;
- }
- /* TODO: notify audio users that the panel resumed. */
-
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-err:
- mutex_unlock(&hdmi.lock);
-
- return r;
-}
-
static void hdmi_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -379,20 +327,22 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
{
int r;
+ bool need_enable;
mutex_lock(&hdmi.lock);
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
- r = omapdss_hdmi_display_enable(dssdev);
+ need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+ if (need_enable) {
+ r = omapdss_hdmi_core_enable(dssdev);
if (r)
goto err;
}
r = omapdss_hdmi_read_edid(buf, len);
- if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
- dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
- omapdss_hdmi_display_disable(dssdev);
+ if (need_enable)
+ omapdss_hdmi_core_disable(dssdev);
err:
mutex_unlock(&hdmi.lock);
@@ -402,20 +352,22 @@ err:
static bool hdmi_detect(struct omap_dss_device *dssdev)
{
int r;
+ bool need_enable;
mutex_lock(&hdmi.lock);
- if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
- r = omapdss_hdmi_display_enable(dssdev);
+ need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
+
+ if (need_enable) {
+ r = omapdss_hdmi_core_enable(dssdev);
if (r)
goto err;
}
r = omapdss_hdmi_detect();
- if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
- dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
- omapdss_hdmi_display_disable(dssdev);
+ if (need_enable)
+ omapdss_hdmi_core_disable(dssdev);
err:
mutex_unlock(&hdmi.lock);
@@ -427,8 +379,6 @@ static struct omap_dss_driver hdmi_driver = {
.remove = hdmi_panel_remove,
.enable = hdmi_panel_enable,
.disable = hdmi_panel_disable,
- .suspend = hdmi_panel_suspend,
- .resume = hdmi_panel_resume,
.get_timings = hdmi_get_timings,
.set_timings = hdmi_set_timings,
.check_timings = hdmi_check_timings,
@@ -454,9 +404,7 @@ int hdmi_panel_init(void)
spin_lock_init(&hdmi.audio_lock);
#endif
- omap_dss_register_driver(&hdmi_driver);
-
- return 0;
+ return omap_dss_register_driver(&hdmi_driver);
}
void hdmi_panel_exit(void)
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index c54d2f620ce..2551eaa14c4 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -36,36 +36,6 @@
static int num_managers;
static struct omap_overlay_manager *managers;
-static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
-{
- return mgr->output ? mgr->output->device : NULL;
-}
-
-static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
-{
- unsigned long timeout = msecs_to_jiffies(500);
- struct omap_dss_device *dssdev = mgr->get_device(mgr);
- u32 irq;
- int r;
-
- r = dispc_runtime_get();
- if (r)
- return r;
-
- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
- irq = DISPC_IRQ_EVSYNC_ODD;
- else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
- irq = DISPC_IRQ_EVSYNC_EVEN;
- else
- irq = dispc_mgr_get_vsync_irq(mgr->id);
-
- r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
-
- dispc_runtime_put();
-
- return r;
-}
-
int dss_init_overlay_managers(struct platform_device *pdev)
{
int i, r;
@@ -99,15 +69,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
break;
}
- mgr->set_output = &dss_mgr_set_output;
- mgr->unset_output = &dss_mgr_unset_output;
- mgr->apply = &omap_dss_mgr_apply;
- mgr->set_manager_info = &dss_mgr_set_info;
- mgr->get_manager_info = &dss_mgr_get_info;
- mgr->wait_for_go = &dss_mgr_wait_for_go;
- mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
- mgr->get_device = &dss_mgr_get_device;
-
mgr->caps = 0;
mgr->supported_displays =
dss_feat_get_supported_displays(mgr->id);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
index 813f26682b7..79dea1a1a73 100644
--- a/drivers/video/omap2/dss/output.c
+++ b/drivers/video/omap2/dss/output.c
@@ -114,35 +114,67 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
return NULL;
}
-struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
+static const struct dss_mgr_ops *dss_mgr_ops;
+
+int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
{
- struct omap_dss_output *out = NULL;
- enum omap_dss_output_id id;
-
- switch (dssdev->type) {
- case OMAP_DISPLAY_TYPE_DPI:
- out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
- break;
- case OMAP_DISPLAY_TYPE_DBI:
- out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
- break;
- case OMAP_DISPLAY_TYPE_SDI:
- out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
- break;
- case OMAP_DISPLAY_TYPE_VENC:
- out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
- break;
- case OMAP_DISPLAY_TYPE_HDMI:
- out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
- break;
- case OMAP_DISPLAY_TYPE_DSI:
- id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
- OMAP_DSS_OUTPUT_DSI2;
- out = omap_dss_get_output(id);
- break;
- default:
- break;
- }
+ if (dss_mgr_ops)
+ return -EBUSY;
+
+ dss_mgr_ops = mgr_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL(dss_install_mgr_ops);
+
+void dss_uninstall_mgr_ops(void)
+{
+ dss_mgr_ops = NULL;
+}
+EXPORT_SYMBOL(dss_uninstall_mgr_ops);
+
+void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
+ const struct omap_video_timings *timings)
+{
+ dss_mgr_ops->set_timings(mgr, timings);
+}
+EXPORT_SYMBOL(dss_mgr_set_timings);
+
+void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
+ const struct dss_lcd_mgr_config *config)
+{
+ dss_mgr_ops->set_lcd_config(mgr, config);
+}
+EXPORT_SYMBOL(dss_mgr_set_lcd_config);
+
+int dss_mgr_enable(struct omap_overlay_manager *mgr)
+{
+ return dss_mgr_ops->enable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_enable);
+
+void dss_mgr_disable(struct omap_overlay_manager *mgr)
+{
+ dss_mgr_ops->disable(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_disable);
- return out;
+void dss_mgr_start_update(struct omap_overlay_manager *mgr)
+{
+ dss_mgr_ops->start_update(mgr);
+}
+EXPORT_SYMBOL(dss_mgr_start_update);
+
+int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
+ void (*handler)(void *), void *data)
+{
+ return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
+}
+EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
+
+void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
+ void (*handler)(void *), void *data)
+{
+ dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
}
+EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 45f4994bc6b..eccde322c28 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -38,13 +38,6 @@
static int num_overlays;
static struct omap_overlay *overlays;
-static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
-{
- return ovl->manager ?
- (ovl->manager->output ? ovl->manager->output->device : NULL) :
- NULL;
-}
-
int omap_dss_get_num_overlays(void)
{
return num_overlays;
@@ -93,16 +86,6 @@ void dss_init_overlays(struct platform_device *pdev)
break;
}
- ovl->is_enabled = &dss_ovl_is_enabled;
- ovl->enable = &dss_ovl_enable;
- ovl->disable = &dss_ovl_disable;
- ovl->set_manager = &dss_ovl_set_manager;
- ovl->unset_manager = &dss_ovl_unset_manager;
- ovl->set_overlay_info = &dss_ovl_set_info;
- ovl->get_overlay_info = &dss_ovl_get_info;
- ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
- ovl->get_device = &dss_ovl_get_device;
-
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
ovl->supported_modes =
dss_feat_get_supported_color_modes(ovl->id);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7282e5af3e1..e903dd3f54d 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -342,7 +342,7 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
return 0;
}
-static void framedone_callback(void *data, u32 mask)
+static void framedone_callback(void *data)
{
void (*callback)(void *data);
@@ -908,8 +908,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
goto err0;
}
- r = omap_dispc_register_isr(framedone_callback, NULL,
- DISPC_IRQ_FRAMEDONE);
+ r = dss_mgr_register_framedone_handler(out->manager,
+ framedone_callback, NULL);
if (r) {
DSSERR("can't get FRAMEDONE irq\n");
goto err1;
@@ -933,8 +933,10 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
{
- omap_dispc_unregister_isr(framedone_callback, NULL,
- DISPC_IRQ_FRAMEDONE);
+ struct omap_dss_output *out = dssdev->output;
+
+ dss_mgr_unregister_framedone_handler(out->manager,
+ framedone_callback, NULL);
omap_dss_stop_device(dssdev);
rfbi_runtime_put();
@@ -950,7 +952,7 @@ static int __init rfbi_init_display(struct omap_dss_device *dssdev)
static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = dss_get_default_display_name();
+ const char *def_disp_name = omapdss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
@@ -999,9 +1001,18 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
return;
}
+ r = omapdss_output_set_device(&rfbi.output, dssdev);
+ if (r) {
+ DSSERR("failed to connect output to new device: %s\n",
+ dssdev->name);
+ dss_put_device(dssdev);
+ return;
+ }
+
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ omapdss_output_unset_device(&rfbi.output);
dss_put_device(dssdev);
return;
}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 7760851f6e5..62b5374ce43 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -205,7 +205,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = dss_get_default_display_name();
+ const char *def_disp_name = omapdss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
@@ -254,9 +254,18 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev)
return;
}
+ r = omapdss_output_set_device(&sdi.output, dssdev);
+ if (r) {
+ DSSERR("failed to connect output to new device: %s\n",
+ dssdev->name);
+ dss_put_device(dssdev);
+ return;
+ }
+
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ omapdss_output_unset_device(&sdi.output);
dss_put_device(dssdev);
return;
}
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index b046c208cb9..216aa704f9d 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -102,6 +102,8 @@ struct ti_hdmi_ip_ops {
int (*audio_config)(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio);
+
+ int (*audio_get_dma_port)(u32 *offset, u32 *size);
#endif
};
@@ -183,5 +185,6 @@ int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
struct omap_dss_audio *audio);
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
#endif
#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index c23b85a20cd..e18b222ed73 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -899,7 +899,7 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
hdmi_read_reg(hdmi_av_base(ip_data), r))
#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
- (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
+ (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
DUMPCORE(HDMI_CORE_SYS_VND_IDL);
@@ -1418,4 +1418,13 @@ void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
REG_FLD_MOD(hdmi_wp_base(ip_data),
HDMI_WP_AUDIO_CTRL, false, 30, 30);
}
+
+int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
+{
+ if (!offset || !size)
+ return -EINVAL;
+ *offset = HDMI_WP_AUDIO_DATA;
+ *size = 4;
+ return 0;
+}
#endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 56efa3bb465..006caf3cb50 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -744,7 +744,7 @@ static void venc_put_clocks(void)
static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
- const char *def_disp_name = dss_get_default_display_name();
+ const char *def_disp_name = omapdss_get_default_display_name();
struct omap_dss_device *def_dssdev;
int i;
@@ -795,9 +795,18 @@ static void __init venc_probe_pdata(struct platform_device *vencdev)
return;
}
+ r = omapdss_output_set_device(&venc.output, dssdev);
+ if (r) {
+ DSSERR("failed to connect output to new device: %s\n",
+ dssdev->name);
+ dss_put_device(dssdev);
+ return;
+ }
+
r = dss_add_device(dssdev);
if (r) {
DSSERR("device %s register failed: %d\n", dssdev->name, r);
+ omapdss_output_unset_device(&venc.output);
dss_put_device(dssdev);
return;
}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
index d55b8784ecf..0d2b1a0834a 100644
--- a/drivers/video/omap2/dss/venc_panel.c
+++ b/drivers/video/omap2/dss/venc_panel.c
@@ -157,12 +157,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
goto end;
- if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
- /* suspended is the same as disabled with venc */
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
- goto end;
- }
-
omapdss_venc_display_disable(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
@@ -170,17 +164,6 @@ end:
mutex_unlock(&venc_panel.lock);
}
-static int venc_panel_suspend(struct omap_dss_device *dssdev)
-{
- venc_panel_disable(dssdev);
- return 0;
-}
-
-static int venc_panel_resume(struct omap_dss_device *dssdev)
-{
- return venc_panel_enable(dssdev);
-}
-
static void venc_panel_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -222,8 +205,6 @@ static struct omap_dss_driver venc_driver = {
.enable = venc_panel_enable,
.disable = venc_panel_disable,
- .suspend = venc_panel_suspend,
- .resume = venc_panel_resume,
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 4ea17dc3258..4cb12ce6885 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -2,7 +2,6 @@ menuconfig FB_OMAP2
tristate "OMAP2+ frame buffer support"
depends on FB && OMAP2_DSS && !DRM_OMAP
- select OMAP2_VRAM
select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index d630b26a005..d30b45d7264 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -28,10 +28,10 @@
#include <linux/omapfb.h>
#include <linux/vmalloc.h>
#include <linux/export.h>
+#include <linux/sizes.h>
#include <video/omapdss.h>
-#include <plat/vrfb.h>
-#include <plat/vram.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
@@ -211,6 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
struct omapfb2_mem_region *rg;
int r = 0, i;
size_t size;
@@ -220,6 +221,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
size = PAGE_ALIGN(mi->size);
+ if (display && display->driver->sync)
+ display->driver->sync(display);
+
rg = ofbi->region;
down_write_nested(&rg->lock, rg->id);
@@ -279,7 +283,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
return 0;
}
-static int omapfb_update_window_nolock(struct fb_info *fbi,
+static int omapfb_update_window(struct fb_info *fbi,
u32 x, u32 y, u32 w, u32 h)
{
struct omap_dss_device *display = fb2display(fbi);
@@ -299,27 +303,6 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
return display->driver->update(display, x, y, w, h);
}
-/* This function is exported for SGX driver use */
-int omapfb_update_window(struct fb_info *fbi,
- u32 x, u32 y, u32 w, u32 h)
-{
- struct omapfb_info *ofbi = FB2OFB(fbi);
- struct omapfb2_device *fbdev = ofbi->fbdev;
- int r;
-
- if (!lock_fb_info(fbi))
- return -ENODEV;
- omapfb_lock(fbdev);
-
- r = omapfb_update_window_nolock(fbi, x, y, w, h);
-
- omapfb_unlock(fbdev);
- unlock_fb_info(fbi);
-
- return r;
-}
-EXPORT_SYMBOL(omapfb_update_window);
-
int omapfb_set_update_mode(struct fb_info *fbi,
enum omapfb_update_mode mode)
{
@@ -646,7 +629,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
break;
}
- r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y,
+ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y,
p.uwnd_o.width, p.uwnd_o.height);
break;
@@ -663,7 +646,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
break;
}
- r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y,
+ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y,
p.uwnd.width, p.uwnd.height);
break;
@@ -853,14 +836,15 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
break;
case OMAPFB_GET_VRAM_INFO: {
- unsigned long vram, free, largest;
-
DBG("ioctl GET_VRAM_INFO\n");
- omap_vram_get_info(&vram, &free, &largest);
- p.vram_info.total = vram;
- p.vram_info.free = free;
- p.vram_info.largest_free_block = largest;
+ /*
+ * We don't have the ability to get this vram info anymore.
+ * Fill in something that should keep the applications working.
+ */
+ p.vram_info.total = SZ_1M * 64;
+ p.vram_info.free = SZ_1M * 64;
+ p.vram_info.largest_free_block = SZ_1M * 64;
if (copy_to_user((void __user *)arg, &p.vram_info,
sizeof(p.vram_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 16db1589bd9..ca585ef37f2 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -31,9 +31,7 @@
#include <linux/omapfb.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
-#include <plat/vram.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
@@ -1259,11 +1257,10 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
switch (blank) {
case FB_BLANK_UNBLANK:
- if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
+ if (display->state == OMAP_DSS_DISPLAY_ACTIVE)
goto exit;
- if (display->driver->resume)
- r = display->driver->resume(display);
+ r = display->driver->enable(display);
if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
d->update_mode == OMAPFB_AUTO_UPDATE &&
@@ -1284,8 +1281,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (d->auto_update_work_enabled)
omapfb_stop_auto_update(fbdev, display);
- if (display->driver->suspend)
- r = display->driver->suspend(display);
+ display->driver->disable(display);
break;
@@ -1336,24 +1332,25 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
rg = ofbi->region;
- WARN_ON(atomic_read(&rg->map_count));
-
- if (rg->paddr)
- if (omap_vram_free(rg->paddr, rg->size))
- dev_err(fbdev->dev, "VRAM FREE failed\n");
+ if (rg->token == NULL)
+ return;
- if (rg->vaddr)
- iounmap(rg->vaddr);
+ WARN_ON(atomic_read(&rg->map_count));
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
/* unmap the 0 angle rotation */
if (rg->vrfb.vaddr[0]) {
iounmap(rg->vrfb.vaddr[0]);
- omap_vrfb_release_ctx(&rg->vrfb);
rg->vrfb.vaddr[0] = NULL;
}
+
+ omap_vrfb_release_ctx(&rg->vrfb);
}
+ dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
+ &rg->attrs);
+
+ rg->token = NULL;
rg->vaddr = NULL;
rg->paddr = 0;
rg->alloc = 0;
@@ -1388,7 +1385,9 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb2_mem_region *rg;
- void __iomem *vaddr;
+ void *token;
+ DEFINE_DMA_ATTRS(attrs);
+ dma_addr_t dma_handle;
int r;
rg = ofbi->region;
@@ -1403,42 +1402,40 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
size = PAGE_ALIGN(size);
- if (!paddr) {
- DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
- r = omap_vram_alloc(size, &paddr);
- } else {
- DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
- ofbi->id);
- r = omap_vram_reserve(paddr, size);
- }
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- if (r) {
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
+ dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+
+ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+
+ token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
+ GFP_KERNEL, &attrs);
+
+ if (token == NULL) {
dev_err(fbdev->dev, "failed to allocate framebuffer\n");
return -ENOMEM;
}
- if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
- vaddr = ioremap_wc(paddr, size);
-
- if (!vaddr) {
- dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
- omap_vram_free(paddr, size);
- return -ENOMEM;
- }
+ DBG("allocated VRAM paddr %lx, vaddr %p\n",
+ (unsigned long)dma_handle, token);
- DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
- } else {
+ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
r = omap_vrfb_request_ctx(&rg->vrfb);
if (r) {
+ dma_free_attrs(fbdev->dev, size, token, dma_handle,
+ &attrs);
dev_err(fbdev->dev, "vrfb create ctx failed\n");
return r;
}
-
- vaddr = NULL;
}
- rg->paddr = paddr;
- rg->vaddr = vaddr;
+ rg->attrs = attrs;
+ rg->token = token;
+ rg->dma_handle = dma_handle;
+
+ rg->paddr = (unsigned long)dma_handle;
+ rg->vaddr = (void __iomem *)token;
rg->size = size;
rg->alloc = 1;
@@ -1532,6 +1529,9 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
}
+ WARN_ONCE(paddr,
+ "reserving memory at predefined address not supported\n");
+
paddrs[fbnum] = paddr;
sizes[fbnum] = size;
@@ -1611,7 +1611,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
- struct omap_dss_device *display = fb2display(fbi);
struct omapfb2_mem_region *rg = ofbi->region;
unsigned long old_size = rg->size;
unsigned long old_paddr = rg->paddr;
@@ -1626,9 +1625,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
if (old_size == size && old_type == type)
return 0;
- if (display && display->driver->sync)
- display->driver->sync(display);
-
omapfb_free_fbmem(fbi);
if (size == 0) {
@@ -1883,7 +1879,6 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
}
dev_set_drvdata(fbdev->dev, NULL);
- kfree(fbdev);
}
static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
@@ -2259,26 +2254,28 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
{
struct fb_monspecs *specs;
u8 *edid;
- int r, i, best_xres, best_idx, len;
+ int r, i, best_idx, len;
if (!display->driver->read_edid)
return -ENODEV;
len = 0x80 * 2;
edid = kmalloc(len, GFP_KERNEL);
+ if (edid == NULL)
+ return -ENOMEM;
r = display->driver->read_edid(display, edid, len);
if (r < 0)
goto err1;
specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+ if (specs == NULL) {
+ r = -ENOMEM;
+ goto err1;
+ }
fb_edid_to_monspecs(edid, specs);
- if (edid[126] > 0)
- fb_edid_add_monspecs(edid + 0x80, specs);
-
- best_xres = 0;
best_idx = -1;
for (i = 0; i < specs->modedb_len; ++i) {
@@ -2294,16 +2291,20 @@ static int omapfb_find_best_mode(struct omap_dss_device *display,
if (m->xres == 2880 || m->xres == 1440)
continue;
+ if (m->vmode & FB_VMODE_INTERLACED ||
+ m->vmode & FB_VMODE_DOUBLE)
+ continue;
+
fb_videomode_to_omap_timings(m, display, &t);
r = display->driver->check_timings(display, &t);
- if (r == 0 && best_xres < m->xres) {
- best_xres = m->xres;
+ if (r == 0) {
best_idx = i;
+ break;
}
}
- if (best_xres == 0) {
+ if (best_idx == -1) {
r = -ENOENT;
goto err2;
}
@@ -2372,15 +2373,62 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return 0;
}
+static int omapfb_init_connections(struct omapfb2_device *fbdev,
+ struct omap_dss_device *def_dssdev)
+{
+ int i, r;
+ struct omap_overlay_manager *mgr;
+
+ if (!def_dssdev->output) {
+ dev_err(fbdev->dev, "no output for the default display\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < fbdev->num_displays; ++i) {
+ struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
+ struct omap_dss_output *out = dssdev->output;
+
+ mgr = omap_dss_get_overlay_manager(dssdev->channel);
+
+ if (!mgr || !out)
+ continue;
+
+ if (mgr->output)
+ mgr->unset_output(mgr);
+
+ mgr->set_output(mgr, out);
+ }
+
+ mgr = def_dssdev->output->manager;
+
+ if (!mgr) {
+ dev_err(fbdev->dev, "no ovl manager for the default display\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < fbdev->num_overlays; i++) {
+ struct omap_overlay *ovl = fbdev->overlays[i];
+
+ if (ovl->manager)
+ ovl->unset_manager(ovl);
+
+ r = ovl->set_manager(ovl, mgr);
+ if (r)
+ dev_warn(fbdev->dev,
+ "failed to connect overlay %s to manager %s\n",
+ ovl->name, mgr->name);
+ }
+
+ return 0;
+}
+
static int __init omapfb_probe(struct platform_device *pdev)
{
struct omapfb2_device *fbdev = NULL;
int r = 0;
int i;
- struct omap_overlay *ovl;
struct omap_dss_device *def_display;
struct omap_dss_device *dssdev;
- struct omap_dss_device *ovl_device;
DBG("omapfb_probe\n");
@@ -2390,28 +2438,28 @@ static int __init omapfb_probe(struct platform_device *pdev)
goto err0;
}
- fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
+ fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device),
+ GFP_KERNEL);
if (fbdev == NULL) {
r = -ENOMEM;
goto err0;
}
- /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
- * available for OMAP2 and OMAP3
- */
- if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+ if (def_vrfb && !omap_vrfb_supported()) {
def_vrfb = 0;
dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
"ignoring the module parameter vrfb=y\n");
}
+ r = omapdss_compat_init();
+ if (r)
+ goto err0;
mutex_init(&fbdev->mtx);
fbdev->dev = &pdev->dev;
platform_set_drvdata(pdev, fbdev);
- r = 0;
fbdev->num_displays = 0;
dssdev = NULL;
for_each_dss_dev(dssdev) {
@@ -2434,9 +2482,6 @@ static int __init omapfb_probe(struct platform_device *pdev)
d->update_mode = OMAPFB_AUTO_UPDATE;
}
- if (r)
- goto cleanup;
-
if (fbdev->num_displays == 0) {
dev_err(&pdev->dev, "no displays\n");
r = -EINVAL;
@@ -2451,15 +2496,33 @@ static int __init omapfb_probe(struct platform_device *pdev)
for (i = 0; i < fbdev->num_managers; i++)
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
- /* gfx overlay should be the default one. find a display
- * connected to that, and use it as default display */
- ovl = omap_dss_get_overlay(0);
- ovl_device = ovl->get_device(ovl);
- if (ovl_device) {
- def_display = ovl_device;
- } else {
- dev_warn(&pdev->dev, "cannot find default display\n");
- def_display = NULL;
+ def_display = NULL;
+
+ for (i = 0; i < fbdev->num_displays; ++i) {
+ struct omap_dss_device *dssdev;
+ const char *def_name;
+
+ def_name = omapdss_get_default_display_name();
+
+ dssdev = fbdev->displays[i].dssdev;
+
+ if (def_name == NULL ||
+ (dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
+ def_display = dssdev;
+ break;
+ }
+ }
+
+ if (def_display == NULL) {
+ dev_err(fbdev->dev, "failed to find default display\n");
+ r = -EINVAL;
+ goto cleanup;
+ }
+
+ r = omapfb_init_connections(fbdev, def_display);
+ if (r) {
+ dev_err(fbdev->dev, "failed to init overlay connections\n");
+ goto cleanup;
}
if (def_mode && strlen(def_mode) > 0) {
@@ -2510,6 +2573,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
cleanup:
omapfb_free_resources(fbdev);
+ omapdss_compat_uninit();
err0:
dev_err(&pdev->dev, "failed to setup omapfb\n");
return r;
@@ -2525,6 +2589,8 @@ static int __exit omapfb_remove(struct platform_device *pdev)
omapfb_free_resources(fbdev);
+ omapdss_compat_uninit();
+
return 0;
}
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index e8d8cc76a43..18fa9e1d003 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -30,7 +30,7 @@
#include <linux/omapfb.h>
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
@@ -441,6 +441,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
+ struct omap_dss_device *display = fb2display(fbi);
struct omapfb2_mem_region *rg;
unsigned long size;
int r;
@@ -455,6 +456,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
if (!lock_fb_info(fbi))
return -ENODEV;
+ if (display && display->driver->sync)
+ display->driver->sync(display);
+
rg = ofbi->region;
down_write_nested(&rg->lock, rg->id);
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 5ced9b334d3..623cd872a36 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -28,6 +28,8 @@
#endif
#include <linux/rwsem.h>
+#include <linux/dma-attrs.h>
+#include <linux/dma-mapping.h>
#include <video/omapdss.h>
@@ -49,6 +51,9 @@ extern bool omapfb_debug;
struct omapfb2_mem_region {
int id;
+ struct dma_attrs attrs;
+ void *token;
+ dma_addr_t dma_handle;
u32 paddr;
void __iomem *vaddr;
struct vrfb vrfb;
@@ -124,9 +129,6 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
-int omapfb_update_window(struct fb_info *fbi,
- u32 x, u32 y, u32 w, u32 h);
-
int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
struct fb_var_screeninfo *var);
@@ -144,16 +146,16 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
- int i;
+ struct omap_overlay *ovl;
/* XXX: returns the display connected to first attached overlay */
- for (i = 0; i < ofbi->num_overlays; i++) {
- struct omap_overlay *ovl = ofbi->overlays[i];
- return ovl->get_device(ovl);
- }
+ if (ofbi->num_overlays == 0)
+ return NULL;
- return NULL;
+ ovl = ofbi->overlays[0];
+
+ return ovl->get_device(ovl);
}
static inline struct omapfb_display_data *get_display_data(
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
deleted file mode 100644
index f2b15c4a75b..00000000000
--- a/drivers/video/omap2/vram.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * VRAM manager for OMAP
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * 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.,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*#define DEBUG*/
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/seq_file.h>
-#include <linux/memblock.h>
-#include <linux/completion.h>
-#include <linux/debugfs.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-
-#include <asm/setup.h>
-
-#include <plat/vram.h>
-
-#ifdef DEBUG
-#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
-#else
-#define DBG(format, ...)
-#endif
-
-/* postponed regions are used to temporarily store region information at boot
- * time when we cannot yet allocate the region list */
-#define MAX_POSTPONED_REGIONS 10
-
-static bool vram_initialized;
-static int postponed_cnt;
-static struct {
- unsigned long paddr;
- size_t size;
-} postponed_regions[MAX_POSTPONED_REGIONS];
-
-struct vram_alloc {
- struct list_head list;
- unsigned long paddr;
- unsigned pages;
-};
-
-struct vram_region {
- struct list_head list;
- struct list_head alloc_list;
- unsigned long paddr;
- unsigned pages;
-};
-
-static DEFINE_MUTEX(region_mutex);
-static LIST_HEAD(region_list);
-
-static struct vram_region *omap_vram_create_region(unsigned long paddr,
- unsigned pages)
-{
- struct vram_region *rm;
-
- rm = kzalloc(sizeof(*rm), GFP_KERNEL);
-
- if (rm) {
- INIT_LIST_HEAD(&rm->alloc_list);
- rm->paddr = paddr;
- rm->pages = pages;
- }
-
- return rm;
-}
-
-#if 0
-static void omap_vram_free_region(struct vram_region *vr)
-{
- list_del(&vr->list);
- kfree(vr);
-}
-#endif
-
-static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
- unsigned long paddr, unsigned pages)
-{
- struct vram_alloc *va;
- struct vram_alloc *new;
-
- new = kzalloc(sizeof(*va), GFP_KERNEL);
-
- if (!new)
- return NULL;
-
- new->paddr = paddr;
- new->pages = pages;
-
- list_for_each_entry(va, &vr->alloc_list, list) {
- if (va->paddr > new->paddr)
- break;
- }
-
- list_add_tail(&new->list, &va->list);
-
- return new;
-}
-
-static void omap_vram_free_allocation(struct vram_alloc *va)
-{
- list_del(&va->list);
- kfree(va);
-}
-
-int omap_vram_add_region(unsigned long paddr, size_t size)
-{
- struct vram_region *rm;
- unsigned pages;
-
- if (vram_initialized) {
- DBG("adding region paddr %08lx size %d\n",
- paddr, size);
-
- size &= PAGE_MASK;
- pages = size >> PAGE_SHIFT;
-
- rm = omap_vram_create_region(paddr, pages);
- if (rm == NULL)
- return -ENOMEM;
-
- list_add(&rm->list, &region_list);
- } else {
- if (postponed_cnt == MAX_POSTPONED_REGIONS)
- return -ENOMEM;
-
- postponed_regions[postponed_cnt].paddr = paddr;
- postponed_regions[postponed_cnt].size = size;
-
- ++postponed_cnt;
- }
- return 0;
-}
-
-int omap_vram_free(unsigned long paddr, size_t size)
-{
- struct vram_region *rm;
- struct vram_alloc *alloc;
- unsigned start, end;
-
- DBG("free mem paddr %08lx size %d\n", paddr, size);
-
- size = PAGE_ALIGN(size);
-
- mutex_lock(&region_mutex);
-
- list_for_each_entry(rm, &region_list, list) {
- list_for_each_entry(alloc, &rm->alloc_list, list) {
- start = alloc->paddr;
- end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
-
- if (start >= paddr && end < paddr + size)
- goto found;
- }
- }
-
- mutex_unlock(&region_mutex);
- return -EINVAL;
-
-found:
- omap_vram_free_allocation(alloc);
-
- mutex_unlock(&region_mutex);
- return 0;
-}
-EXPORT_SYMBOL(omap_vram_free);
-
-static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
-{
- struct vram_region *rm;
- struct vram_alloc *alloc;
- size_t size;
-
- size = pages << PAGE_SHIFT;
-
- list_for_each_entry(rm, &region_list, list) {
- unsigned long start, end;
-
- DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
- start = rm->paddr;
- end = start + (rm->pages << PAGE_SHIFT) - 1;
- if (start > paddr || end < paddr + size - 1)
- continue;
-
- DBG("block ok, checking allocs\n");
-
- list_for_each_entry(alloc, &rm->alloc_list, list) {
- end = alloc->paddr - 1;
-
- if (start <= paddr && end >= paddr + size - 1)
- goto found;
-
- start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
- }
-
- end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
-
- if (!(start <= paddr && end >= paddr + size - 1))
- continue;
-found:
- DBG("found area start %lx, end %lx\n", start, end);
-
- if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
- return -ENOMEM;
-
- return 0;
- }
-
- return -ENOMEM;
-}
-
-int omap_vram_reserve(unsigned long paddr, size_t size)
-{
- unsigned pages;
- int r;
-
- DBG("reserve mem paddr %08lx size %d\n", paddr, size);
-
- size = PAGE_ALIGN(size);
- pages = size >> PAGE_SHIFT;
-
- mutex_lock(&region_mutex);
-
- r = _omap_vram_reserve(paddr, pages);
-
- mutex_unlock(&region_mutex);
-
- return r;
-}
-EXPORT_SYMBOL(omap_vram_reserve);
-
-static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
-{
- struct vram_region *rm;
- struct vram_alloc *alloc;
-
- list_for_each_entry(rm, &region_list, list) {
- unsigned long start, end;
-
- DBG("checking region %lx %d\n", rm->paddr, rm->pages);
-
- start = rm->paddr;
-
- list_for_each_entry(alloc, &rm->alloc_list, list) {
- end = alloc->paddr;
-
- if (end - start >= pages << PAGE_SHIFT)
- goto found;
-
- start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
- }
-
- end = rm->paddr + (rm->pages << PAGE_SHIFT);
-found:
- if (end - start < pages << PAGE_SHIFT)
- continue;
-
- DBG("found %lx, end %lx\n", start, end);
-
- alloc = omap_vram_create_allocation(rm, start, pages);
- if (alloc == NULL)
- return -ENOMEM;
-
- *paddr = start;
-
- return 0;
- }
-
- return -ENOMEM;
-}
-
-int omap_vram_alloc(size_t size, unsigned long *paddr)
-{
- unsigned pages;
- int r;
-
- BUG_ON(!size);
-
- DBG("alloc mem size %d\n", size);
-
- size = PAGE_ALIGN(size);
- pages = size >> PAGE_SHIFT;
-
- mutex_lock(&region_mutex);
-
- r = _omap_vram_alloc(pages, paddr);
-
- mutex_unlock(&region_mutex);
-
- return r;
-}
-EXPORT_SYMBOL(omap_vram_alloc);
-
-void omap_vram_get_info(unsigned long *vram,
- unsigned long *free_vram,
- unsigned long *largest_free_block)
-{
- struct vram_region *vr;
- struct vram_alloc *va;
-
- *vram = 0;
- *free_vram = 0;
- *largest_free_block = 0;
-
- mutex_lock(&region_mutex);
-
- list_for_each_entry(vr, &region_list, list) {
- unsigned free;
- unsigned long pa;
-
- pa = vr->paddr;
- *vram += vr->pages << PAGE_SHIFT;
-
- list_for_each_entry(va, &vr->alloc_list, list) {
- free = va->paddr - pa;
- *free_vram += free;
- if (free > *largest_free_block)
- *largest_free_block = free;
- pa = va->paddr + (va->pages << PAGE_SHIFT);
- }
-
- free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa;
- *free_vram += free;
- if (free > *largest_free_block)
- *largest_free_block = free;
- }
-
- mutex_unlock(&region_mutex);
-}
-EXPORT_SYMBOL(omap_vram_get_info);
-
-#if defined(CONFIG_DEBUG_FS)
-static int vram_debug_show(struct seq_file *s, void *unused)
-{
- struct vram_region *vr;
- struct vram_alloc *va;
- unsigned size;
-
- mutex_lock(&region_mutex);
-
- list_for_each_entry(vr, &region_list, list) {
- size = vr->pages << PAGE_SHIFT;
- seq_printf(s, "%08lx-%08lx (%d bytes)\n",
- vr->paddr, vr->paddr + size - 1,
- size);
-
- list_for_each_entry(va, &vr->alloc_list, list) {
- size = va->pages << PAGE_SHIFT;
- seq_printf(s, " %08lx-%08lx (%d bytes)\n",
- va->paddr, va->paddr + size - 1,
- size);
- }
- }
-
- mutex_unlock(&region_mutex);
-
- return 0;
-}
-
-static int vram_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, vram_debug_show, inode->i_private);
-}
-
-static const struct file_operations vram_debug_fops = {
- .open = vram_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init omap_vram_create_debugfs(void)
-{
- struct dentry *d;
-
- d = debugfs_create_file("vram", S_IRUGO, NULL,
- NULL, &vram_debug_fops);
- if (IS_ERR(d))
- return PTR_ERR(d);
-
- return 0;
-}
-#endif
-
-static __init int omap_vram_init(void)
-{
- int i;
-
- vram_initialized = 1;
-
- for (i = 0; i < postponed_cnt; i++)
- omap_vram_add_region(postponed_regions[i].paddr,
- postponed_regions[i].size);
-
-#ifdef CONFIG_DEBUG_FS
- if (omap_vram_create_debugfs())
- pr_err("VRAM: Failed to create debugfs file\n");
-#endif
-
- return 0;
-}
-
-arch_initcall(omap_vram_init);
-
-/* boottime vram alloc stuff */
-
-/* set from board file */
-static u32 omap_vram_sdram_start __initdata;
-static u32 omap_vram_sdram_size __initdata;
-
-/* set from kernel cmdline */
-static u32 omap_vram_def_sdram_size __initdata;
-static u32 omap_vram_def_sdram_start __initdata;
-
-static int __init omap_vram_early_vram(char *p)
-{
- omap_vram_def_sdram_size = memparse(p, &p);
- if (*p == ',')
- omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16);
- return 0;
-}
-early_param("vram", omap_vram_early_vram);
-
-/*
- * Called from map_io. We need to call to this early enough so that we
- * can reserve the fixed SDRAM regions before VM could get hold of them.
- */
-void __init omap_vram_reserve_sdram_memblock(void)
-{
- u32 paddr;
- u32 size = 0;
-
- /* cmdline arg overrides the board file definition */
- if (omap_vram_def_sdram_size) {
- size = omap_vram_def_sdram_size;
- paddr = omap_vram_def_sdram_start;
- }
-
- if (!size) {
- size = omap_vram_sdram_size;
- paddr = omap_vram_sdram_start;
- }
-
-#ifdef CONFIG_OMAP2_VRAM_SIZE
- if (!size) {
- size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024;
- paddr = 0;
- }
-#endif
-
- if (!size)
- return;
-
- size = ALIGN(size, SZ_2M);
-
- if (paddr) {
- if (paddr & ~PAGE_MASK) {
- pr_err("VRAM start address 0x%08x not page aligned\n",
- paddr);
- return;
- }
-
- if (!memblock_is_region_memory(paddr, size)) {
- pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
- paddr, paddr + size - 1);
- return;
- }
-
- if (memblock_is_region_reserved(paddr, size)) {
- pr_err("FB: failed to reserve VRAM - busy\n");
- return;
- }
-
- if (memblock_reserve(paddr, size) < 0) {
- pr_err("FB: failed to reserve VRAM - no memory\n");
- return;
- }
- } else {
- paddr = memblock_alloc(size, SZ_2M);
- }
-
- memblock_free(paddr, size);
- memblock_remove(paddr, size);
-
- omap_vram_add_region(paddr, size);
-
- pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
-}
-
-void __init omap_vram_set_sdram_vram(u32 size, u32 start)
-{
- omap_vram_sdram_start = start;
- omap_vram_sdram_size = size;
-}
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e990220ad2..5d8fdac3b80 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
-#include <plat/vrfb.h>
-#include <plat/sdrc.h>
+#include <video/omapvrfb.h>
#ifdef DEBUG
#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
#define DBG(format, ...)
#endif
-#define SMS_ROT_VIRT_BASE(context, rot) \
- (((context >= 4) ? 0xD0000000 : 0x70000000) \
- + (0x4000000 * (context)) \
- + (0x1000000 * (rot)))
+#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
@@ -53,10 +53,16 @@
#define SMS_PW_OFFSET 4
#define SMS_PS_OFFSET 0
-#define VRFB_NUM_CTXS 12
/* bitmap of reserved contexts */
static unsigned long ctx_map;
+struct vrfb_ctx {
+ u32 base;
+ u32 physical_ba;
+ u32 control;
+ u32 size;
+};
+
static DEFINE_MUTEX(ctx_lock);
/*
@@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
* we don't need locking, since no drivers will run until after the wake-up
* has finished.
*/
-static struct {
- u32 physical_ba;
- u32 control;
- u32 size;
-} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static bool vrfb_loaded;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
static inline void restore_hw_context(int ctx)
{
- omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
- omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
- omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
+ omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+ omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+ omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
}
static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
- vrfb_hw_context[ctx].physical_ba = paddr;
- vrfb_hw_context[ctx].size = size;
- vrfb_hw_context[ctx].control = control;
+ ctxs[ctx].physical_ba = paddr;
+ ctxs[ctx].size = size;
+ ctxs[ctx].control = control;
omap2_sms_write_rot_physical_ba(paddr, ctx);
omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
mutex_lock(&ctx_lock);
- for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+ for (ctx = 0; ctx < num_ctxs; ++ctx)
if ((ctx_map & (1 << ctx)) == 0)
break;
- if (ctx == VRFB_NUM_CTXS) {
+ if (ctx == num_ctxs) {
pr_err("vrfb: no free contexts\n");
r = -EBUSY;
goto out;
@@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
vrfb->context = ctx;
for (rot = 0; rot < 4; ++rot) {
- paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+ paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
pr_err("vrfb: failed to reserve VRFB "
"area for ctx %d, rotation %d\n",
@@ -314,3 +337,80 @@ out:
return r;
}
EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+bool omap_vrfb_supported(void)
+{
+ return vrfb_loaded;
+}
+EXPORT_SYMBOL(omap_vrfb_supported);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ int i;
+
+ /* first resource is the register res, the rest are vrfb contexts */
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "can't get vrfb base address\n");
+ return -EINVAL;
+ }
+
+ vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!vrfb_base) {
+ dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
+ return -ENOMEM;
+ }
+
+ num_ctxs = pdev->num_resources - 1;
+
+ ctxs = devm_kzalloc(&pdev->dev,
+ sizeof(struct vrfb_ctx) * num_ctxs,
+ GFP_KERNEL);
+
+ if (!ctxs)
+ return -ENOMEM;
+
+ for (i = 0; i < num_ctxs; ++i) {
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+ if (!mem) {
+ dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+ i);
+ return -EINVAL;
+ }
+
+ ctxs[i].base = mem->start;
+ }
+
+ vrfb_loaded = true;
+
+ return 0;
+}
+
+static void __exit vrfb_remove(struct platform_device *pdev)
+{
+ vrfb_loaded = false;
+}
+
+static struct platform_driver vrfb_driver = {
+ .driver.name = "omapvrfb",
+ .remove = __exit_p(vrfb_remove),
+};
+
+static int __init vrfb_init(void)
+{
+ return platform_driver_probe(&vrfb_driver, &vrfb_probe);
+}
+
+static void __exit vrfb_exit(void)
+{
+ platform_driver_unregister(&vrfb_driver);
+}
+
+module_init(vrfb_init);
+module_exit(vrfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 2ed7b633bbd..1a00ad241ed 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -189,7 +189,7 @@ struct s3c_fb_vsync {
/**
* struct s3c_fb - overall hardware state of the hardware
- * @slock: The spinlock protection for this data sturucture.
+ * @slock: The spinlock protection for this data structure.
* @dev: The device that we bound to, for printing, etc.
* @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
* @lcd_clk: The clk (sclk) feeding pixclk.
@@ -268,10 +268,10 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
case 8:
if (sfb->variant.palette[win->index] != 0) {
/* non palletised, A:1,R:2,G:3,B:2 mode */
- var->red.offset = 4;
+ var->red.offset = 5;
var->green.offset = 2;
var->blue.offset = 0;
- var->red.length = 5;
+ var->red.length = 2;
var->green.length = 3;
var->blue.length = 2;
var->transp.offset = 7;
@@ -288,6 +288,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
/* 666 with one bit alpha/transparency */
var->transp.offset = 18;
var->transp.length = 1;
+ /* drop through */
case 18:
var->bits_per_pixel = 32;
@@ -329,6 +330,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
default:
dev_err(sfb->dev, "invalid bpp\n");
+ return -EINVAL;
}
dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
@@ -1544,8 +1546,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int s3c_fb_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
struct s3c_fb_win *win;
int win_no;
@@ -1572,8 +1573,7 @@ static int s3c_fb_suspend(struct device *dev)
static int s3c_fb_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
struct s3c_fb_platdata *pd = sfb->pdata;
struct s3c_fb_win *win;
int win_no;
@@ -1623,7 +1623,7 @@ static int s3c_fb_resume(struct device *dev)
if (!win)
continue;
- dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
+ dev_dbg(dev, "resuming window %d\n", win_no);
s3c_fb_set_par(win->fbinfo);
}
@@ -1636,8 +1636,7 @@ static int s3c_fb_resume(struct device *dev)
#ifdef CONFIG_PM_RUNTIME
static int s3c_fb_runtime_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
if (!sfb->variant.has_clksel)
clk_disable_unprepare(sfb->lcd_clk);
@@ -1649,8 +1648,7 @@ static int s3c_fb_runtime_suspend(struct device *dev)
static int s3c_fb_runtime_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct s3c_fb *sfb = platform_get_drvdata(pdev);
+ struct s3c_fb *sfb = dev_get_drvdata(dev);
struct s3c_fb_platdata *pd = sfb->pdata;
clk_prepare_enable(sfb->bus_clk);
@@ -1910,7 +1908,7 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
.variant = {
.nr_windows = 5,
- .vidtcon = VIDTCON0,
+ .vidtcon = FIMD_V8_VIDTCON0,
.wincon = WINCON(0),
.winmap = WINxMAP(0),
.keycon = WKEYCON,
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 3951fdae5f6..f4962292792 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -127,13 +127,12 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
sh_mipi_dsi_enable(mipi, false);
}
-static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
+static int sh_mipi_setup(struct sh_mipi *mipi, const struct fb_videomode *mode)
{
void __iomem *base = mipi->base;
- struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
+ struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
u32 pctype, datatype, pixfmt, linelength, vmctr2;
u32 tmp, top, bottom, delay, div;
- bool yuv;
int bpp;
/*
@@ -146,95 +145,79 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
pctype = 0;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
- linelength = ch->lcd_modes[0].xres * 3;
- yuv = false;
+ linelength = mode->xres * 3;
break;
case MIPI_RGB565:
pctype = 1;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
- linelength = ch->lcd_modes[0].xres * 2;
- yuv = false;
+ linelength = mode->xres * 2;
break;
case MIPI_RGB666_LP:
pctype = 2;
datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
- linelength = ch->lcd_modes[0].xres * 3;
- yuv = false;
+ linelength = mode->xres * 3;
break;
case MIPI_RGB666:
pctype = 3;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
- linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
- yuv = false;
+ linelength = (mode->xres * 18 + 7) / 8;
break;
case MIPI_BGR888:
pctype = 8;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
- linelength = ch->lcd_modes[0].xres * 3;
- yuv = false;
+ linelength = mode->xres * 3;
break;
case MIPI_BGR565:
pctype = 9;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
- linelength = ch->lcd_modes[0].xres * 2;
- yuv = false;
+ linelength = mode->xres * 2;
break;
case MIPI_BGR666_LP:
pctype = 0xa;
datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
- linelength = ch->lcd_modes[0].xres * 3;
- yuv = false;
+ linelength = mode->xres * 3;
break;
case MIPI_BGR666:
pctype = 0xb;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
- linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
- yuv = false;
+ linelength = (mode->xres * 18 + 7) / 8;
break;
case MIPI_YUYV:
pctype = 4;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
- linelength = ch->lcd_modes[0].xres * 2;
- yuv = true;
+ linelength = mode->xres * 2;
break;
case MIPI_UYVY:
pctype = 5;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
- linelength = ch->lcd_modes[0].xres * 2;
- yuv = true;
+ linelength = mode->xres * 2;
break;
case MIPI_YUV420_L:
pctype = 6;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
- linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
- yuv = true;
+ linelength = (mode->xres * 12 + 7) / 8;
break;
case MIPI_YUV420:
pctype = 7;
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
/* Length of U/V line */
- linelength = (ch->lcd_modes[0].xres + 1) / 2;
- yuv = true;
+ linelength = (mode->xres + 1) / 2;
break;
default:
return -EINVAL;
}
- if ((yuv && ch->interface_type != YUV422) ||
- (!yuv && ch->interface_type != RGB24))
- return -EINVAL;
-
if (!pdata->lane)
return -EINVAL;
@@ -293,7 +276,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
*/
iowrite32(0x00000006, mipi->linkbase + DTCTR);
/* VSYNC width = 2 (<< 17) */
- iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
+ iowrite32((mode->vsync_len << pdata->vsynw_offset) |
(pdata->clksrc << 16) | (pctype << 12) | datatype,
mipi->linkbase + VMCTR1);
@@ -327,7 +310,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
top = linelength << 16; /* RGBLEN */
bottom = 0x00000001;
if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
- bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
+ bottom = (pdata->lane * mode->hsync_len) - 10;
iowrite32(top | bottom , mipi->linkbase + VMLEN1);
/*
@@ -347,18 +330,18 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
div = 2;
if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
- top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
+ top = mode->hsync_len + mode->left_margin;
top = ((pdata->lane * top / div) - 10) << 16;
}
if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
- bottom = ch->lcd_modes[0].right_margin;
+ bottom = mode->right_margin;
bottom = (pdata->lane * bottom / div) - 12;
}
- bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
+ bpp = linelength / mode->xres; /* byte / pixel */
if ((pdata->lane / div) > bpp) {
- tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
- tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
+ tmp = mode->xres / bpp; /* output cycle */
+ tmp = mode->xres - tmp; /* (input - output) cycle */
delay = (pdata->lane * tmp);
}
@@ -369,7 +352,7 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
/* setup LCD panel */
/* cf. drivers/video/omap/lcd_mipid.c */
- sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
+ sh_mipi_dcs(pdata->channel, MIPI_DCS_EXIT_SLEEP_MODE);
msleep(120);
/*
* [7] - Page Address Mode
@@ -381,11 +364,11 @@ static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
* [1] - Flip Horizontal
* [0] - Flip Vertical
*/
- sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+ sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
/* cf. set_data_lines() */
- sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
+ sh_mipi_dcs_param(pdata->channel, MIPI_DCS_SET_PIXEL_FORMAT,
pixfmt << 4);
- sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
+ sh_mipi_dcs(pdata->channel, MIPI_DCS_SET_DISPLAY_ON);
/* Enable timeout counters */
iowrite32(0x00000f00, base + DSICTRL);
@@ -405,7 +388,7 @@ static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
if (ret < 0)
goto mipi_display_on_fail1;
- ret = sh_mipi_setup(mipi, pdata);
+ ret = sh_mipi_setup(mipi, &entity->def_mode);
if (ret < 0)
goto mipi_display_on_fail2;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 699487c287b..e78fe4bc152 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -438,7 +438,7 @@ static unsigned long lcdc_sys_read_data(void *handle)
return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK;
}
-struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
+static struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
lcdc_sys_write_index,
lcdc_sys_write_data,
lcdc_sys_read_data,
@@ -586,8 +586,8 @@ static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
* Just turn on, if we run a resume here, the
* logo disappears.
*/
- info->var.width = monspec->max_x * 10;
- info->var.height = monspec->max_y * 10;
+ info->var.width = ch->display.width;
+ info->var.height = ch->display.height;
sh_mobile_lcdc_display_on(ch);
} else {
/* New monitor or have to wake up */
@@ -1614,6 +1614,15 @@ static int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info)
return 1;
}
+static int
+sh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct sh_mobile_lcdc_overlay *ovl = info->par;
+
+ return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem,
+ ovl->dma_handle, ovl->fb_size);
+}
+
static struct fb_ops sh_mobile_lcdc_overlay_ops = {
.owner = THIS_MODULE,
.fb_read = fb_sys_read,
@@ -1626,6 +1635,7 @@ static struct fb_ops sh_mobile_lcdc_overlay_ops = {
.fb_ioctl = sh_mobile_lcdc_overlay_ioctl,
.fb_check_var = sh_mobile_lcdc_overlay_check_var,
.fb_set_par = sh_mobile_lcdc_overlay_set_par,
+ .fb_mmap = sh_mobile_lcdc_overlay_mmap,
};
static void
@@ -2093,6 +2103,15 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
return 0;
}
+static int
+sh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct sh_mobile_lcdc_chan *ch = info->par;
+
+ return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem,
+ ch->dma_handle, ch->fb_size);
+}
+
static struct fb_ops sh_mobile_lcdc_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = sh_mobile_lcdc_setcolreg,
@@ -2108,6 +2127,7 @@ static struct fb_ops sh_mobile_lcdc_ops = {
.fb_release = sh_mobile_lcdc_release,
.fb_check_var = sh_mobile_lcdc_check_var,
.fb_set_par = sh_mobile_lcdc_set_par,
+ .fb_mmap = sh_mobile_lcdc_mmap,
};
static void
@@ -2167,7 +2187,7 @@ sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
static int __devinit
sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
- const struct fb_videomode *mode,
+ const struct fb_videomode *modes,
unsigned int num_modes)
{
struct sh_mobile_lcdc_priv *priv = ch->lcdc;
@@ -2193,7 +2213,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
info->pseudo_palette = &ch->pseudo_palette;
info->par = ch;
- fb_videomode_to_modelist(mode, num_modes, &info->modelist);
+ fb_videomode_to_modelist(modes, num_modes, &info->modelist);
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
if (ret < 0) {
@@ -2227,9 +2247,9 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
* default.
*/
var = &info->var;
- fb_videomode_to_var(var, mode);
- var->width = ch->cfg->panel_cfg.width;
- var->height = ch->cfg->panel_cfg.height;
+ fb_videomode_to_var(var, modes);
+ var->width = ch->display.width;
+ var->height = ch->display.height;
var->xres_virtual = ch->xres_virtual;
var->yres_virtual = ch->yres_virtual;
var->activate = FB_ACTIVATE_NOW;
@@ -2262,6 +2282,7 @@ static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
brightness = 0;
+ ch->bl_brightness = brightness;
return ch->cfg->bl_info.set_brightness(brightness);
}
@@ -2269,7 +2290,7 @@ static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
{
struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
- return ch->cfg->bl_info.get_brightness();
+ return ch->bl_brightness;
}
static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
@@ -2516,10 +2537,10 @@ static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *
}
static int __devinit
-sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
- struct sh_mobile_lcdc_overlay *ovl)
+sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl)
{
const struct sh_mobile_lcdc_format_info *format;
+ struct device *dev = ovl->channel->lcdc->dev;
int ret;
if (ovl->cfg->fourcc == 0)
@@ -2528,7 +2549,7 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
/* Validate the format. */
format = sh_mobile_format_info(ovl->cfg->fourcc);
if (format == NULL) {
- dev_err(priv->dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
+ dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc);
return -EINVAL;
}
@@ -2556,10 +2577,10 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
/* Allocate frame buffer memory. */
ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres
* format->bpp / 8 * 2;
- ovl->fb_mem = dma_alloc_coherent(priv->dev, ovl->fb_size,
- &ovl->dma_handle, GFP_KERNEL);
+ ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle,
+ GFP_KERNEL);
if (!ovl->fb_mem) {
- dev_err(priv->dev, "unable to allocate buffer\n");
+ dev_err(dev, "unable to allocate buffer\n");
return -ENOMEM;
}
@@ -2571,11 +2592,11 @@ sh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_priv *priv,
}
static int __devinit
-sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
- struct sh_mobile_lcdc_chan *ch)
+sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch)
{
const struct sh_mobile_lcdc_format_info *format;
const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
+ struct device *dev = ch->lcdc->dev;
const struct fb_videomode *max_mode;
const struct fb_videomode *mode;
unsigned int num_modes;
@@ -2588,7 +2609,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
/* Validate the format. */
format = sh_mobile_format_info(cfg->fourcc);
if (format == NULL) {
- dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
+ dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
return -EINVAL;
}
@@ -2604,7 +2625,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
/* NV12/NV21 buffers must have even number of lines */
if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
- dev_err(priv->dev, "yres must be multiple of 2 for "
+ dev_err(dev, "yres must be multiple of 2 for "
"YCbCr420 mode.\n");
return -EINVAL;
}
@@ -2618,7 +2639,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
if (!max_size)
max_size = MAX_XRES * MAX_YRES;
else
- dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
+ dev_dbg(dev, "Found largest videomode %ux%u\n",
max_mode->xres, max_mode->yres);
if (cfg->lcd_modes == NULL) {
@@ -2652,10 +2673,10 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
/* Allocate frame buffer memory. */
ch->fb_size = max_size * format->bpp / 8 * 2;
- ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle,
+ ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle,
GFP_KERNEL);
if (ch->fb_mem == NULL) {
- dev_err(priv->dev, "unable to allocate buffer\n");
+ dev_err(dev, "unable to allocate buffer\n");
return -ENOMEM;
}
@@ -2663,8 +2684,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
if (cfg->tx_dev) {
if (!cfg->tx_dev->dev.driver ||
!try_module_get(cfg->tx_dev->dev.driver->owner)) {
- dev_warn(priv->dev,
- "unable to get transmitter device\n");
+ dev_warn(dev, "unable to get transmitter device\n");
return -EINVAL;
}
ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
@@ -2772,9 +2792,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
for (i = 0; i < num_channels; i++) {
- struct sh_mobile_lcdc_chan *ch = priv->ch + i;
+ struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
- error = sh_mobile_lcdc_channel_init(priv, ch);
+ error = sh_mobile_lcdc_channel_init(ch);
if (error)
goto err1;
}
@@ -2785,7 +2805,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
ovl->cfg = &pdata->overlays[i];
ovl->channel = &priv->ch[0];
- error = sh_mobile_lcdc_overlay_init(priv, ovl);
+ error = sh_mobile_lcdc_overlay_init(ovl);
if (error)
goto err1;
}
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 0f92f6544b9..f839adef1d9 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -94,6 +94,7 @@ struct sh_mobile_lcdc_chan {
/* Backlight */
struct backlight_device *bl;
+ unsigned int bl_brightness;
/* FB */
struct fb_info *info;
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
new file mode 100644
index 00000000000..6101f5c2f62
--- /dev/null
+++ b/drivers/video/ssd1307fb.c
@@ -0,0 +1,396 @@
+/*
+ * Driver for the Solomon SSD1307 OLED controler
+ *
+ * Copyright 2012 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/uaccess.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#define SSD1307FB_WIDTH 96
+#define SSD1307FB_HEIGHT 16
+
+#define SSD1307FB_DATA 0x40
+#define SSD1307FB_COMMAND 0x80
+
+#define SSD1307FB_CONTRAST 0x81
+#define SSD1307FB_SEG_REMAP_ON 0xa1
+#define SSD1307FB_DISPLAY_OFF 0xae
+#define SSD1307FB_DISPLAY_ON 0xaf
+#define SSD1307FB_START_PAGE_ADDRESS 0xb0
+
+struct ssd1307fb_par {
+ struct i2c_client *client;
+ struct fb_info *info;
+ struct pwm_device *pwm;
+ u32 pwm_period;
+ int reset;
+};
+
+static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
+ .id = "Solomon SSD1307",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_MONO10,
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+ .line_length = SSD1307FB_WIDTH / 8,
+ .accel = FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
+ .xres = SSD1307FB_WIDTH,
+ .yres = SSD1307FB_HEIGHT,
+ .xres_virtual = SSD1307FB_WIDTH,
+ .yres_virtual = SSD1307FB_HEIGHT,
+ .bits_per_pixel = 1,
+};
+
+static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8 *cmd, u32 len)
+{
+ u8 *buf;
+ int ret = 0;
+
+ buf = kzalloc(len + 1, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
+ return -ENOMEM;
+ }
+
+ buf[0] = type;
+ memcpy(buf + 1, cmd, len);
+
+ ret = i2c_master_send(client, buf, len + 1);
+ if (ret != len + 1) {
+ dev_err(&client->dev, "Couldn't send I2C command.\n");
+ goto error;
+ }
+
+error:
+ kfree(buf);
+ return ret;
+}
+
+static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+ return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
+}
+
+static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
+{
+ return ssd1307fb_write_cmd_array(client, &cmd, 1);
+}
+
+static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
+{
+ return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
+}
+
+static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
+{
+ return ssd1307fb_write_data_array(client, &data, 1);
+}
+
+static void ssd1307fb_update_display(struct ssd1307fb_par *par)
+{
+ u8 *vmem = par->info->screen_base;
+ int i, j, k;
+
+ /*
+ * The screen is divided in pages, each having a height of 8
+ * pixels, and the width of the screen. When sending a byte of
+ * data to the controller, it gives the 8 bits for the current
+ * column. I.e, the first byte are the 8 bits of the first
+ * column, then the 8 bits for the second column, etc.
+ *
+ *
+ * Representation of the screen, assuming it is 5 bits
+ * wide. Each letter-number combination is a bit that controls
+ * one pixel.
+ *
+ * A0 A1 A2 A3 A4
+ * B0 B1 B2 B3 B4
+ * C0 C1 C2 C3 C4
+ * D0 D1 D2 D3 D4
+ * E0 E1 E2 E3 E4
+ * F0 F1 F2 F3 F4
+ * G0 G1 G2 G3 G4
+ * H0 H1 H2 H3 H4
+ *
+ * If you want to update this screen, you need to send 5 bytes:
+ * (1) A0 B0 C0 D0 E0 F0 G0 H0
+ * (2) A1 B1 C1 D1 E1 F1 G1 H1
+ * (3) A2 B2 C2 D2 E2 F2 G2 H2
+ * (4) A3 B3 C3 D3 E3 F3 G3 H3
+ * (5) A4 B4 C4 D4 E4 F4 G4 H4
+ */
+
+ for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
+ ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
+ ssd1307fb_write_cmd(par->client, 0x00);
+ ssd1307fb_write_cmd(par->client, 0x10);
+
+ for (j = 0; j < SSD1307FB_WIDTH; j++) {
+ u8 buf = 0;
+ for (k = 0; k < 8; k++) {
+ u32 page_length = SSD1307FB_WIDTH * i;
+ u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
+ u8 byte = *(vmem + index);
+ u8 bit = byte & (1 << (7 - (j % 8)));
+ bit = bit >> (7 - (j % 8));
+ buf |= bit << k;
+ }
+ ssd1307fb_write_data(par->client, buf);
+ }
+ }
+}
+
+
+static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct ssd1307fb_par *par = info->par;
+ unsigned long total_size;
+ unsigned long p = *ppos;
+ u8 __iomem *dst;
+
+ total_size = info->fix.smem_len;
+
+ if (p > total_size)
+ return -EINVAL;
+
+ if (count + p > total_size)
+ count = total_size - p;
+
+ if (!count)
+ return -EINVAL;
+
+ dst = (void __force *) (info->screen_base + p);
+
+ if (copy_from_user(dst, buf, count))
+ return -EFAULT;
+
+ ssd1307fb_update_display(par);
+
+ *ppos += count;
+
+ return count;
+}
+
+static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+ struct ssd1307fb_par *par = info->par;
+ sys_fillrect(info, rect);
+ ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+ struct ssd1307fb_par *par = info->par;
+ sys_copyarea(info, area);
+ ssd1307fb_update_display(par);
+}
+
+static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct ssd1307fb_par *par = info->par;
+ sys_imageblit(info, image);
+ ssd1307fb_update_display(par);
+}
+
+static struct fb_ops ssd1307fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_read = fb_sys_read,
+ .fb_write = ssd1307fb_write,
+ .fb_fillrect = ssd1307fb_fillrect,
+ .fb_copyarea = ssd1307fb_copyarea,
+ .fb_imageblit = ssd1307fb_imageblit,
+};
+
+static void ssd1307fb_deferred_io(struct fb_info *info,
+ struct list_head *pagelist)
+{
+ ssd1307fb_update_display(info->par);
+}
+
+static struct fb_deferred_io ssd1307fb_defio = {
+ .delay = HZ,
+ .deferred_io = ssd1307fb_deferred_io,
+};
+
+static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct fb_info *info;
+ u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
+ struct ssd1307fb_par *par;
+ u8 *vmem;
+ int ret;
+
+ if (!client->dev.of_node) {
+ dev_err(&client->dev, "No device tree data found!\n");
+ return -EINVAL;
+ }
+
+ info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
+ if (!info) {
+ dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
+ return -ENOMEM;
+ }
+
+ vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
+ if (!vmem) {
+ dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
+ ret = -ENOMEM;
+ goto fb_alloc_error;
+ }
+
+ info->fbops = &ssd1307fb_ops;
+ info->fix = ssd1307fb_fix;
+ info->fbdefio = &ssd1307fb_defio;
+
+ info->var = ssd1307fb_var;
+ info->var.red.length = 1;
+ info->var.red.offset = 0;
+ info->var.green.length = 1;
+ info->var.green.offset = 0;
+ info->var.blue.length = 1;
+ info->var.blue.offset = 0;
+
+ info->screen_base = (u8 __force __iomem *)vmem;
+ info->fix.smem_start = (unsigned long)vmem;
+ info->fix.smem_len = vmem_size;
+
+ fb_deferred_io_init(info);
+
+ par = info->par;
+ par->info = info;
+ par->client = client;
+
+ par->reset = of_get_named_gpio(client->dev.of_node,
+ "reset-gpios", 0);
+ if (!gpio_is_valid(par->reset)) {
+ ret = -EINVAL;
+ goto reset_oled_error;
+ }
+
+ ret = devm_gpio_request_one(&client->dev, par->reset,
+ GPIOF_OUT_INIT_HIGH,
+ "oled-reset");
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to request gpio %d: %d\n",
+ par->reset, ret);
+ goto reset_oled_error;
+ }
+
+ par->pwm = pwm_get(&client->dev, NULL);
+ if (IS_ERR(par->pwm)) {
+ dev_err(&client->dev, "Could not get PWM from device tree!\n");
+ ret = PTR_ERR(par->pwm);
+ goto pwm_error;
+ }
+
+ par->pwm_period = pwm_get_period(par->pwm);
+
+ dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
+
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(&client->dev, "Couldn't register the framebuffer\n");
+ goto fbreg_error;
+ }
+
+ i2c_set_clientdata(client, info);
+
+ /* Reset the screen */
+ gpio_set_value(par->reset, 0);
+ udelay(4);
+ gpio_set_value(par->reset, 1);
+ udelay(4);
+
+ /* Enable the PWM */
+ pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+ pwm_enable(par->pwm);
+
+ /* Map column 127 of the OLED to segment 0 */
+ ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
+ if (ret < 0) {
+ dev_err(&client->dev, "Couldn't remap the screen.\n");
+ goto remap_error;
+ }
+
+ /* Turn on the display */
+ ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
+ if (ret < 0) {
+ dev_err(&client->dev, "Couldn't turn the display on.\n");
+ goto remap_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;
+
+remap_error:
+ unregister_framebuffer(info);
+ pwm_disable(par->pwm);
+fbreg_error:
+ pwm_put(par->pwm);
+pwm_error:
+reset_oled_error:
+ fb_deferred_io_cleanup(info);
+fb_alloc_error:
+ framebuffer_release(info);
+ return ret;
+}
+
+static int __devexit ssd1307fb_remove(struct i2c_client *client)
+{
+ struct fb_info *info = i2c_get_clientdata(client);
+ struct ssd1307fb_par *par = info->par;
+
+ unregister_framebuffer(info);
+ pwm_disable(par->pwm);
+ pwm_put(par->pwm);
+ fb_deferred_io_cleanup(info);
+ framebuffer_release(info);
+
+ return 0;
+}
+
+static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+ { "ssd1307fb", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
+
+static const struct of_device_id ssd1307fb_of_match[] = {
+ { .compatible = "solomon,ssd1307fb-i2c" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+
+static struct i2c_driver ssd1307fb_driver = {
+ .probe = ssd1307fb_probe,
+ .remove = __devexit_p(ssd1307fb_remove),
+ .id_table = ssd1307fb_i2c_id,
+ .driver = {
+ .name = "ssd1307fb",
+ .of_match_table = of_match_ptr(ssd1307fb_of_match),
+ .owner = THIS_MODULE,
+ },
+};
+
+module_i2c_driver(ssd1307fb_driver);
+
+MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_LICENSE("GPL");