summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/imx-dma.c3
-rw-r--r--drivers/dma/imx-sdma.c6
-rw-r--r--drivers/gpio/74x164.c (renamed from drivers/gpio/gpio-74x164.c)33
-rw-r--r--drivers/gpio/Kconfig66
-rw-r--r--drivers/gpio/Makefile87
-rw-r--r--drivers/gpio/ab8500-gpio.c (renamed from drivers/gpio/gpio-ab8500.c)0
-rw-r--r--drivers/gpio/adp5520-gpio.c (renamed from drivers/gpio/gpio-adp5520.c)0
-rw-r--r--drivers/gpio/adp5588-gpio.c (renamed from drivers/gpio/gpio-adp5588.c)0
-rw-r--r--drivers/gpio/basic_mmio_gpio.c (renamed from drivers/gpio/gpio-generic.c)6
-rw-r--r--drivers/gpio/bt8xxgpio.c (renamed from drivers/gpio/gpio-bt8xx.c)0
-rw-r--r--drivers/gpio/cs5535-gpio.c (renamed from drivers/gpio/gpio-cs5535.c)0
-rw-r--r--drivers/gpio/gpio-da9052.c277
-rw-r--r--drivers/gpio/gpio-ep93xx.c405
-rw-r--r--drivers/gpio/gpio-exynos4.c5
-rw-r--r--drivers/gpio/gpio-mpc5200.c376
-rw-r--r--drivers/gpio/gpio-mxc.c460
-rw-r--r--drivers/gpio/gpio-mxs.c289
-rw-r--r--drivers/gpio/gpio-omap.c723
-rw-r--r--drivers/gpio/gpio-plat-samsung.c3
-rw-r--r--drivers/gpio/gpio-s5pc100.c5
-rw-r--r--drivers/gpio/gpio-s5pv210.c5
-rw-r--r--drivers/gpio/gpio-tegra.c441
-rw-r--r--drivers/gpio/gpio-u300.c5
-rw-r--r--drivers/gpio/it8761e_gpio.c (renamed from drivers/gpio/gpio-it8761e.c)2
-rw-r--r--drivers/gpio/janz-ttl.c (renamed from drivers/gpio/gpio-janz-ttl.c)0
-rw-r--r--drivers/gpio/langwell_gpio.c (renamed from drivers/gpio/gpio-langwell.c)4
-rw-r--r--drivers/gpio/max7300.c (renamed from drivers/gpio/gpio-max7300.c)2
-rw-r--r--drivers/gpio/max7301.c (renamed from drivers/gpio/gpio-max7301.c)2
-rw-r--r--drivers/gpio/max730x.c (renamed from drivers/gpio/gpio-max730x.c)2
-rw-r--r--drivers/gpio/max732x.c (renamed from drivers/gpio/gpio-max732x.c)2
-rw-r--r--drivers/gpio/mc33880.c (renamed from drivers/gpio/gpio-mc33880.c)2
-rw-r--r--drivers/gpio/mcp23s08.c (renamed from drivers/gpio/gpio-mcp23s08.c)291
-rw-r--r--drivers/gpio/ml_ioh_gpio.c (renamed from drivers/gpio/gpio-ml-ioh.c)2
-rw-r--r--drivers/gpio/pca953x.c (renamed from drivers/gpio/gpio-pca953x.c)105
-rw-r--r--drivers/gpio/pcf857x.c (renamed from drivers/gpio/gpio-pcf857x.c)2
-rw-r--r--drivers/gpio/pch_gpio.c (renamed from drivers/gpio/gpio-pch.c)0
-rw-r--r--drivers/gpio/pl061.c (renamed from drivers/gpio/gpio-pl061.c)4
-rw-r--r--drivers/gpio/rdc321x-gpio.c (renamed from drivers/gpio/gpio-rdc321x.c)0
-rw-r--r--drivers/gpio/sch_gpio.c (renamed from drivers/gpio/gpio-sch.c)2
-rw-r--r--drivers/gpio/stmpe-gpio.c (renamed from drivers/gpio/gpio-stmpe.c)0
-rw-r--r--drivers/gpio/sx150x.c (renamed from drivers/gpio/gpio-sx150x.c)0
-rw-r--r--drivers/gpio/tc3589x-gpio.c (renamed from drivers/gpio/gpio-tc3589x.c)0
-rw-r--r--drivers/gpio/timbgpio.c (renamed from drivers/gpio/gpio-timberdale.c)2
-rw-r--r--drivers/gpio/tps65910-gpio.c (renamed from drivers/gpio/gpio-tps65910.c)2
-rw-r--r--drivers/gpio/twl4030-gpio.c (renamed from drivers/gpio/gpio-twl4030.c)2
-rw-r--r--drivers/gpio/ucb1400_gpio.c (renamed from drivers/gpio/gpio-ucb1400.c)0
-rw-r--r--drivers/gpio/vr41xx_giu.c (renamed from drivers/gpio/gpio-vr41xx.c)2
-rw-r--r--drivers/gpio/vx855_gpio.c (renamed from drivers/gpio/gpio-vx855.c)0
-rw-r--r--drivers/gpio/wm831x-gpio.c (renamed from drivers/gpio/gpio-wm831x.c)2
-rw-r--r--drivers/gpio/wm8350-gpiolib.c (renamed from drivers/gpio/gpio-wm8350.c)2
-rw-r--r--drivers/gpio/wm8994-gpio.c (renamed from drivers/gpio/gpio-wm8994.c)2
-rw-r--r--drivers/gpio/xilinx_gpio.c (renamed from drivers/gpio/gpio-xilinx.c)0
-rw-r--r--drivers/input/misc/Kconfig13
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/twl4030-vibra.c12
-rw-r--r--drivers/input/misc/twl6040-vibra.c423
-rw-r--r--drivers/leds/Kconfig19
-rw-r--r--drivers/leds/leds-gpio.c6
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/twl-core.c13
-rw-r--r--drivers/mfd/twl4030-audio.c277
-rw-r--r--drivers/mfd/twl4030-codec.c277
-rw-r--r--drivers/mfd/twl6040-core.c620
-rw-r--r--drivers/mfd/twl6040-irq.c191
-rw-r--r--drivers/mmc/host/mxcmmc.c8
-rw-r--r--drivers/of/gpio.c11
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c3
-rw-r--r--drivers/pcmcia/pxa2xx_trizeps4.c4
-rw-r--r--drivers/tty/serial/Kconfig15
-rw-r--r--drivers/tty/serial/Makefile2
-rw-r--r--drivers/tty/serial/s3c2400.c105
-rw-r--r--drivers/tty/serial/s3c24a0.c117
-rw-r--r--drivers/video/omap2/displays/Kconfig7
-rw-r--r--drivers/video/omap2/displays/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c591
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-taal.c50
-rw-r--r--drivers/video/omap2/dss/Kconfig12
-rw-r--r--drivers/video/omap2/dss/core.c15
-rw-r--r--drivers/video/omap2/dss/dispc.c484
-rw-r--r--drivers/video/omap2/dss/display.c45
-rw-r--r--drivers/video/omap2/dss/dpi.c73
-rw-r--r--drivers/video/omap2/dss/dsi.c277
-rw-r--r--drivers/video/omap2/dss/dss.c584
-rw-r--r--drivers/video/omap2/dss/dss.h34
-rw-r--r--drivers/video/omap2/dss/dss_features.c13
-rw-r--r--drivers/video/omap2/dss/dss_features.h4
-rw-r--r--drivers/video/omap2/dss/hdmi.c162
-rw-r--r--drivers/video/omap2/dss/manager.c67
-rw-r--r--drivers/video/omap2/dss/overlay.c27
-rw-r--r--drivers/video/omap2/dss/rfbi.c111
-rw-r--r--drivers/video/omap2/dss/sdi.c40
-rw-r--r--drivers/video/omap2/dss/venc.c180
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c72
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c166
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c34
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h37
98 files changed, 2554 insertions, 6579 deletions
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index d99f71c356b..e18eaabe92b 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -135,8 +135,7 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
if (ret)
return ret;
- imx_dma_config_burstlen(imxdmac->imxdma_channel,
- imxdmac->watermark_level * imxdmac->word_size);
+ imx_dma_config_burstlen(imxdmac->imxdma_channel, imxdmac->watermark_level);
return 0;
default:
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 1ea47db2ff0..b6d1455fa93 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1105,7 +1105,7 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
}
static int __init sdma_get_firmware(struct sdma_engine *sdma,
- const char *fw_name)
+ const char *cpu_name, int to_version)
{
const struct firmware *fw;
char *fwname;
@@ -1114,7 +1114,7 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma,
const struct sdma_script_start_addrs *addr;
unsigned short *ram_code;
- fwname = kasprintf(GFP_KERNEL, "%s", fw_name);
+ fwname = kasprintf(GFP_KERNEL, "sdma-%s-to%d.bin", cpu_name, to_version);
if (!fwname)
return -ENOMEM;
@@ -1317,7 +1317,7 @@ static int __init sdma_probe(struct platform_device *pdev)
if (pdata->script_addrs)
sdma_add_scripts(sdma, pdata->script_addrs);
- sdma_get_firmware(sdma, pdata->fw_name);
+ sdma_get_firmware(sdma, pdata->cpu_name, pdata->to_version);
sdma->dma_device.dev = &pdev->dev;
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/74x164.c
index ff525c0958d..84e07021983 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/74x164.c
@@ -16,6 +16,9 @@
#include <linux/gpio.h>
#include <linux/slab.h>
+#define GEN_74X164_GPIO_COUNT 8
+
+
struct gen_74x164_chip {
struct spi_device *spi;
struct gpio_chip gpio_chip;
@@ -23,7 +26,9 @@ struct gen_74x164_chip {
u8 port_config;
};
-static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
+static void gen_74x164_set_value(struct gpio_chip *, unsigned, int);
+
+static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
{
return container_of(gc, struct gen_74x164_chip, gpio_chip);
}
@@ -34,9 +39,16 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
&chip->port_config, sizeof(chip->port_config));
}
+static int gen_74x164_direction_output(struct gpio_chip *gc,
+ unsigned offset, int val)
+{
+ gen_74x164_set_value(gc, offset, val);
+ return 0;
+}
+
static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
{
- struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+ struct gen_74x164_chip *chip = gpio_to_chip(gc);
int ret;
mutex_lock(&chip->lock);
@@ -49,7 +61,7 @@ static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
static void gen_74x164_set_value(struct gpio_chip *gc,
unsigned offset, int val)
{
- struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+ struct gen_74x164_chip *chip = gpio_to_chip(gc);
mutex_lock(&chip->lock);
if (val)
@@ -61,13 +73,6 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
mutex_unlock(&chip->lock);
}
-static int gen_74x164_direction_output(struct gpio_chip *gc,
- unsigned offset, int val)
-{
- gen_74x164_set_value(gc, offset, val);
- return 0;
-}
-
static int __devinit gen_74x164_probe(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
@@ -99,12 +104,12 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
chip->spi = spi;
- chip->gpio_chip.label = spi->modalias;
- chip->gpio_chip.direction_output = gen_74x164_direction_output;
+ chip->gpio_chip.label = GEN_74X164_DRIVER_NAME,
+ chip->gpio_chip.direction_output = gen_74x164_direction_output;
chip->gpio_chip.get = gen_74x164_get_value;
chip->gpio_chip.set = gen_74x164_set_value;
chip->gpio_chip.base = pdata->base;
- chip->gpio_chip.ngpio = 8;
+ chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT;
chip->gpio_chip.can_sleep = 1;
chip->gpio_chip.dev = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
@@ -152,7 +157,7 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
static struct spi_driver gen_74x164_driver = {
.driver = {
- .name = "74x164",
+ .name = GEN_74X164_DRIVER_NAME,
.owner = THIS_MODULE,
},
.probe = gen_74x164_probe,
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 363498697c2..2967002a9f8 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -63,58 +63,33 @@ config GPIO_SYSFS
Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging.
-config GPIO_GENERIC
- tristate
-
# put drivers in the right section, in alphabetical order
-config GPIO_DA9052
- tristate "Dialog DA9052 GPIO"
- depends on PMIC_DA9052
- help
- Say yes here to enable the GPIO driver for the DA9052 chip.
-
config GPIO_MAX730X
tristate
comment "Memory mapped GPIO drivers:"
-config GPIO_GENERIC_PLATFORM
- tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
- select GPIO_GENERIC
+config GPIO_BASIC_MMIO_CORE
+ tristate
+ help
+ Provides core functionality for basic memory-mapped GPIO controllers.
+
+config GPIO_BASIC_MMIO
+ tristate "Basic memory-mapped GPIO controllers support"
+ select GPIO_BASIC_MMIO_CORE
help
- Say yes here to support basic platform_device memory-mapped GPIO controllers.
+ Say yes here to support basic memory-mapped GPIO controllers.
config GPIO_IT8761E
tristate "IT8761E GPIO support"
help
Say yes here to support GPIO functionality of IT8761E super I/O chip.
-config GPIO_EP93XX
- def_bool y
- depends on ARCH_EP93XX
- select GPIO_GENERIC
-
config GPIO_EXYNOS4
def_bool y
depends on CPU_EXYNOS4210
-config GPIO_MPC5200
- def_bool y
- depends on PPC_MPC52xx
-
-config GPIO_MXC
- def_bool y
- depends on ARCH_MXC
- select GPIO_GENERIC
- select GENERIC_IRQ_CHIP
-
-config GPIO_MXS
- def_bool y
- depends on ARCH_MXS
- select GPIO_GENERIC
- select GENERIC_IRQ_CHIP
-
config GPIO_PLAT_SAMSUNG
def_bool y
depends on SAMSUNG_GPIOLIB_4BIT
@@ -162,6 +137,9 @@ config GPIO_SCH
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
+ This driver can also be built as a module. If so, the module
+ will be called sch-gpio.
+
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on MFD_SUPPORT && PCI
@@ -224,6 +202,9 @@ config GPIO_PCA953X
16 bits: pca9535, pca9539, pca9555, tca6416
+ This driver can also be built as a module. If so, the module
+ will be called pca953x.
+
config GPIO_PCA953X_IRQ
bool "Interrupt controller support for PCA953x"
depends on GPIO_PCA953X=y
@@ -315,12 +296,17 @@ config GPIO_ADP5520
This option enables support for on-chip GPIO found
on Analog Devices ADP5520 PMICs.
+ To compile this driver as a module, choose M here: the module will
+ be called adp5520-gpio.
+
config GPIO_ADP5588
tristate "ADP5588 I2C GPIO expander"
depends on I2C
help
This option enables support for 18 GPIOs found
on Analog Devices ADP5588 GPIO Expanders.
+ To compile this driver as a module, choose M here: the module will be
+ called adp5588-gpio.
config GPIO_ADP5588_IRQ
bool "Interrupt controller support for ADP5588"
@@ -412,11 +398,10 @@ config GPIO_MAX7301
GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
config GPIO_MCP23S08
- tristate "Microchip MCP23xxx I/O expander"
- depends on SPI_MASTER || I2C
+ tristate "Microchip MCP23Sxx I/O expander"
+ depends on SPI_MASTER
help
- SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
- I/O expanders.
+ SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
This provides a GPIO interface supporting inputs and outputs.
config GPIO_MC33880
@@ -443,6 +428,9 @@ config GPIO_UCB1400
This enables support for the Philips UCB1400 GPIO pins.
The UCB1400 is an AC97 audio codec.
+ To compile this driver as a module, choose M here: the
+ module will be called ucb1400_gpio.
+
comment "MODULbus GPIO expanders:"
config GPIO_JANZ_TTL
@@ -453,7 +441,7 @@ config GPIO_JANZ_TTL
This driver provides support for driving the pins in output
mode only. Input mode is not supported.
-config GPIO_AB8500
+config AB8500_GPIO
bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
depends on AB8500_CORE && BROKEN
help
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 72071125139..b605f8ec6fb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,56 +4,47 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o
-# Device drivers. Generally keep list sorted alphabetically
-obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
-
-obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
-obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o
-obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
-obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
-obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
-obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
-obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
-obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
+obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
+obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
+obj-$(CONFIG_GPIO_BASIC_MMIO_CORE) += basic_mmio_gpio.o
+obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o
obj-$(CONFIG_GPIO_EXYNOS4) += gpio-exynos4.o
-obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
-obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
-obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o
-obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
-obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
-obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
-obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
-obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
-obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
-obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
-obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
-obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
-obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
-obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
-obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
-obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
-obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
-obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
-obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
-obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
-
obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
obj-$(CONFIG_GPIO_S5PC100) += gpio-s5pc100.o
obj-$(CONFIG_GPIO_S5PV210) += gpio-s5pv210.o
-
-obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
-obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
-obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o
-obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
-obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o
-obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
-obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
-obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
+obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o
+obj-$(CONFIG_GPIO_MAX730X) += max730x.o
+obj-$(CONFIG_GPIO_MAX7300) += max7300.o
+obj-$(CONFIG_GPIO_MAX7301) += max7301.o
+obj-$(CONFIG_GPIO_MAX732X) += max732x.o
+obj-$(CONFIG_GPIO_MC33880) += mc33880.o
+obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
+obj-$(CONFIG_GPIO_74X164) += 74x164.o
+obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
+obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
+obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
+obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
+obj-$(CONFIG_GPIO_PL061) += pl061.o
+obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
+obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o
+obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o
+obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o
+obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
+obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
+obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o
+obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
+obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
+obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
+obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
+obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
+obj-$(CONFIG_GPIO_SCH) += sch_gpio.o
obj-$(CONFIG_MACH_U300) += gpio-u300.o
-obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
-obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
-obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
-obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
-obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
-obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
-obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
+obj-$(CONFIG_PLAT_NOMADIK) += gpio-nomadik.o
+obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o
+obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o
+obj-$(CONFIG_GPIO_SX150X) += sx150x.o
+obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
+obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
+obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
+obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/ab8500-gpio.c
index 970053c89ff..970053c89ff 100644
--- a/drivers/gpio/gpio-ab8500.c
+++ b/drivers/gpio/ab8500-gpio.c
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/adp5520-gpio.c
index 9f278153700..9f278153700 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/adp5520-gpio.c
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/adp5588-gpio.c
index 3525ad91877..3525ad91877 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/adp5588-gpio.c
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/basic_mmio_gpio.c
index 231714def4d..8152e9f516b 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/basic_mmio_gpio.c
@@ -1,5 +1,5 @@
/*
- * Generic driver for memory-mapped GPIO controllers.
+ * Driver for basic memory-mapped GPIO controllers.
*
* Copyright 2008 MontaVista Software, Inc.
* Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
@@ -404,7 +404,7 @@ int __devinit bgpio_init(struct bgpio_chip *bgc,
}
EXPORT_SYMBOL_GPL(bgpio_init);
-#ifdef CONFIG_GPIO_GENERIC_PLATFORM
+#ifdef CONFIG_GPIO_BASIC_MMIO
static void __iomem *bgpio_map(struct platform_device *pdev,
const char *name,
@@ -541,7 +541,7 @@ static void __exit bgpio_platform_exit(void)
}
module_exit(bgpio_platform_exit);
-#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
+#endif /* CONFIG_GPIO_BASIC_MMIO */
MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/bt8xxgpio.c
index aa4f09ad3ce..aa4f09ad3ce 100644
--- a/drivers/gpio/gpio-bt8xx.c
+++ b/drivers/gpio/bt8xxgpio.c
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/cs5535-gpio.c
index 6e16cba56ad..6e16cba56ad 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/cs5535-gpio.c
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
deleted file mode 100644
index 038f5eb8b13..00000000000
--- a/drivers/gpio/gpio-da9052.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * GPIO Driver for Dialog DA9052 PMICs.
- *
- * Copyright(c) 2011 Dialog Semiconductor Ltd.
- *
- * Author: David Dajun Chen <dchen@diasemi.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/syscalls.h>
-#include <linux/seq_file.h>
-
-#include <linux/mfd/da9052/da9052.h>
-#include <linux/mfd/da9052/reg.h>
-#include <linux/mfd/da9052/pdata.h>
-#include <linux/mfd/da9052/gpio.h>
-
-#define DA9052_INPUT 1
-#define DA9052_OUTPUT_OPENDRAIN 2
-#define DA9052_OUTPUT_PUSHPULL 3
-
-#define DA9052_SUPPLY_VDD_IO1 0
-
-#define DA9052_DEBOUNCING_OFF 0
-#define DA9052_DEBOUNCING_ON 1
-
-#define DA9052_OUTPUT_LOWLEVEL 0
-
-#define DA9052_ACTIVE_LOW 0
-#define DA9052_ACTIVE_HIGH 1
-
-#define DA9052_GPIO_MAX_PORTS_PER_REGISTER 8
-#define DA9052_GPIO_SHIFT_COUNT(no) (no%8)
-#define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0
-#define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F
-#define DA9052_GPIO_NIBBLE_SHIFT 4
-
-struct da9052_gpio {
- struct da9052 *da9052;
- struct gpio_chip gp;
-};
-
-static inline struct da9052_gpio *to_da9052_gpio(struct gpio_chip *chip)
-{
- return container_of(chip, struct da9052_gpio, gp);
-}
-
-static unsigned char da9052_gpio_port_odd(unsigned offset)
-{
- return offset % 2;
-}
-
-static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
- struct da9052_gpio *gpio = to_da9052_gpio(gc);
- int da9052_port_direction = 0;
- int ret;
-
- ret = da9052_reg_read(gpio->da9052,
- DA9052_GPIO_0_1_REG + (offset >> 1));
- if (ret < 0)
- return ret;
-
- if (da9052_gpio_port_odd(offset)) {
- da9052_port_direction = ret & DA9052_GPIO_ODD_PORT_PIN;
- da9052_port_direction >>= 4;
- } else {
- da9052_port_direction = ret & DA9052_GPIO_EVEN_PORT_PIN;
- }
-
- switch (da9052_port_direction) {
- case DA9052_INPUT:
- if (offset < DA9052_GPIO_MAX_PORTS_PER_REGISTER)
- ret = da9052_reg_read(gpio->da9052,
- DA9052_STATUS_C_REG);
- else
- ret = da9052_reg_read(gpio->da9052,
- DA9052_STATUS_D_REG);
- if (ret < 0)
- return ret;
- if (ret & (1 << DA9052_GPIO_SHIFT_COUNT(offset)))
- return 1;
- else
- return 0;
- case DA9052_OUTPUT_PUSHPULL:
- if (da9052_gpio_port_odd(offset))
- return ret & DA9052_GPIO_ODD_PORT_MODE;
- else
- return ret & DA9052_GPIO_EVEN_PORT_MODE;
- default:
- return -EINVAL;
- }
-}
-
-static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
-{
- struct da9052_gpio *gpio = to_da9052_gpio(gc);
- unsigned char register_value = 0;
- int ret;
-
- if (da9052_gpio_port_odd(offset)) {
- if (value) {
- register_value = DA9052_GPIO_ODD_PORT_MODE;
- ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
- DA9052_GPIO_0_1_REG,
- DA9052_GPIO_ODD_PORT_MODE,
- register_value);
- if (ret != 0)
- dev_err(gpio->da9052->dev,
- "Failed to updated gpio odd reg,%d",
- ret);
- }
- } else {
- if (value) {
- register_value = DA9052_GPIO_EVEN_PORT_MODE;
- ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
- DA9052_GPIO_0_1_REG,
- DA9052_GPIO_EVEN_PORT_MODE,
- register_value);
- if (ret != 0)
- dev_err(gpio->da9052->dev,
- "Failed to updated gpio even reg,%d",
- ret);
- }
- }
-}
-
-static int da9052_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
- struct da9052_gpio *gpio = to_da9052_gpio(gc);
- unsigned char register_value;
- int ret;
-
- /* Format: function - 2 bits type - 1 bit mode - 1 bit */
- register_value = DA9052_INPUT | DA9052_ACTIVE_LOW << 2 |
- DA9052_DEBOUNCING_ON << 3;
-
- if (da9052_gpio_port_odd(offset))
- ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
- DA9052_GPIO_0_1_REG,
- DA9052_GPIO_MASK_UPPER_NIBBLE,
- (register_value <<
- DA9052_GPIO_NIBBLE_SHIFT));
- else
- ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
- DA9052_GPIO_0_1_REG,
- DA9052_GPIO_MASK_LOWER_NIBBLE,
- register_value);
-
- return ret;
-}
-
-static int da9052_gpio_direction_output(struct gpio_chip *gc,
- unsigned offset, int value)
-{
- struct da9052_gpio *gpio = to_da9052_gpio(gc);
- unsigned char register_value;
- int ret;
-
- /* Format: Function - 2 bits Type - 1 bit Mode - 1 bit */
- register_value = DA9052_OUTPUT_PUSHPULL | DA9052_SUPPLY_VDD_IO1 << 2 |
- value << 3;
-
- if (da9052_gpio_port_odd(offset))
- ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
- DA9052_GPIO_0_1_REG,
- DA9052_GPIO_MASK_UPPER_NIBBLE,
- (register_value <<
- DA9052_GPIO_NIBBLE_SHIFT));
- else
- ret = da9052_reg_update(gpio->da9052, (offset >> 1) +
- DA9052_GPIO_0_1_REG,
- DA9052_GPIO_MASK_LOWER_NIBBLE,
- register_value);
-
- return ret;
-}
-
-static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
-{
- struct da9052_gpio *gpio = to_da9052_gpio(gc);
- struct da9052 *da9052 = gpio->da9052;
-
- return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
-}
-
-static struct gpio_chip reference_gp __devinitdata = {
- .label = "da9052-gpio",
- .owner = THIS_MODULE,
- .get = da9052_gpio_get,
- .set = da9052_gpio_set,
- .direction_input = da9052_gpio_direction_input,
- .direction_output = da9052_gpio_direction_output,
- .to_irq = da9052_gpio_to_irq,
- .can_sleep = 1;
- .ngpio = 16;
- .base = -1;
-};
-
-static int __devinit da9052_gpio_probe(struct platform_device *pdev)
-{
- struct da9052_gpio *gpio;
- struct da9052_pdata *pdata;
- int ret;
-
- gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
- if (gpio == NULL)
- return -ENOMEM;
-
- gpio->da9052 = dev_get_drvdata(pdev->dev.parent);
- pdata = gpio->da9052->dev->platform_data;
-
- gpio->gp = reference_gp;
- if (pdata && pdata->gpio_base)
- gpio->gp.base = pdata->gpio_base;
-
- ret = gpiochip_add(&gpio->gp);
- if (ret < 0) {
- dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
- goto err_mem;
- }
-
- platform_set_drvdata(pdev, gpio);
-
- return 0;
-
-err_mem:
- kfree(gpio);
- return ret;
-}
-
-static int __devexit da9052_gpio_remove(struct platform_device *pdev)
-{
- struct da9052_gpio *gpio = platform_get_drvdata(pdev);
- int ret;
-
- ret = gpiochip_remove(&gpio->gp);
- if (ret == 0)
- kfree(gpio);
-
- return ret;
-}
-
-static struct platform_driver da9052_gpio_driver = {
- .probe = da9052_gpio_probe,
- .remove = __devexit_p(da9052_gpio_remove),
- .driver = {
- .name = "da9052-gpio",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init da9052_gpio_init(void)
-{
- return platform_driver_register(&da9052_gpio_driver);
-}
-module_init(da9052_gpio_init);
-
-static void __exit da9052_gpio_exit(void)
-{
- return platform_driver_unregister(&da9052_gpio_driver);
-}
-module_exit(da9052_gpio_exit);
-
-MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
-MODULE_DESCRIPTION("DA9052 GPIO Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:da9052-gpio");
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
deleted file mode 100644
index 3bfd3417ab1..00000000000
--- a/drivers/gpio/gpio-ep93xx.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Generic EP93xx GPIO handling
- *
- * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com>
- * Copyright (c) 2011 H Hartley Sweeten <hsweeten@visionengravers.com>
- *
- * Based on code originally from:
- * linux/arch/arm/mach-ep93xx/core.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
- * published by the Free Software Foundation.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/basic_mmio_gpio.h>
-
-#include <mach/hardware.h>
-
-struct ep93xx_gpio {
- void __iomem *mmio_base;
- struct bgpio_chip bgc[8];
-};
-
-/*************************************************************************
- * Interrupt handling for EP93xx on-chip GPIOs
- *************************************************************************/
-static unsigned char gpio_int_unmasked[3];
-static unsigned char gpio_int_enabled[3];
-static unsigned char gpio_int_type1[3];
-static unsigned char gpio_int_type2[3];
-static unsigned char gpio_int_debounce[3];
-
-/* Port ordering is: A B F */
-static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c };
-static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 };
-static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
-static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
-static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
-
-static void ep93xx_gpio_update_int_params(unsigned port)
-{
- BUG_ON(port > 2);
-
- __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
-
- __raw_writeb(gpio_int_type2[port],
- EP93XX_GPIO_REG(int_type2_register_offset[port]));
-
- __raw_writeb(gpio_int_type1[port],
- EP93XX_GPIO_REG(int_type1_register_offset[port]));
-
- __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
- EP93XX_GPIO_REG(int_en_register_offset[port]));
-}
-
-static inline void ep93xx_gpio_int_mask(unsigned line)
-{
- gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
-}
-
-static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
-{
- int line = irq_to_gpio(irq);
- int port = line >> 3;
- int port_mask = 1 << (line & 7);
-
- if (enable)
- gpio_int_debounce[port] |= port_mask;
- else
- gpio_int_debounce[port] &= ~port_mask;
-
- __raw_writeb(gpio_int_debounce[port],
- EP93XX_GPIO_REG(int_debounce_register_offset[port]));
-}
-
-static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- unsigned char status;
- int i;
-
- status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
- for (i = 0; i < 8; i++) {
- if (status & (1 << i)) {
- int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
- generic_handle_irq(gpio_irq);
- }
- }
-
- status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
- for (i = 0; i < 8; i++) {
- if (status & (1 << i)) {
- int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
- generic_handle_irq(gpio_irq);
- }
- }
-}
-
-static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- /*
- * map discontiguous hw irq range to continuous sw irq range:
- *
- * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
- */
- int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
- int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
-
- generic_handle_irq(gpio_irq);
-}
-
-static void ep93xx_gpio_irq_ack(struct irq_data *d)
-{
- int line = irq_to_gpio(d->irq);
- int port = line >> 3;
- int port_mask = 1 << (line & 7);
-
- if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
- gpio_int_type2[port] ^= port_mask; /* switch edge direction */
- ep93xx_gpio_update_int_params(port);
- }
-
- __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
-}
-
-static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
-{
- int line = irq_to_gpio(d->irq);
- int port = line >> 3;
- int port_mask = 1 << (line & 7);
-
- if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
- gpio_int_type2[port] ^= port_mask; /* switch edge direction */
-
- gpio_int_unmasked[port] &= ~port_mask;
- ep93xx_gpio_update_int_params(port);
-
- __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
-}
-
-static void ep93xx_gpio_irq_mask(struct irq_data *d)
-{
- int line = irq_to_gpio(d->irq);
- int port = line >> 3;
-
- gpio_int_unmasked[port] &= ~(1 << (line & 7));
- ep93xx_gpio_update_int_params(port);
-}
-
-static void ep93xx_gpio_irq_unmask(struct irq_data *d)
-{
- int line = irq_to_gpio(d->irq);
- int port = line >> 3;
-
- gpio_int_unmasked[port] |= 1 << (line & 7);
- ep93xx_gpio_update_int_params(port);
-}
-
-/*
- * gpio_int_type1 controls whether the interrupt is level (0) or
- * edge (1) triggered, while gpio_int_type2 controls whether it
- * triggers on low/falling (0) or high/rising (1).
- */
-static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
- const int gpio = irq_to_gpio(d->irq);
- const int port = gpio >> 3;
- const int port_mask = 1 << (gpio & 7);
- irq_flow_handler_t handler;
-
- gpio_direction_input(gpio);
-
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- gpio_int_type1[port] |= port_mask;
- gpio_int_type2[port] |= port_mask;
- handler = handle_edge_irq;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- gpio_int_type1[port] |= port_mask;
- gpio_int_type2[port] &= ~port_mask;
- handler = handle_edge_irq;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- gpio_int_type1[port] &= ~port_mask;
- gpio_int_type2[port] |= port_mask;
- handler = handle_level_irq;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- gpio_int_type1[port] &= ~port_mask;
- gpio_int_type2[port] &= ~port_mask;
- handler = handle_level_irq;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- gpio_int_type1[port] |= port_mask;
- /* set initial polarity based on current input level */
- if (gpio_get_value(gpio))
- gpio_int_type2[port] &= ~port_mask; /* falling */
- else
- gpio_int_type2[port] |= port_mask; /* rising */
- handler = handle_edge_irq;
- break;
- default:
- pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
- return -EINVAL;
- }
-
- __irq_set_handler_locked(d->irq, handler);
-
- gpio_int_enabled[port] |= port_mask;
-
- ep93xx_gpio_update_int_params(port);
-
- return 0;
-}
-
-static struct irq_chip ep93xx_gpio_irq_chip = {
- .name = "GPIO",
- .irq_ack = ep93xx_gpio_irq_ack,
- .irq_mask_ack = ep93xx_gpio_irq_mask_ack,
- .irq_mask = ep93xx_gpio_irq_mask,
- .irq_unmask = ep93xx_gpio_irq_unmask,
- .irq_set_type = ep93xx_gpio_irq_type,
-};
-
-static void ep93xx_gpio_init_irq(void)
-{
- int gpio_irq;
-
- for (gpio_irq = gpio_to_irq(0);
- gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
- irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(gpio_irq, IRQF_VALID);
- }
-
- irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
- ep93xx_gpio_ab_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
- ep93xx_gpio_f_irq_handler);
- irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
- ep93xx_gpio_f_irq_handler);
-}
-
-
-/*************************************************************************
- * gpiolib interface for EP93xx on-chip GPIOs
- *************************************************************************/
-struct ep93xx_gpio_bank {
- const char *label;
- int data;
- int dir;
- int base;
- bool has_debounce;
-};
-
-#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _debounce) \
- { \
- .label = _label, \
- .data = _data, \
- .dir = _dir, \
- .base = _base, \
- .has_debounce = _debounce, \
- }
-
-static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
- EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true),
- EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true),
- EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false),
- EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false),
- EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false),
- EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true),
- EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false),
- EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false),
-};
-
-static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
- unsigned offset, unsigned debounce)
-{
- int gpio = chip->base + offset;
- int irq = gpio_to_irq(gpio);
-
- if (irq < 0)
- return -EINVAL;
-
- ep93xx_gpio_int_debounce(irq, debounce ? true : false);
-
- return 0;
-}
-
-static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
- void __iomem *mmio_base, struct ep93xx_gpio_bank *bank)
-{
- void __iomem *data = mmio_base + bank->data;
- void __iomem *dir = mmio_base + bank->dir;
- int err;
-
- err = bgpio_init(bgc, dev, 1, data, NULL, NULL, dir, NULL, false);
- if (err)
- return err;
-
- bgc->gc.label = bank->label;
- bgc->gc.base = bank->base;
-
- if (bank->has_debounce)
- bgc->gc.set_debounce = ep93xx_gpio_set_debounce;
-
- return gpiochip_add(&bgc->gc);
-}
-
-static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
-{
- struct ep93xx_gpio *ep93xx_gpio;
- struct resource *res;
- void __iomem *mmio;
- int i;
- int ret;
-
- ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
- if (!ep93xx_gpio)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -ENXIO;
- goto exit_free;
- }
-
- if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
- ret = -EBUSY;
- goto exit_free;
- }
-
- mmio = ioremap(res->start, resource_size(res));
- if (!mmio) {
- ret = -ENXIO;
- goto exit_release;
- }
- ep93xx_gpio->mmio_base = mmio;
-
- /* Default all ports to GPIO */
- ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
- EP93XX_SYSCON_DEVCFG_GONK |
- EP93XX_SYSCON_DEVCFG_EONIDE |
- EP93XX_SYSCON_DEVCFG_GONIDE |
- EP93XX_SYSCON_DEVCFG_HONIDE);
-
- for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
- struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
- struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
-
- if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
- dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
- bank->label);
- }
-
- ep93xx_gpio_init_irq();
-
- return 0;
-
-exit_release:
- release_mem_region(res->start, resource_size(res));
-exit_free:
- kfree(ep93xx_gpio);
- dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
- return ret;
-}
-
-static struct platform_driver ep93xx_gpio_driver = {
- .driver = {
- .name = "gpio-ep93xx",
- .owner = THIS_MODULE,
- },
- .probe = ep93xx_gpio_probe,
-};
-
-static int __init ep93xx_gpio_init(void)
-{
- return platform_driver_register(&ep93xx_gpio_driver);
-}
-postcore_initcall(ep93xx_gpio_init);
-
-MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com> "
- "H Hartley Sweeten <hsweeten@visionengravers.com>");
-MODULE_DESCRIPTION("EP93XX GPIO driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
index d24b337cf1a..9029835112e 100644
--- a/drivers/gpio/gpio-exynos4.c
+++ b/drivers/gpio/gpio-exynos4.c
@@ -1,9 +1,10 @@
-/*
- * EXYNOS4 - GPIOlib support
+/* linux/arch/arm/mach-exynos4/gpiolib.c
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
+ * EXYNOS4 - GPIOlib support
+ *
* 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.
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
deleted file mode 100644
index 52d3ed20810..00000000000
--- a/drivers/gpio/gpio-mpc5200.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * MPC52xx gpio driver
- *
- * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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
- */
-
-#include <linux/of.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/of_gpio.h>
-#include <linux/io.h>
-#include <linux/of_platform.h>
-
-#include <asm/gpio.h>
-#include <asm/mpc52xx.h>
-#include <sysdev/fsl_soc.h>
-
-static DEFINE_SPINLOCK(gpio_lock);
-
-struct mpc52xx_gpiochip {
- struct of_mm_gpio_chip mmchip;
- unsigned int shadow_dvo;
- unsigned int shadow_gpioe;
- unsigned int shadow_ddr;
-};
-
-/*
- * GPIO LIB API implementation for wakeup GPIOs.
- *
- * There's a maximum of 8 wakeup GPIOs. Which of these are available
- * for use depends on your board setup.
- *
- * 0 -> GPIO_WKUP_7
- * 1 -> GPIO_WKUP_6
- * 2 -> PSC6_1
- * 3 -> PSC6_0
- * 4 -> ETH_17
- * 5 -> PSC3_9
- * 6 -> PSC2_4
- * 7 -> PSC1_4
- *
- */
-static int mpc52xx_wkup_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
- unsigned int ret;
-
- ret = (in_8(&regs->wkup_ival) >> (7 - gpio)) & 1;
-
- pr_debug("%s: gpio: %d ret: %d\n", __func__, gpio, ret);
-
- return ret;
-}
-
-static inline void
-__mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpiochip *chip = container_of(mm_gc,
- struct mpc52xx_gpiochip, mmchip);
- struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
-
- if (val)
- chip->shadow_dvo |= 1 << (7 - gpio);
- else
- chip->shadow_dvo &= ~(1 << (7 - gpio));
-
- out_8(&regs->wkup_dvo, chip->shadow_dvo);
-}
-
-static void
-mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- __mpc52xx_wkup_gpio_set(gc, gpio, val);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-}
-
-static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpiochip *chip = container_of(mm_gc,
- struct mpc52xx_gpiochip, mmchip);
- struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- /* set the direction */
- chip->shadow_ddr &= ~(1 << (7 - gpio));
- out_8(&regs->wkup_ddr, chip->shadow_ddr);
-
- /* and enable the pin */
- chip->shadow_gpioe |= 1 << (7 - gpio);
- out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- return 0;
-}
-
-static int
-mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpio_wkup __iomem *regs = mm_gc->regs;
- struct mpc52xx_gpiochip *chip = container_of(mm_gc,
- struct mpc52xx_gpiochip, mmchip);
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- __mpc52xx_wkup_gpio_set(gc, gpio, val);
-
- /* Then set direction */
- chip->shadow_ddr |= 1 << (7 - gpio);
- out_8(&regs->wkup_ddr, chip->shadow_ddr);
-
- /* Finally enable the pin */
- chip->shadow_gpioe |= 1 << (7 - gpio);
- out_8(&regs->wkup_gpioe, chip->shadow_gpioe);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-
- return 0;
-}
-
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
-{
- struct mpc52xx_gpiochip *chip;
- struct mpc52xx_gpio_wkup __iomem *regs;
- struct gpio_chip *gc;
- int ret;
-
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- gc = &chip->mmchip.gc;
-
- gc->ngpio = 8;
- gc->direction_input = mpc52xx_wkup_gpio_dir_in;
- gc->direction_output = mpc52xx_wkup_gpio_dir_out;
- gc->get = mpc52xx_wkup_gpio_get;
- gc->set = mpc52xx_wkup_gpio_set;
-
- ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip);
- if (ret)
- return ret;
-
- regs = chip->mmchip.regs;
- chip->shadow_gpioe = in_8(&regs->wkup_gpioe);
- chip->shadow_ddr = in_8(&regs->wkup_ddr);
- chip->shadow_dvo = in_8(&regs->wkup_dvo);
-
- return 0;
-}
-
-static int mpc52xx_gpiochip_remove(struct platform_device *ofdev)
-{
- return -EBUSY;
-}
-
-static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
- { .compatible = "fsl,mpc5200-gpio-wkup", },
- {}
-};
-
-static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
- .driver = {
- .name = "mpc5200-gpio-wkup",
- .owner = THIS_MODULE,
- .of_match_table = mpc52xx_wkup_gpiochip_match,
- },
- .probe = mpc52xx_wkup_gpiochip_probe,
- .remove = mpc52xx_gpiochip_remove,
-};
-
-/*
- * GPIO LIB API implementation for simple GPIOs
- *
- * There's a maximum of 32 simple GPIOs. Which of these are available
- * for use depends on your board setup.
- * The numbering reflects the bit numbering in the port registers:
- *
- * 0..1 > reserved
- * 2..3 > IRDA
- * 4..7 > ETHR
- * 8..11 > reserved
- * 12..15 > USB
- * 16..17 > reserved
- * 18..23 > PSC3
- * 24..27 > PSC2
- * 28..31 > PSC1
- */
-static int mpc52xx_simple_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
- unsigned int ret;
-
- ret = (in_be32(&regs->simple_ival) >> (31 - gpio)) & 1;
-
- return ret;
-}
-
-static inline void
-__mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpiochip *chip = container_of(mm_gc,
- struct mpc52xx_gpiochip, mmchip);
- struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
-
- if (val)
- chip->shadow_dvo |= 1 << (31 - gpio);
- else
- chip->shadow_dvo &= ~(1 << (31 - gpio));
- out_be32(&regs->simple_dvo, chip->shadow_dvo);
-}
-
-static void
-mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- __mpc52xx_simple_gpio_set(gc, gpio, val);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-}
-
-static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpiochip *chip = container_of(mm_gc,
- struct mpc52xx_gpiochip, mmchip);
- struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- /* set the direction */
- chip->shadow_ddr &= ~(1 << (31 - gpio));
- out_be32(&regs->simple_ddr, chip->shadow_ddr);
-
- /* and enable the pin */
- chip->shadow_gpioe |= 1 << (31 - gpio);
- out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- return 0;
-}
-
-static int
-mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
- struct mpc52xx_gpiochip *chip = container_of(mm_gc,
- struct mpc52xx_gpiochip, mmchip);
- struct mpc52xx_gpio __iomem *regs = mm_gc->regs;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- /* First set initial value */
- __mpc52xx_simple_gpio_set(gc, gpio, val);
-
- /* Then set direction */
- chip->shadow_ddr |= 1 << (31 - gpio);
- out_be32(&regs->simple_ddr, chip->shadow_ddr);
-
- /* Finally enable the pin */
- chip->shadow_gpioe |= 1 << (31 - gpio);
- out_be32(&regs->simple_gpioe, chip->shadow_gpioe);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
-
- return 0;
-}
-
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
-{
- struct mpc52xx_gpiochip *chip;
- struct gpio_chip *gc;
- struct mpc52xx_gpio __iomem *regs;
- int ret;
-
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- gc = &chip->mmchip.gc;
-
- gc->ngpio = 32;
- gc->direction_input = mpc52xx_simple_gpio_dir_in;
- gc->direction_output = mpc52xx_simple_gpio_dir_out;
- gc->get = mpc52xx_simple_gpio_get;
- gc->set = mpc52xx_simple_gpio_set;
-
- ret = of_mm_gpiochip_add(ofdev->dev.of_node, &chip->mmchip);
- if (ret)
- return ret;
-
- regs = chip->mmchip.regs;
- chip->shadow_gpioe = in_be32(&regs->simple_gpioe);
- chip->shadow_ddr = in_be32(&regs->simple_ddr);
- chip->shadow_dvo = in_be32(&regs->simple_dvo);
-
- return 0;
-}
-
-static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
- { .compatible = "fsl,mpc5200-gpio", },
- {}
-};
-
-static struct platform_driver mpc52xx_simple_gpiochip_driver = {
- .driver = {
- .name = "mpc5200-gpio",
- .owner = THIS_MODULE,
- .of_match_table = mpc52xx_simple_gpiochip_match,
- },
- .probe = mpc52xx_simple_gpiochip_probe,
- .remove = mpc52xx_gpiochip_remove,
-};
-
-static int __init mpc52xx_gpio_init(void)
-{
- if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver))
- printk(KERN_ERR "Unable to register wakeup GPIO driver\n");
-
- if (platform_driver_register(&mpc52xx_simple_gpiochip_driver))
- printk(KERN_ERR "Unable to register simple GPIO driver\n");
-
- return 0;
-}
-
-
-/* Make sure we get initialised before anyone else tries to use us */
-subsys_initcall(mpc52xx_gpio_init);
-
-/* No exit call at the moment as we cannot unregister of gpio chips */
-
-MODULE_DESCRIPTION("Freescale MPC52xx gpio driver");
-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
-MODULE_LICENSE("GPL v2");
-
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
deleted file mode 100644
index 89fda58db90..00000000000
--- a/drivers/gpio/gpio-mxc.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/basic_mmio_gpio.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <asm-generic/bug.h>
-
-enum mxc_gpio_hwtype {
- IMX1_GPIO, /* runs on i.mx1 */
- IMX21_GPIO, /* runs on i.mx21 and i.mx27 */
- IMX31_GPIO, /* runs on all other i.mx */
-};
-
-/* device type dependent stuff */
-struct mxc_gpio_hwdata {
- unsigned dr_reg;
- unsigned gdir_reg;
- unsigned psr_reg;
- unsigned icr1_reg;
- unsigned icr2_reg;
- unsigned imr_reg;
- unsigned isr_reg;
- unsigned low_level;
- unsigned high_level;
- unsigned rise_edge;
- unsigned fall_edge;
-};
-
-struct mxc_gpio_port {
- struct list_head node;
- void __iomem *base;
- int irq;
- int irq_high;
- int virtual_irq_start;
- struct bgpio_chip bgc;
- u32 both_edges;
-};
-
-static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
- .dr_reg = 0x1c,
- .gdir_reg = 0x00,
- .psr_reg = 0x24,
- .icr1_reg = 0x28,
- .icr2_reg = 0x2c,
- .imr_reg = 0x30,
- .isr_reg = 0x34,
- .low_level = 0x03,
- .high_level = 0x02,
- .rise_edge = 0x00,
- .fall_edge = 0x01,
-};
-
-static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
- .dr_reg = 0x00,
- .gdir_reg = 0x04,
- .psr_reg = 0x08,
- .icr1_reg = 0x0c,
- .icr2_reg = 0x10,
- .imr_reg = 0x14,
- .isr_reg = 0x18,
- .low_level = 0x00,
- .high_level = 0x01,
- .rise_edge = 0x02,
- .fall_edge = 0x03,
-};
-
-static enum mxc_gpio_hwtype mxc_gpio_hwtype;
-static struct mxc_gpio_hwdata *mxc_gpio_hwdata;
-
-#define GPIO_DR (mxc_gpio_hwdata->dr_reg)
-#define GPIO_GDIR (mxc_gpio_hwdata->gdir_reg)
-#define GPIO_PSR (mxc_gpio_hwdata->psr_reg)
-#define GPIO_ICR1 (mxc_gpio_hwdata->icr1_reg)
-#define GPIO_ICR2 (mxc_gpio_hwdata->icr2_reg)
-#define GPIO_IMR (mxc_gpio_hwdata->imr_reg)
-#define GPIO_ISR (mxc_gpio_hwdata->isr_reg)
-
-#define GPIO_INT_LOW_LEV (mxc_gpio_hwdata->low_level)
-#define GPIO_INT_HIGH_LEV (mxc_gpio_hwdata->high_level)
-#define GPIO_INT_RISE_EDGE (mxc_gpio_hwdata->rise_edge)
-#define GPIO_INT_FALL_EDGE (mxc_gpio_hwdata->fall_edge)
-#define GPIO_INT_NONE 0x4
-
-static struct platform_device_id mxc_gpio_devtype[] = {
- {
- .name = "imx1-gpio",
- .driver_data = IMX1_GPIO,
- }, {
- .name = "imx21-gpio",
- .driver_data = IMX21_GPIO,
- }, {
- .name = "imx31-gpio",
- .driver_data = IMX31_GPIO,
- }, {
- /* sentinel */
- }
-};
-
-static const struct of_device_id mxc_gpio_dt_ids[] = {
- { .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
- { .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
- { .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
- { /* sentinel */ }
-};
-
-/*
- * MX2 has one interrupt *for all* gpio ports. The list is used
- * to save the references to all ports, so that mx2_gpio_irq_handler
- * can walk through all interrupt status registers.
- */
-static LIST_HEAD(mxc_gpio_ports);
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static int gpio_set_irq_type(struct irq_data *d, u32 type)
-{
- u32 gpio = irq_to_gpio(d->irq);
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct mxc_gpio_port *port = gc->private;
- u32 bit, val;
- int edge;
- void __iomem *reg = port->base;
-
- port->both_edges &= ~(1 << (gpio & 31));
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- edge = GPIO_INT_RISE_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- edge = GPIO_INT_FALL_EDGE;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- val = gpio_get_value(gpio);
- if (val) {
- edge = GPIO_INT_LOW_LEV;
- pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
- } else {
- edge = GPIO_INT_HIGH_LEV;
- pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
- }
- port->both_edges |= 1 << (gpio & 31);
- break;
- case IRQ_TYPE_LEVEL_LOW:
- edge = GPIO_INT_LOW_LEV;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- edge = GPIO_INT_HIGH_LEV;
- break;
- default:
- return -EINVAL;
- }
-
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = readl(reg) & ~(0x3 << (bit << 1));
- writel(val | (edge << (bit << 1)), reg);
- writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
-
- return 0;
-}
-
-static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
-{
- void __iomem *reg = port->base;
- u32 bit, val;
- int edge;
-
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = readl(reg);
- edge = (val >> (bit << 1)) & 3;
- val &= ~(0x3 << (bit << 1));
- if (edge == GPIO_INT_HIGH_LEV) {
- edge = GPIO_INT_LOW_LEV;
- pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
- } else if (edge == GPIO_INT_LOW_LEV) {
- edge = GPIO_INT_HIGH_LEV;
- pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
- } else {
- pr_err("mxc: invalid configuration for GPIO %d: %x\n",
- gpio, edge);
- return;
- }
- writel(val | (edge << (bit << 1)), reg);
-}
-
-/* handle 32 interrupts in one status register */
-static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
-{
- u32 gpio_irq_no_base = port->virtual_irq_start;
-
- while (irq_stat != 0) {
- int irqoffset = fls(irq_stat) - 1;
-
- if (port->both_edges & (1 << irqoffset))
- mxc_flip_edge(port, irqoffset);
-
- generic_handle_irq(gpio_irq_no_base + irqoffset);
-
- irq_stat &= ~(1 << irqoffset);
- }
-}
-
-/* MX1 and MX3 has one interrupt *per* gpio port */
-static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- u32 irq_stat;
- struct mxc_gpio_port *port = irq_get_handler_data(irq);
-
- irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
-
- mxc_gpio_irq_handler(port, irq_stat);
-}
-
-/* MX2 has one interrupt *for all* gpio ports */
-static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- u32 irq_msk, irq_stat;
- struct mxc_gpio_port *port;
-
- /* walk through all interrupt status registers */
- list_for_each_entry(port, &mxc_gpio_ports, node) {
- irq_msk = readl(port->base + GPIO_IMR);
- if (!irq_msk)
- continue;
-
- irq_stat = readl(port->base + GPIO_ISR) & irq_msk;
- if (irq_stat)
- mxc_gpio_irq_handler(port, irq_stat);
- }
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param irq interrupt source number
- * @param enable enable as wake-up if equal to non-zero
- * @return This function returns 0 on success.
- */
-static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
-{
- u32 gpio = irq_to_gpio(d->irq);
- u32 gpio_idx = gpio & 0x1F;
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct mxc_gpio_port *port = gc->private;
-
- if (enable) {
- if (port->irq_high && (gpio_idx >= 16))
- enable_irq_wake(port->irq_high);
- else
- enable_irq_wake(port->irq);
- } else {
- if (port->irq_high && (gpio_idx >= 16))
- disable_irq_wake(port->irq_high);
- else
- disable_irq_wake(port->irq);
- }
-
- return 0;
-}
-
-static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port)
-{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start,
- port->base, handle_level_irq);
- gc->private = port;
-
- ct = gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack,
- ct->chip.irq_mask = irq_gc_mask_clr_bit;
- ct->chip.irq_unmask = irq_gc_mask_set_bit;
- ct->chip.irq_set_type = gpio_set_irq_type;
- ct->chip.irq_set_wake = gpio_set_wake_irq,
- ct->regs.ack = GPIO_ISR;
- ct->regs.mask = GPIO_IMR;
-
- irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
- IRQ_NOREQUEST, 0);
-}
-
-static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
-{
- const struct of_device_id *of_id =
- of_match_device(mxc_gpio_dt_ids, &pdev->dev);
- enum mxc_gpio_hwtype hwtype;
-
- if (of_id)
- pdev->id_entry = of_id->data;
- hwtype = pdev->id_entry->driver_data;
-
- if (mxc_gpio_hwtype) {
- /*
- * The driver works with a reasonable presupposition,
- * that is all gpio ports must be the same type when
- * running on one soc.
- */
- BUG_ON(mxc_gpio_hwtype != hwtype);
- return;
- }
-
- if (hwtype == IMX31_GPIO)
- mxc_gpio_hwdata = &imx31_gpio_hwdata;
- else
- mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;
-
- mxc_gpio_hwtype = hwtype;
-}
-
-static int __devinit mxc_gpio_probe(struct platform_device *pdev)
-{
- struct device_node *np = pdev->dev.of_node;
- struct mxc_gpio_port *port;
- struct resource *iores;
- int err;
-
- mxc_gpio_get_hw(pdev);
-
- port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iores) {
- err = -ENODEV;
- goto out_kfree;
- }
-
- if (!request_mem_region(iores->start, resource_size(iores),
- pdev->name)) {
- err = -EBUSY;
- goto out_kfree;
- }
-
- port->base = ioremap(iores->start, resource_size(iores));
- if (!port->base) {
- err = -ENOMEM;
- goto out_release_mem;
- }
-
- port->irq_high = platform_get_irq(pdev, 1);
- port->irq = platform_get_irq(pdev, 0);
- if (port->irq < 0) {
- err = -EINVAL;
- goto out_iounmap;
- }
-
- /* disable the interrupt and clear the status */
- writel(0, port->base + GPIO_IMR);
- writel(~0, port->base + GPIO_ISR);
-
- if (mxc_gpio_hwtype == IMX21_GPIO) {
- /* setup one handler for all GPIO interrupts */
- if (pdev->id == 0)
- irq_set_chained_handler(port->irq,
- mx2_gpio_irq_handler);
- } else {
- /* setup one handler for each entry */
- irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
- irq_set_handler_data(port->irq, port);
- if (port->irq_high > 0) {
- /* setup handler for GPIO 16 to 31 */
- irq_set_chained_handler(port->irq_high,
- mx3_gpio_irq_handler);
- irq_set_handler_data(port->irq_high, port);
- }
- }
-
- err = bgpio_init(&port->bgc, &pdev->dev, 4,
- port->base + GPIO_PSR,
- port->base + GPIO_DR, NULL,
- port->base + GPIO_GDIR, NULL, false);
- if (err)
- goto out_iounmap;
-
- port->bgc.gc.base = pdev->id * 32;
- port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
- port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
-
- err = gpiochip_add(&port->bgc.gc);
- if (err)
- goto out_bgpio_remove;
-
- /*
- * In dt case, we use gpio number range dynamically
- * allocated by gpio core.
- */
- port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base :
- pdev->id * 32);
-
- /* gpio-mxc can be a generic irq chip */
- mxc_gpio_init_gc(port);
-
- list_add_tail(&port->node, &mxc_gpio_ports);
-
- return 0;
-
-out_bgpio_remove:
- bgpio_remove(&port->bgc);
-out_iounmap:
- iounmap(port->base);
-out_release_mem:
- release_mem_region(iores->start, resource_size(iores));
-out_kfree:
- kfree(port);
- dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
- return err;
-}
-
-static struct platform_driver mxc_gpio_driver = {
- .driver = {
- .name = "gpio-mxc",
- .owner = THIS_MODULE,
- .of_match_table = mxc_gpio_dt_ids,
- },
- .probe = mxc_gpio_probe,
- .id_table = mxc_gpio_devtype,
-};
-
-static int __init gpio_mxc_init(void)
-{
- return platform_driver_register(&mxc_gpio_driver);
-}
-postcore_initcall(gpio_mxc_init);
-
-MODULE_AUTHOR("Freescale Semiconductor, "
- "Daniel Mack <danielncaiaq.de>, "
- "Juergen Beisert <kernel@pengutronix.de>");
-MODULE_DESCRIPTION("Freescale MXC GPIO");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
deleted file mode 100644
index d8cafba8c82..00000000000
--- a/drivers/gpio/gpio-mxs.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/basic_mmio_gpio.h>
-#include <mach/mxs.h>
-
-#define MXS_SET 0x4
-#define MXS_CLR 0x8
-
-#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10)
-#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10)
-#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10)
-#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10)
-#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10)
-#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10)
-#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10)
-#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10)
-
-#define GPIO_INT_FALL_EDGE 0x0
-#define GPIO_INT_LOW_LEV 0x1
-#define GPIO_INT_RISE_EDGE 0x2
-#define GPIO_INT_HIGH_LEV 0x3
-#define GPIO_INT_LEV_MASK (1 << 0)
-#define GPIO_INT_POL_MASK (1 << 1)
-
-struct mxs_gpio_port {
- void __iomem *base;
- int id;
- int irq;
- int virtual_irq_start;
- struct bgpio_chip bgc;
-};
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
-{
- u32 gpio = irq_to_gpio(d->irq);
- u32 pin_mask = 1 << (gpio & 31);
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct mxs_gpio_port *port = gc->private;
- void __iomem *pin_addr;
- int edge;
-
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- edge = GPIO_INT_RISE_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- edge = GPIO_INT_FALL_EDGE;
- break;
- case IRQ_TYPE_LEVEL_LOW:
- edge = GPIO_INT_LOW_LEV;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- edge = GPIO_INT_HIGH_LEV;
- break;
- default:
- return -EINVAL;
- }
-
- /* set level or edge */
- pin_addr = port->base + PINCTRL_IRQLEV(port->id);
- if (edge & GPIO_INT_LEV_MASK)
- writel(pin_mask, pin_addr + MXS_SET);
- else
- writel(pin_mask, pin_addr + MXS_CLR);
-
- /* set polarity */
- pin_addr = port->base + PINCTRL_IRQPOL(port->id);
- if (edge & GPIO_INT_POL_MASK)
- writel(pin_mask, pin_addr + MXS_SET);
- else
- writel(pin_mask, pin_addr + MXS_CLR);
-
- writel(1 << (gpio & 0x1f),
- port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
-
- return 0;
-}
-
-/* MXS has one interrupt *per* gpio port */
-static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- u32 irq_stat;
- struct mxs_gpio_port *port = irq_get_handler_data(irq);
- u32 gpio_irq_no_base = port->virtual_irq_start;
-
- desc->irq_data.chip->irq_ack(&desc->irq_data);
-
- irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) &
- readl(port->base + PINCTRL_IRQEN(port->id));
-
- while (irq_stat != 0) {
- int irqoffset = fls(irq_stat) - 1;
- generic_handle_irq(gpio_irq_no_base + irqoffset);
- irq_stat &= ~(1 << irqoffset);
- }
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param irq interrupt source number
- * @param enable enable as wake-up if equal to non-zero
- * @return This function returns 0 on success.
- */
-static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
-{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct mxs_gpio_port *port = gc->private;
-
- if (enable)
- enable_irq_wake(port->irq);
- else
- disable_irq_wake(port->irq);
-
- return 0;
-}
-
-static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port)
-{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start,
- port->base, handle_level_irq);
- gc->private = port;
-
- ct = gc->chip_types;
- ct->chip.irq_ack = irq_gc_ack,
- ct->chip.irq_mask = irq_gc_mask_clr_bit;
- ct->chip.irq_unmask = irq_gc_mask_set_bit;
- ct->chip.irq_set_type = mxs_gpio_set_irq_type;
- ct->chip.irq_set_wake = mxs_gpio_set_wake_irq,
- ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR;
- ct->regs.mask = PINCTRL_IRQEN(port->id);
-
- irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
-}
-
-static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
-{
- struct bgpio_chip *bgc = to_bgpio_chip(gc);
- struct mxs_gpio_port *port =
- container_of(bgc, struct mxs_gpio_port, bgc);
-
- return port->virtual_irq_start + offset;
-}
-
-static int __devinit mxs_gpio_probe(struct platform_device *pdev)
-{
- static void __iomem *base;
- struct mxs_gpio_port *port;
- struct resource *iores = NULL;
- int err;
-
- port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL);
- if (!port)
- return -ENOMEM;
-
- port->id = pdev->id;
- port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32;
-
- /*
- * map memory region only once, as all the gpio ports
- * share the same one
- */
- if (!base) {
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iores) {
- err = -ENODEV;
- goto out_kfree;
- }
-
- if (!request_mem_region(iores->start, resource_size(iores),
- pdev->name)) {
- err = -EBUSY;
- goto out_kfree;
- }
-
- base = ioremap(iores->start, resource_size(iores));
- if (!base) {
- err = -ENOMEM;
- goto out_release_mem;
- }
- }
- port->base = base;
-
- port->irq = platform_get_irq(pdev, 0);
- if (port->irq < 0) {
- err = -EINVAL;
- goto out_iounmap;
- }
-
- /*
- * select the pin interrupt functionality but initially
- * disable the interrupts
- */
- writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id));
- writel(0, port->base + PINCTRL_IRQEN(port->id));
-
- /* clear address has to be used to clear IRQSTAT bits */
- writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR);
-
- /* gpio-mxs can be a generic irq chip */
- mxs_gpio_init_gc(port);
-
- /* setup one handler for each entry */
- irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
- irq_set_handler_data(port->irq, port);
-
- err = bgpio_init(&port->bgc, &pdev->dev, 4,
- port->base + PINCTRL_DIN(port->id),
- port->base + PINCTRL_DOUT(port->id), NULL,
- port->base + PINCTRL_DOE(port->id), NULL, false);
- if (err)
- goto out_iounmap;
-
- port->bgc.gc.to_irq = mxs_gpio_to_irq;
- port->bgc.gc.base = port->id * 32;
-
- err = gpiochip_add(&port->bgc.gc);
- if (err)
- goto out_bgpio_remove;
-
- return 0;
-
-out_bgpio_remove:
- bgpio_remove(&port->bgc);
-out_iounmap:
- if (iores)
- iounmap(port->base);
-out_release_mem:
- if (iores)
- release_mem_region(iores->start, resource_size(iores));
-out_kfree:
- kfree(port);
- dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
- return err;
-}
-
-static struct platform_driver mxs_gpio_driver = {
- .driver = {
- .name = "gpio-mxs",
- .owner = THIS_MODULE,
- },
- .probe = mxs_gpio_probe,
-};
-
-static int __init mxs_gpio_init(void)
-{
- return platform_driver_register(&mxs_gpio_driver);
-}
-postcore_initcall(mxs_gpio_init);
-
-MODULE_AUTHOR("Freescale Semiconductor, "
- "Daniel Mack <danielncaiaq.de>, "
- "Juergen Beisert <kernel@pengutronix.de>");
-MODULE_DESCRIPTION("Freescale MXS GPIO");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 0599854e221..35bebde23e8 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -54,11 +54,6 @@ struct gpio_bank {
struct device *dev;
bool dbck_flag;
int stride;
- u32 width;
-
- void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable);
-
- struct omap_gpio_reg_offs *regs;
};
#ifdef CONFIG_ARCH_OMAP3
@@ -84,18 +79,121 @@ static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
*/
static struct gpio_bank *gpio_bank;
+static int bank_width;
+
/* TODO: Analyze removing gpio_bank_count usage from driver code */
int gpio_bank_count;
-#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
-#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
+static inline struct gpio_bank *get_gpio_bank(int gpio)
+{
+ if (cpu_is_omap15xx()) {
+ if (OMAP_GPIO_IS_MPUIO(gpio))
+ return &gpio_bank[0];
+ return &gpio_bank[1];
+ }
+ if (cpu_is_omap16xx()) {
+ if (OMAP_GPIO_IS_MPUIO(gpio))
+ return &gpio_bank[0];
+ return &gpio_bank[1 + (gpio >> 4)];
+ }
+ if (cpu_is_omap7xx()) {
+ if (OMAP_GPIO_IS_MPUIO(gpio))
+ return &gpio_bank[0];
+ return &gpio_bank[1 + (gpio >> 5)];
+ }
+ if (cpu_is_omap24xx())
+ return &gpio_bank[gpio >> 5];
+ if (cpu_is_omap34xx() || cpu_is_omap44xx())
+ return &gpio_bank[gpio >> 5];
+ BUG();
+ return NULL;
+}
+
+static inline int get_gpio_index(int gpio)
+{
+ if (cpu_is_omap7xx())
+ return gpio & 0x1f;
+ if (cpu_is_omap24xx())
+ return gpio & 0x1f;
+ if (cpu_is_omap34xx() || cpu_is_omap44xx())
+ return gpio & 0x1f;
+ return gpio & 0x0f;
+}
+
+static inline int gpio_valid(int gpio)
+{
+ if (gpio < 0)
+ return -1;
+ if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
+ if (gpio >= OMAP_MAX_GPIO_LINES + 16)
+ return -1;
+ return 0;
+ }
+ if (cpu_is_omap15xx() && gpio < 16)
+ return 0;
+ if ((cpu_is_omap16xx()) && gpio < 64)
+ return 0;
+ if (cpu_is_omap7xx() && gpio < 192)
+ return 0;
+ if (cpu_is_omap2420() && gpio < 128)
+ return 0;
+ if (cpu_is_omap2430() && gpio < 160)
+ return 0;
+ if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
+ return 0;
+ return -1;
+}
+
+static int check_gpio(int gpio)
+{
+ if (unlikely(gpio_valid(gpio) < 0)) {
+ printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
+ dump_stack();
+ return -1;
+ }
+ return 0;
+}
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
{
void __iomem *reg = bank->base;
u32 l;
- reg += bank->regs->direction;
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_IO_CNTL / bank->stride;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_DIR_CONTROL;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ reg += OMAP1610_GPIO_DIRECTION;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_DIR_CONTROL;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_OE;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ case METHOD_GPIO_44XX:
+ reg += OMAP4_GPIO_OE;
+ break;
+#endif
+ default:
+ WARN_ON(1);
+ return;
+ }
l = __raw_readl(reg);
if (is_input)
l |= 1 << gpio;
@@ -104,48 +202,165 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
__raw_writel(l, reg);
}
-
-/* set data out value using dedicate set/clear register */
-static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)
+static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
{
void __iomem *reg = bank->base;
- u32 l = GPIO_BIT(bank, gpio);
-
- if (enable)
- reg += bank->regs->set_dataout;
- else
- reg += bank->regs->clr_dataout;
-
- __raw_writel(l, reg);
-}
-
-/* set data out value using mask register */
-static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)
-{
- void __iomem *reg = bank->base + bank->regs->dataout;
- u32 gpio_bit = GPIO_BIT(bank, gpio);
- u32 l;
+ u32 l = 0;
- l = __raw_readl(reg);
- if (enable)
- l |= gpio_bit;
- else
- l &= ~gpio_bit;
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_OUTPUT / bank->stride;
+ l = __raw_readl(reg);
+ if (enable)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_DATA_OUTPUT;
+ l = __raw_readl(reg);
+ if (enable)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ if (enable)
+ reg += OMAP1610_GPIO_SET_DATAOUT;
+ else
+ reg += OMAP1610_GPIO_CLEAR_DATAOUT;
+ l = 1 << gpio;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_DATA_OUTPUT;
+ l = __raw_readl(reg);
+ if (enable)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ if (enable)
+ reg += OMAP24XX_GPIO_SETDATAOUT;
+ else
+ reg += OMAP24XX_GPIO_CLEARDATAOUT;
+ l = 1 << gpio;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+ case METHOD_GPIO_44XX:
+ if (enable)
+ reg += OMAP4_GPIO_SETDATAOUT;
+ else
+ reg += OMAP4_GPIO_CLEARDATAOUT;
+ l = 1 << gpio;
+ break;
+#endif
+ default:
+ WARN_ON(1);
+ return;
+ }
__raw_writel(l, reg);
}
static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
{
- void __iomem *reg = bank->base + bank->regs->datain;
+ void __iomem *reg;
- return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+ reg = bank->base;
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_DATA_INPUT;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ reg += OMAP1610_GPIO_DATAIN;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_DATA_INPUT;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_DATAIN;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+ case METHOD_GPIO_44XX:
+ reg += OMAP4_GPIO_DATAIN;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+ return (__raw_readl(reg)
+ & (1 << get_gpio_index(gpio))) != 0;
}
static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
{
- void __iomem *reg = bank->base + bank->regs->dataout;
+ void __iomem *reg;
+
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+ reg = bank->base;
+
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_OUTPUT / bank->stride;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_DATA_OUTPUT;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ reg += OMAP1610_GPIO_DATAOUT;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_DATA_OUTPUT;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_DATAOUT;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+ case METHOD_GPIO_44XX:
+ reg += OMAP4_GPIO_DATAOUT;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
- return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
+ return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
}
#define MOD_REG_BIT(reg, bit_mask, set) \
@@ -168,7 +383,7 @@ do { \
static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
unsigned debounce)
{
- void __iomem *reg;
+ void __iomem *reg = bank->base;
u32 val;
u32 l;
@@ -182,12 +397,21 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
else
debounce = (debounce / 0x1f) - 1;
- l = GPIO_BIT(bank, gpio);
+ l = 1 << get_gpio_index(gpio);
+
+ if (bank->method == METHOD_GPIO_44XX)
+ reg += OMAP4_GPIO_DEBOUNCINGTIME;
+ else
+ reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
- reg = bank->base + bank->regs->debounce;
__raw_writel(debounce, reg);
- reg = bank->base + bank->regs->debounce_en;
+ reg = bank->base;
+ if (bank->method == METHOD_GPIO_44XX)
+ reg += OMAP4_GPIO_DEBOUNCENABLE;
+ else
+ reg += OMAP24XX_GPIO_DEBOUNCE_EN;
+
val = __raw_readl(reg);
if (debounce) {
@@ -405,6 +629,9 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
else
gpio = d->irq - IH_GPIO_BASE;
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+
if (type & ~IRQ_TYPE_SENSE_MASK)
return -EINVAL;
@@ -415,7 +642,7 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
bank = irq_data_get_irq_chip_data(d);
spin_lock_irqsave(&bank->lock, flags);
- retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);
+ retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
spin_unlock_irqrestore(&bank->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -430,81 +657,195 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
void __iomem *reg = bank->base;
- reg += bank->regs->irqstatus;
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ /* MPUIO irqstatus is reset by reading the status register,
+ * so do nothing here */
+ return;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_INT_STATUS;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ reg += OMAP1610_GPIO_IRQSTATUS1;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_INT_STATUS;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_IRQSTATUS1;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ case METHOD_GPIO_44XX:
+ reg += OMAP4_GPIO_IRQSTATUS0;
+ break;
+#endif
+ default:
+ WARN_ON(1);
+ return;
+ }
__raw_writel(gpio_mask, reg);
/* Workaround for clearing DSP GPIO interrupts to allow retention */
- if (bank->regs->irqstatus2) {
- reg = bank->base + bank->regs->irqstatus2;
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
+ else if (cpu_is_omap44xx())
+ reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
+
+ if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
__raw_writel(gpio_mask, reg);
- }
/* Flush posted write for the irq status to avoid spurious interrupts */
__raw_readl(reg);
+ }
}
static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
{
- _clear_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+ _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
}
static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
{
void __iomem *reg = bank->base;
+ int inv = 0;
u32 l;
- u32 mask = (1 << bank->width) - 1;
+ u32 mask;
+
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
+ mask = 0xffff;
+ inv = 1;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_INT_MASK;
+ mask = 0xffff;
+ inv = 1;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ reg += OMAP1610_GPIO_IRQENABLE1;
+ mask = 0xffff;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_INT_MASK;
+ mask = 0xffffffff;
+ inv = 1;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_IRQENABLE1;
+ mask = 0xffffffff;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ case METHOD_GPIO_44XX:
+ reg += OMAP4_GPIO_IRQSTATUSSET0;
+ mask = 0xffffffff;
+ break;
+#endif
+ default:
+ WARN_ON(1);
+ return 0;
+ }
- reg += bank->regs->irqenable;
l = __raw_readl(reg);
- if (bank->regs->irqenable_inv)
+ if (inv)
l = ~l;
l &= mask;
return l;
}
-static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
{
void __iomem *reg = bank->base;
u32 l;
- if (bank->regs->set_irqenable) {
- reg += bank->regs->set_irqenable;
- l = gpio_mask;
- } else {
- reg += bank->regs->irqenable;
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
l = __raw_readl(reg);
- if (bank->regs->irqenable_inv)
- l &= ~gpio_mask;
+ if (enable)
+ l &= ~(gpio_mask);
else
l |= gpio_mask;
- }
-
- __raw_writel(l, reg);
-}
-
-static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
-{
- void __iomem *reg = bank->base;
- u32 l;
-
- if (bank->regs->clr_irqenable) {
- reg += bank->regs->clr_irqenable;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_INT_MASK;
+ l = __raw_readl(reg);
+ if (enable)
+ l &= ~(gpio_mask);
+ else
+ l |= gpio_mask;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_GPIO_1610:
+ if (enable)
+ reg += OMAP1610_GPIO_SET_IRQENABLE1;
+ else
+ reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
l = gpio_mask;
- } else {
- reg += bank->regs->irqenable;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_INT_MASK;
l = __raw_readl(reg);
- if (bank->regs->irqenable_inv)
+ if (enable)
+ l &= ~(gpio_mask);
+ else
l |= gpio_mask;
+ break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ case METHOD_GPIO_24XX:
+ if (enable)
+ reg += OMAP24XX_GPIO_SETIRQENABLE1;
+ else
+ reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
+ l = gpio_mask;
+ break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+ case METHOD_GPIO_44XX:
+ if (enable)
+ reg += OMAP4_GPIO_IRQSTATUSSET0;
else
- l &= ~gpio_mask;
+ reg += OMAP4_GPIO_IRQSTATUSCLR0;
+ l = gpio_mask;
+ break;
+#endif
+ default:
+ WARN_ON(1);
+ return;
}
-
__raw_writel(l, reg);
}
static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
{
- _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+ _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
}
/*
@@ -517,32 +858,50 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena
*/
static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
{
- u32 gpio_bit = GPIO_BIT(bank, gpio);
- unsigned long flags;
+ unsigned long uninitialized_var(flags);
- if (bank->non_wakeup_gpios & gpio_bit) {
- dev_err(bank->dev,
- "Unable to modify wakeup on non-wakeup GPIO%d\n", gpio);
+ switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
+ case METHOD_MPUIO:
+ case METHOD_GPIO_1610:
+ spin_lock_irqsave(&bank->lock, flags);
+ if (enable)
+ bank->suspend_wakeup |= (1 << gpio);
+ else
+ bank->suspend_wakeup &= ~(1 << gpio);
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
+#endif
+#ifdef CONFIG_ARCH_OMAP2PLUS
+ case METHOD_GPIO_24XX:
+ case METHOD_GPIO_44XX:
+ if (bank->non_wakeup_gpios & (1 << gpio)) {
+ printk(KERN_ERR "Unable to modify wakeup on "
+ "non-wakeup GPIO%d\n",
+ (bank - gpio_bank) * 32 + gpio);
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&bank->lock, flags);
+ if (enable)
+ bank->suspend_wakeup |= (1 << gpio);
+ else
+ bank->suspend_wakeup &= ~(1 << gpio);
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
+#endif
+ default:
+ printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
+ bank->method);
return -EINVAL;
}
-
- spin_lock_irqsave(&bank->lock, flags);
- if (enable)
- bank->suspend_wakeup |= gpio_bit;
- else
- bank->suspend_wakeup &= ~gpio_bit;
-
- spin_unlock_irqrestore(&bank->lock, flags);
-
- return 0;
}
static void _reset_gpio(struct gpio_bank *bank, int gpio)
{
- _set_gpio_direction(bank, GPIO_INDEX(bank, gpio), 1);
+ _set_gpio_direction(bank, get_gpio_index(gpio), 1);
_set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio);
- _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+ _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
}
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
@@ -552,8 +911,10 @@ static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
struct gpio_bank *bank;
int retval;
+ if (check_gpio(gpio) < 0)
+ return -ENODEV;
bank = irq_data_get_irq_chip_data(d);
- retval = _set_gpio_wakeup(bank, gpio, enable);
+ retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
return retval;
}
@@ -669,7 +1030,31 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
chained_irq_enter(chip, desc);
bank = irq_get_handler_data(irq);
- isr_reg = bank->base + bank->regs->irqstatus;
+#ifdef CONFIG_ARCH_OMAP1
+ if (bank->method == METHOD_MPUIO)
+ isr_reg = bank->base +
+ OMAP_MPUIO_GPIO_INT / bank->stride;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+ if (bank->method == METHOD_GPIO_1510)
+ isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
+#endif
+#if defined(CONFIG_ARCH_OMAP16XX)
+ if (bank->method == METHOD_GPIO_1610)
+ isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+ if (bank->method == METHOD_GPIO_7XX)
+ isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+ if (bank->method == METHOD_GPIO_24XX)
+ isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ if (bank->method == METHOD_GPIO_44XX)
+ isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
+#endif
if (WARN_ON(!isr_reg))
goto exit;
@@ -691,9 +1076,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
/* clear edge sensitive interrupts before handler(s) are
called so that we don't miss any interrupt occurred while
executing them */
- _disable_gpio_irqbank(bank, isr_saved & ~level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
- _enable_gpio_irqbank(bank, isr_saved & ~level_mask);
+ _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
/* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */
@@ -709,7 +1094,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
- gpio_index = GPIO_INDEX(bank, irq_to_gpio(gpio_irq));
+ gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
if (!(isr & 1))
continue;
@@ -765,7 +1150,7 @@ static void gpio_mask_irq(struct irq_data *d)
spin_lock_irqsave(&bank->lock, flags);
_set_gpio_irqenable(bank, gpio, 0);
- _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+ _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
spin_unlock_irqrestore(&bank->lock, flags);
}
@@ -773,13 +1158,13 @@ static void gpio_unmask_irq(struct irq_data *d)
{
unsigned int gpio = d->irq - IH_GPIO_BASE;
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
- unsigned int irq_mask = GPIO_BIT(bank, gpio);
+ unsigned int irq_mask = 1 << get_gpio_index(gpio);
u32 trigger = irqd_get_trigger_type(d);
unsigned long flags;
spin_lock_irqsave(&bank->lock, flags);
if (trigger)
- _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), trigger);
+ _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
/* For level-triggered GPIOs, the clearing must be done after
* the HW source is cleared, thus after the handler has run */
@@ -806,8 +1191,45 @@ static struct irq_chip gpio_irq_chip = {
#ifdef CONFIG_ARCH_OMAP1
+/* MPUIO uses the always-on 32k clock */
+
+static void mpuio_ack_irq(struct irq_data *d)
+{
+ /* The ISR is reset automatically, so do nothing here. */
+}
+
+static void mpuio_mask_irq(struct irq_data *d)
+{
+ unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+ struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+ _set_gpio_irqenable(bank, gpio, 0);
+}
+
+static void mpuio_unmask_irq(struct irq_data *d)
+{
+ unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+ struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+ _set_gpio_irqenable(bank, gpio, 1);
+}
+
+static struct irq_chip mpuio_irq_chip = {
+ .name = "MPUIO",
+ .irq_ack = mpuio_ack_irq,
+ .irq_mask = mpuio_mask_irq,
+ .irq_unmask = mpuio_unmask_irq,
+ .irq_set_type = gpio_irq_type,
+#ifdef CONFIG_ARCH_OMAP16XX
+ /* REVISIT: assuming only 16xx supports MPUIO wake events */
+ .irq_set_wake = gpio_wake_enable,
+#endif
+};
+
+
#define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO)
+
#ifdef CONFIG_ARCH_OMAP16XX
#include <linux/platform_device.h>
@@ -867,7 +1289,7 @@ static struct platform_device omap_mpuio_device = {
static inline void mpuio_init(void)
{
- struct gpio_bank *bank = &gpio_bank[0];
+ struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
platform_set_drvdata(&omap_mpuio_device, bank);
if (platform_driver_register(&omap_mpuio_driver) == 0)
@@ -880,6 +1302,8 @@ static inline void mpuio_init(void) {}
#else
+extern struct irq_chip mpuio_irq_chip;
+
#define bank_is_mpuio(bank) 0
static inline void mpuio_init(void) {}
@@ -905,8 +1329,31 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset)
static int gpio_is_input(struct gpio_bank *bank, int mask)
{
- void __iomem *reg = bank->base + bank->regs->direction;
+ void __iomem *reg = bank->base;
+ switch (bank->method) {
+ case METHOD_MPUIO:
+ reg += OMAP_MPUIO_IO_CNTL / bank->stride;
+ break;
+ case METHOD_GPIO_1510:
+ reg += OMAP1510_GPIO_DIR_CONTROL;
+ break;
+ case METHOD_GPIO_1610:
+ reg += OMAP1610_GPIO_DIRECTION;
+ break;
+ case METHOD_GPIO_7XX:
+ reg += OMAP7XX_GPIO_DIR_CONTROL;
+ break;
+ case METHOD_GPIO_24XX:
+ reg += OMAP24XX_GPIO_OE;
+ break;
+ case METHOD_GPIO_44XX:
+ reg += OMAP4_GPIO_OE;
+ break;
+ default:
+ WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
+ return -EINVAL;
+ }
return __raw_readl(reg) & mask;
}
@@ -918,9 +1365,9 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
u32 mask;
gpio = chip->base + offset;
- bank = container_of(chip, struct gpio_bank, chip);
+ bank = get_gpio_bank(gpio);
reg = bank->base;
- mask = GPIO_BIT(bank, gpio);
+ mask = 1 << get_gpio_index(gpio);
if (gpio_is_input(bank, mask))
return _get_gpio_datain(bank, gpio);
@@ -935,7 +1382,7 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
- bank->set_dataout(bank, offset, value);
+ _set_gpio_dataout(bank, offset, value);
_set_gpio_direction(bank, offset, 0);
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
@@ -969,7 +1416,7 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
bank = container_of(chip, struct gpio_bank, chip);
spin_lock_irqsave(&bank->lock, flags);
- bank->set_dataout(bank, offset, value);
+ _set_gpio_dataout(bank, offset, value);
spin_unlock_irqrestore(&bank->lock, flags);
}
@@ -985,17 +1432,19 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
static void __init omap_gpio_show_rev(struct gpio_bank *bank)
{
- static bool called;
u32 rev;
- if (called || bank->regs->revision == USHRT_MAX)
+ if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
+ rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
+ else if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
+ else if (cpu_is_omap44xx())
+ rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
+ else
return;
- rev = __raw_readw(bank->base + bank->regs->revision);
- pr_info("OMAP GPIO hardware version %d.%d\n",
+ printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
(rev >> 4) & 0x0f, rev & 0x0f);
-
- called = true;
}
/* This lock class tells lockdep that GPIO irqs are in a different
@@ -1077,30 +1526,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
}
}
-static __init void
-omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
- unsigned int num)
-{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
- handle_simple_irq);
- ct = gc->chip_types;
-
- /* NOTE: No ack required, reading IRQ status clears it. */
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->chip.irq_set_type = gpio_irq_type;
- /* REVISIT: assuming only 16xx supports MPUIO wake events */
- if (cpu_is_omap16xx())
- ct->chip.irq_set_wake = gpio_wake_enable,
-
- ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
- irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-}
-
static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
{
int j;
@@ -1128,23 +1553,22 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
} else {
bank->chip.label = "gpio";
bank->chip.base = gpio;
- gpio += bank->width;
+ gpio += bank_width;
}
- bank->chip.ngpio = bank->width;
+ bank->chip.ngpio = bank_width;
gpiochip_add(&bank->chip);
for (j = bank->virtual_irq_start;
- j < bank->virtual_irq_start + bank->width; j++) {
+ j < bank->virtual_irq_start + bank_width; j++) {
irq_set_lockdep_class(j, &gpio_lock_class);
irq_set_chip_data(j, bank);
- if (bank_is_mpuio(bank)) {
- omap_mpuio_alloc_gc(bank, j, bank->width);
- } else {
+ if (bank_is_mpuio(bank))
+ irq_set_chip(j, &mpuio_irq_chip);
+ else
irq_set_chip(j, &gpio_irq_chip);
- irq_set_handler(j, handle_simple_irq);
- set_irq_flags(j, IRQF_VALID);
- }
+ irq_set_handler(j, handle_simple_irq);
+ set_irq_flags(j, IRQF_VALID);
}
irq_set_chained_handler(bank->irq, gpio_irq_handler);
irq_set_handler_data(bank->irq, bank);
@@ -1186,14 +1610,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
bank->dev = &pdev->dev;
bank->dbck_flag = pdata->dbck_flag;
bank->stride = pdata->bank_stride;
- bank->width = pdata->bank_width;
-
- bank->regs = pdata->regs;
-
- if (bank->regs->set_dataout && bank->regs->clr_dataout)
- bank->set_dataout = _set_gpio_dataout_reg;
- else
- bank->set_dataout = _set_gpio_dataout_mask;
+ bank_width = pdata->bank_width;
spin_lock_init(&bank->lock);
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
index ef67f1952a7..ea37c046178 100644
--- a/drivers/gpio/gpio-plat-samsung.c
+++ b/drivers/gpio/gpio-plat-samsung.c
@@ -1,4 +1,5 @@
-/*
+/* arch/arm/plat-samsung/gpiolib.c
+ *
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
index 7f87b0c76e0..2842394b28b 100644
--- a/drivers/gpio/gpio-s5pc100.c
+++ b/drivers/gpio/gpio-s5pc100.c
@@ -1,5 +1,4 @@
-/*
- * S5PC100 - GPIOlib support
+/* linux/arch/arm/mach-s5pc100/gpiolib.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
@@ -7,6 +6,8 @@
* Copyright 2009 Samsung Electronics Co
* Kyungmin Park <kyungmin.park@samsung.com>
*
+ * S5PC100 - GPIOlib support
+ *
* 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.
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
index eb12f1602de..1ba20a703e0 100644
--- a/drivers/gpio/gpio-s5pv210.c
+++ b/drivers/gpio/gpio-s5pv210.c
@@ -1,9 +1,10 @@
-/*
- * S5PV210 - GPIOlib support
+/* linux/arch/arm/mach-s5pv210/gpiolib.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
+ * S5PV210 - GPIOlib support
+ *
* 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.
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
deleted file mode 100644
index 747eb40e8af..00000000000
--- a/drivers/gpio/gpio-tegra.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * arch/arm/mach-tegra/gpio.c
- *
- * Copyright (c) 2010 Google, Inc
- *
- * Author:
- * Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/of.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/iomap.h>
-#include <mach/suspend.h>
-
-#define GPIO_BANK(x) ((x) >> 5)
-#define GPIO_PORT(x) (((x) >> 3) & 0x3)
-#define GPIO_BIT(x) ((x) & 0x7)
-
-#define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \
- GPIO_BANK(x) * 0x80 + \
- GPIO_PORT(x) * 4)
-
-#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
-#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
-#define GPIO_OUT(x) (GPIO_REG(x) + 0X20)
-#define GPIO_IN(x) (GPIO_REG(x) + 0x30)
-#define GPIO_INT_STA(x) (GPIO_REG(x) + 0x40)
-#define GPIO_INT_ENB(x) (GPIO_REG(x) + 0x50)
-#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60)
-#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70)
-
-#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800)
-#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810)
-#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820)
-#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840)
-#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850)
-#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860)
-
-#define GPIO_INT_LVL_MASK 0x010101
-#define GPIO_INT_LVL_EDGE_RISING 0x000101
-#define GPIO_INT_LVL_EDGE_FALLING 0x000100
-#define GPIO_INT_LVL_EDGE_BOTH 0x010100
-#define GPIO_INT_LVL_LEVEL_HIGH 0x000001
-#define GPIO_INT_LVL_LEVEL_LOW 0x000000
-
-struct tegra_gpio_bank {
- int bank;
- int irq;
- spinlock_t lvl_lock[4];
-#ifdef CONFIG_PM
- u32 cnf[4];
- u32 out[4];
- u32 oe[4];
- u32 int_enb[4];
- u32 int_lvl[4];
-#endif
-};
-
-
-static struct tegra_gpio_bank tegra_gpio_banks[] = {
- {.bank = 0, .irq = INT_GPIO1},
- {.bank = 1, .irq = INT_GPIO2},
- {.bank = 2, .irq = INT_GPIO3},
- {.bank = 3, .irq = INT_GPIO4},
- {.bank = 4, .irq = INT_GPIO5},
- {.bank = 5, .irq = INT_GPIO6},
- {.bank = 6, .irq = INT_GPIO7},
-};
-
-static int tegra_gpio_compose(int bank, int port, int bit)
-{
- return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
-}
-
-static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
-{
- u32 val;
-
- val = 0x100 << GPIO_BIT(gpio);
- if (value)
- val |= 1 << GPIO_BIT(gpio);
- __raw_writel(val, reg);
-}
-
-void tegra_gpio_enable(int gpio)
-{
- tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
-}
-
-void tegra_gpio_disable(int gpio)
-{
- tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
-}
-
-static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
-}
-
-static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
-}
-
-static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
- return 0;
-}
-
-static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- tegra_gpio_set(chip, offset, value);
- tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
- return 0;
-}
-
-
-
-static struct gpio_chip tegra_gpio_chip = {
- .label = "tegra-gpio",
- .direction_input = tegra_gpio_direction_input,
- .get = tegra_gpio_get,
- .direction_output = tegra_gpio_direction_output,
- .set = tegra_gpio_set,
- .base = 0,
- .ngpio = TEGRA_NR_GPIOS,
-};
-
-static void tegra_gpio_irq_ack(struct irq_data *d)
-{
- int gpio = d->irq - INT_GPIO_BASE;
-
- __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
-}
-
-static void tegra_gpio_irq_mask(struct irq_data *d)
-{
- int gpio = d->irq - INT_GPIO_BASE;
-
- tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
-}
-
-static void tegra_gpio_irq_unmask(struct irq_data *d)
-{
- int gpio = d->irq - INT_GPIO_BASE;
-
- tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
-}
-
-static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
- int gpio = d->irq - INT_GPIO_BASE;
- struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
- int port = GPIO_PORT(gpio);
- int lvl_type;
- int val;
- unsigned long flags;
-
- switch (type & IRQ_TYPE_SENSE_MASK) {
- case IRQ_TYPE_EDGE_RISING:
- lvl_type = GPIO_INT_LVL_EDGE_RISING;
- break;
-
- case IRQ_TYPE_EDGE_FALLING:
- lvl_type = GPIO_INT_LVL_EDGE_FALLING;
- break;
-
- case IRQ_TYPE_EDGE_BOTH:
- lvl_type = GPIO_INT_LVL_EDGE_BOTH;
- break;
-
- case IRQ_TYPE_LEVEL_HIGH:
- lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
- break;
-
- case IRQ_TYPE_LEVEL_LOW:
- lvl_type = GPIO_INT_LVL_LEVEL_LOW;
- break;
-
- default:
- return -EINVAL;
- }
-
- spin_lock_irqsave(&bank->lvl_lock[port], flags);
-
- val = __raw_readl(GPIO_INT_LVL(gpio));
- val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
- val |= lvl_type << GPIO_BIT(gpio);
- __raw_writel(val, GPIO_INT_LVL(gpio));
-
- spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
-
- if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
- __irq_set_handler_locked(d->irq, handle_level_irq);
- else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
- __irq_set_handler_locked(d->irq, handle_edge_irq);
-
- return 0;
-}
-
-static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- struct tegra_gpio_bank *bank;
- int port;
- int pin;
- int unmasked = 0;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
-
- bank = irq_get_handler_data(irq);
-
- for (port = 0; port < 4; port++) {
- int gpio = tegra_gpio_compose(bank->bank, port, 0);
- unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
- __raw_readl(GPIO_INT_ENB(gpio));
- u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
-
- for_each_set_bit(pin, &sta, 8) {
- __raw_writel(1 << pin, GPIO_INT_CLR(gpio));
-
- /* if gpio is edge triggered, clear condition
- * before executing the hander so that we don't
- * miss edges
- */
- if (lvl & (0x100 << pin)) {
- unmasked = 1;
- chained_irq_exit(chip, desc);
- }
-
- generic_handle_irq(gpio_to_irq(gpio + pin));
- }
- }
-
- if (!unmasked)
- chained_irq_exit(chip, desc);
-
-}
-
-#ifdef CONFIG_PM
-void tegra_gpio_resume(void)
-{
- unsigned long flags;
- int b;
- int p;
-
- local_irq_save(flags);
-
- for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
- struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
-
- for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
- unsigned int gpio = (b<<5) | (p<<3);
- __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
- __raw_writel(bank->out[p], GPIO_OUT(gpio));
- __raw_writel(bank->oe[p], GPIO_OE(gpio));
- __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
- __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
- }
- }
-
- local_irq_restore(flags);
-}
-
-void tegra_gpio_suspend(void)
-{
- unsigned long flags;
- int b;
- int p;
-
- local_irq_save(flags);
- for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
- struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
-
- for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
- unsigned int gpio = (b<<5) | (p<<3);
- bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
- bank->out[p] = __raw_readl(GPIO_OUT(gpio));
- bank->oe[p] = __raw_readl(GPIO_OE(gpio));
- bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
- bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
- }
- }
- local_irq_restore(flags);
-}
-
-static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
-{
- struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
- return irq_set_irq_wake(bank->irq, enable);
-}
-#endif
-
-static struct irq_chip tegra_gpio_irq_chip = {
- .name = "GPIO",
- .irq_ack = tegra_gpio_irq_ack,
- .irq_mask = tegra_gpio_irq_mask,
- .irq_unmask = tegra_gpio_irq_unmask,
- .irq_set_type = tegra_gpio_irq_set_type,
-#ifdef CONFIG_PM
- .irq_set_wake = tegra_gpio_wake_enable,
-#endif
-};
-
-
-/* This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-static int __init tegra_gpio_init(void)
-{
- struct tegra_gpio_bank *bank;
- int i;
- int j;
-
- for (i = 0; i < 7; i++) {
- for (j = 0; j < 4; j++) {
- int gpio = tegra_gpio_compose(i, j, 0);
- __raw_writel(0x00, GPIO_INT_ENB(gpio));
- }
- }
-
-#ifdef CONFIG_OF_GPIO
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
- "nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
-
- gpiochip_add(&tegra_gpio_chip);
-
- for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
- bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
-
- irq_set_lockdep_class(i, &gpio_lock_class);
- irq_set_chip_data(i, bank);
- irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
- handle_simple_irq);
- set_irq_flags(i, IRQF_VALID);
- }
-
- for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
- bank = &tegra_gpio_banks[i];
-
- irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
- irq_set_handler_data(bank->irq, bank);
-
- for (j = 0; j < 4; j++)
- spin_lock_init(&bank->lvl_lock[j]);
- }
-
- return 0;
-}
-
-postcore_initcall(tegra_gpio_init);
-
-void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
-{
- int i;
-
- for (i = 0; i < num; i++) {
- int gpio = table[i].gpio;
-
- if (table[i].enable)
- tegra_gpio_enable(gpio);
- else
- tegra_gpio_disable(gpio);
- }
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static int dbg_gpio_show(struct seq_file *s, void *unused)
-{
- int i;
- int j;
-
- for (i = 0; i < 7; i++) {
- for (j = 0; j < 4; j++) {
- int gpio = tegra_gpio_compose(i, j, 0);
- seq_printf(s,
- "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
- i, j,
- __raw_readl(GPIO_CNF(gpio)),
- __raw_readl(GPIO_OE(gpio)),
- __raw_readl(GPIO_OUT(gpio)),
- __raw_readl(GPIO_IN(gpio)),
- __raw_readl(GPIO_INT_STA(gpio)),
- __raw_readl(GPIO_INT_ENB(gpio)),
- __raw_readl(GPIO_INT_LVL(gpio)));
- }
- }
- return 0;
-}
-
-static int dbg_gpio_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dbg_gpio_show, &inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
- .open = dbg_gpio_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init tegra_gpio_debuginit(void)
-{
- (void) debugfs_create_file("tegra_gpio", S_IRUGO,
- NULL, NULL, &debug_fops);
- return 0;
-}
-late_initcall(tegra_gpio_debuginit);
-#endif
diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c
index fd2dfeeefdf..d92790140fe 100644
--- a/drivers/gpio/gpio-u300.c
+++ b/drivers/gpio/gpio-u300.c
@@ -1,8 +1,11 @@
/*
- * U300 GPIO module.
+ *
+ * arch/arm/mach-u300/gpio.c
+ *
*
* Copyright (C) 2007-2009 ST-Ericsson AB
* License terms: GNU General Public License (GPL) version 2
+ * U300 GPIO module.
* This can driver either of the two basic GPIO cores
* available in the U300 platforms:
* COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
diff --git a/drivers/gpio/gpio-it8761e.c b/drivers/gpio/it8761e_gpio.c
index 278b8131701..48fc43c4bdd 100644
--- a/drivers/gpio/gpio-it8761e.c
+++ b/drivers/gpio/it8761e_gpio.c
@@ -1,5 +1,5 @@
/*
- * GPIO interface for IT8761E Super I/O chip
+ * it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
*
* Author: Denis Turischev <denis@compulab.co.il>
*
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/janz-ttl.c
index 813ac077e5d..813ac077e5d 100644
--- a/drivers/gpio/gpio-janz-ttl.c
+++ b/drivers/gpio/janz-ttl.c
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/langwell_gpio.c
index d2eb57c60e0..644ba1255d3 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -1,6 +1,4 @@
-/*
- * Moorestown platform Langwell chip GPIO driver
- *
+/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver
* Copyright (c) 2008 - 2009, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/max7300.c
index a5ca0ab1b37..962f661c18c 100644
--- a/drivers/gpio/gpio-max7300.c
+++ b/drivers/gpio/max7300.c
@@ -1,4 +1,6 @@
/*
+ * drivers/gpio/max7300.c
+ *
* Copyright (C) 2009 Wolfram Sang, Pengutronix
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/max7301.c
index 741acfcbe76..92a100ddef6 100644
--- a/drivers/gpio/gpio-max7301.c
+++ b/drivers/gpio/max7301.c
@@ -1,4 +1,6 @@
/*
+ * drivers/gpio/max7301.c
+ *
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/max730x.c
index 05e2dac60b3..94ce773f95f 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/max730x.c
@@ -1,4 +1,6 @@
/**
+ * drivers/gpio/max7301.c
+ *
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/max732x.c
index 9504120812a..ad6951edc16 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/max732x.c
@@ -1,5 +1,5 @@
/*
- * MAX732x I2C Port Expander with 8/16 I/O
+ * max732x.c - I2C Port Expander with 8/16 I/O
*
* Copyright (C) 2007 Marvell International Ltd.
* Copyright (C) 2008 Jack Ren <jack.ren@marvell.com>
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/mc33880.c
index b3b4652e89e..4ec797593bd 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/mc33880.c
@@ -1,5 +1,5 @@
/*
- * MC33880 high-side/low-side switch GPIO driver
+ * mc33880.c MC33880 high-side/low-side switch GPIO driver
* Copyright (c) 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/mcp23s08.c
index 1ef46e6c2a2..40e076083ec 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -1,12 +1,12 @@
/*
- * MCP23S08 SPI/GPIO gpio expander driver
+ * mcp23s08.c - SPI gpio expander driver
*/
#include <linux/kernel.h>
#include <linux/device.h>
+#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
-#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/spi/mcp23s08.h>
#include <linux/slab.h>
@@ -17,13 +17,13 @@
*/
#define MCP_TYPE_S08 0
#define MCP_TYPE_S17 1
-#define MCP_TYPE_008 2
-#define MCP_TYPE_017 3
/* Registers are all 8 bits wide.
*
* The mcp23s17 has twice as many bits, and can be configured to work
* with either 16 bit registers or with two adjacent 8 bit banks.
+ *
+ * Also, there are I2C versions of both chips.
*/
#define MCP_IODIR 0x00 /* init/reset: all ones */
#define MCP_IPOL 0x01
@@ -51,6 +51,7 @@ struct mcp23s08_ops {
};
struct mcp23s08 {
+ struct spi_device *spi;
u8 addr;
u16 cache[11];
@@ -59,8 +60,9 @@ struct mcp23s08 {
struct gpio_chip chip;
+ struct work_struct work;
+
const struct mcp23s08_ops *ops;
- void *data; /* ops specific data */
};
/* A given spi_device can represent up to eight mcp23sxx chips
@@ -74,74 +76,6 @@ struct mcp23s08_driver_data {
struct mcp23s08 chip[];
};
-/*----------------------------------------------------------------------*/
-
-#ifdef CONFIG_I2C
-
-static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
-{
- return i2c_smbus_read_byte_data(mcp->data, reg);
-}
-
-static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
-{
- return i2c_smbus_write_byte_data(mcp->data, reg, val);
-}
-
-static int
-mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
-{
- while (n--) {
- int ret = mcp23008_read(mcp, reg++);
- if (ret < 0)
- return ret;
- *vals++ = ret;
- }
-
- return 0;
-}
-
-static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg)
-{
- return i2c_smbus_read_word_data(mcp->data, reg << 1);
-}
-
-static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
-{
- return i2c_smbus_write_word_data(mcp->data, reg << 1, val);
-}
-
-static int
-mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
-{
- while (n--) {
- int ret = mcp23017_read(mcp, reg++);
- if (ret < 0)
- return ret;
- *vals++ = ret;
- }
-
- return 0;
-}
-
-static const struct mcp23s08_ops mcp23008_ops = {
- .read = mcp23008_read,
- .write = mcp23008_write,
- .read_regs = mcp23008_read_regs,
-};
-
-static const struct mcp23s08_ops mcp23017_ops = {
- .read = mcp23017_read,
- .write = mcp23017_write,
- .read_regs = mcp23017_read_regs,
-};
-
-#endif /* CONFIG_I2C */
-
-/*----------------------------------------------------------------------*/
-
-#ifdef CONFIG_SPI_MASTER
-
static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
{
u8 tx[2], rx[1];
@@ -149,7 +83,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
tx[0] = mcp->addr | 0x01;
tx[1] = reg;
- status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
+ status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
return (status < 0) ? status : rx[0];
}
@@ -160,7 +94,7 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
tx[0] = mcp->addr;
tx[1] = reg;
tx[2] = val;
- return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
+ return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
}
static int
@@ -175,7 +109,7 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
tx[1] = reg;
tmp = (u8 *)vals;
- status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n);
+ status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
if (status >= 0) {
while (n--)
vals[n] = tmp[n]; /* expand to 16bit */
@@ -190,7 +124,7 @@ static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
tx[0] = mcp->addr | 0x01;
tx[1] = reg << 1;
- status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
+ status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
return (status < 0) ? status : (rx[0] | (rx[1] << 8));
}
@@ -202,7 +136,7 @@ static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
tx[1] = reg << 1;
tx[2] = val;
tx[3] = val >> 8;
- return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
+ return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
}
static int
@@ -216,7 +150,7 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
tx[0] = mcp->addr | 0x01;
tx[1] = reg << 1;
- status = spi_write_then_read(mcp->data, tx, sizeof tx,
+ status = spi_write_then_read(mcp->spi, tx, sizeof tx,
(u8 *)vals, n * 2);
if (status >= 0) {
while (n--)
@@ -238,7 +172,6 @@ static const struct mcp23s08_ops mcp23s17_ops = {
.read_regs = mcp23s17_read_regs,
};
-#endif /* CONFIG_SPI_MASTER */
/*----------------------------------------------------------------------*/
@@ -366,16 +299,17 @@ done:
/*----------------------------------------------------------------------*/
-static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
- void *data, unsigned addr,
+static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
unsigned type, unsigned base, unsigned pullups)
{
- int status;
+ struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
+ struct mcp23s08 *mcp = data->mcp[addr];
+ int status;
mutex_init(&mcp->lock);
- mcp->data = data;
- mcp->addr = addr;
+ mcp->spi = spi;
+ mcp->addr = 0x40 | (addr << 1);
mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get;
@@ -383,43 +317,18 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
mcp->chip.set = mcp23s08_set;
mcp->chip.dbg_show = mcp23s08_dbg_show;
- switch (type) {
-#ifdef CONFIG_SPI_MASTER
- case MCP_TYPE_S08:
- mcp->ops = &mcp23s08_ops;
- mcp->chip.ngpio = 8;
- mcp->chip.label = "mcp23s08";
- break;
-
- case MCP_TYPE_S17:
+ if (type == MCP_TYPE_S17) {
mcp->ops = &mcp23s17_ops;
mcp->chip.ngpio = 16;
mcp->chip.label = "mcp23s17";
- break;
-#endif /* CONFIG_SPI_MASTER */
-
-#ifdef CONFIG_I2C
- case MCP_TYPE_008:
- mcp->ops = &mcp23008_ops;
+ } else {
+ mcp->ops = &mcp23s08_ops;
mcp->chip.ngpio = 8;
- mcp->chip.label = "mcp23008";
- break;
-
- case MCP_TYPE_017:
- mcp->ops = &mcp23017_ops;
- mcp->chip.ngpio = 16;
- mcp->chip.label = "mcp23017";
- break;
-#endif /* CONFIG_I2C */
-
- default:
- dev_err(dev, "invalid device type (%d)\n", type);
- return -EINVAL;
+ mcp->chip.label = "mcp23s08";
}
-
mcp->chip.base = base;
mcp->chip.can_sleep = 1;
- mcp->chip.dev = dev;
+ mcp->chip.dev = &spi->dev;
mcp->chip.owner = THIS_MODULE;
/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
@@ -465,98 +374,11 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
status = gpiochip_add(&mcp->chip);
fail:
if (status < 0)
- dev_dbg(dev, "can't setup chip %d, --> %d\n",
- addr, status);
+ dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
+ addr, status);
return status;
}
-/*----------------------------------------------------------------------*/
-
-#ifdef CONFIG_I2C
-
-static int __devinit mcp230xx_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct mcp23s08_platform_data *pdata;
- struct mcp23s08 *mcp;
- int status;
-
- pdata = client->dev.platform_data;
- if (!pdata || !gpio_is_valid(pdata->base)) {
- dev_dbg(&client->dev, "invalid or missing platform data\n");
- return -EINVAL;
- }
-
- mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
- if (!mcp)
- return -ENOMEM;
-
- status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
- id->driver_data, pdata->base,
- pdata->chip[0].pullups);
- if (status)
- goto fail;
-
- i2c_set_clientdata(client, mcp);
-
- return 0;
-
-fail:
- kfree(mcp);
-
- return status;
-}
-
-static int __devexit mcp230xx_remove(struct i2c_client *client)
-{
- struct mcp23s08 *mcp = i2c_get_clientdata(client);
- int status;
-
- status = gpiochip_remove(&mcp->chip);
- if (status == 0)
- kfree(mcp);
-
- return status;
-}
-
-static const struct i2c_device_id mcp230xx_id[] = {
- { "mcp23008", MCP_TYPE_008 },
- { "mcp23017", MCP_TYPE_017 },
- { },
-};
-MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
-
-static struct i2c_driver mcp230xx_driver = {
- .driver = {
- .name = "mcp230xx",
- .owner = THIS_MODULE,
- },
- .probe = mcp230xx_probe,
- .remove = __devexit_p(mcp230xx_remove),
- .id_table = mcp230xx_id,
-};
-
-static int __init mcp23s08_i2c_init(void)
-{
- return i2c_add_driver(&mcp230xx_driver);
-}
-
-static void mcp23s08_i2c_exit(void)
-{
- i2c_del_driver(&mcp230xx_driver);
-}
-
-#else
-
-static int __init mcp23s08_i2c_init(void) { return 0; }
-static void mcp23s08_i2c_exit(void) { }
-
-#endif /* CONFIG_I2C */
-
-/*----------------------------------------------------------------------*/
-
-#ifdef CONFIG_SPI_MASTER
-
static int mcp23s08_probe(struct spi_device *spi)
{
struct mcp23s08_platform_data *pdata;
@@ -599,8 +421,7 @@ static int mcp23s08_probe(struct spi_device *spi)
continue;
chips--;
data->mcp[addr] = &data->chip[chips];
- status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
- 0x40 | (addr << 1), type, base,
+ status = mcp23s08_probe_one(spi, addr, type, base,
pdata->chip[addr].pullups);
if (status < 0)
goto fail;
@@ -614,6 +435,14 @@ static int mcp23s08_probe(struct spi_device *spi)
* handled here...
*/
+ if (pdata->setup) {
+ status = pdata->setup(spi,
+ pdata->base, data->ngpio,
+ pdata->context);
+ if (status < 0)
+ dev_dbg(&spi->dev, "setup --> %d\n", status);
+ }
+
return 0;
fail:
@@ -633,9 +462,20 @@ fail:
static int mcp23s08_remove(struct spi_device *spi)
{
struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
+ struct mcp23s08_platform_data *pdata = spi->dev.platform_data;
unsigned addr;
int status = 0;
+ if (pdata->teardown) {
+ status = pdata->teardown(spi,
+ pdata->base, data->ngpio,
+ pdata->context);
+ if (status < 0) {
+ dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
+ return status;
+ }
+ }
+
for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
int tmp;
@@ -670,53 +510,20 @@ static struct spi_driver mcp23s08_driver = {
},
};
-static int __init mcp23s08_spi_init(void)
-{
- return spi_register_driver(&mcp23s08_driver);
-}
-
-static void mcp23s08_spi_exit(void)
-{
- spi_unregister_driver(&mcp23s08_driver);
-}
-
-#else
-
-static int __init mcp23s08_spi_init(void) { return 0; }
-static void mcp23s08_spi_exit(void) { }
-
-#endif /* CONFIG_SPI_MASTER */
-
/*----------------------------------------------------------------------*/
static int __init mcp23s08_init(void)
{
- int ret;
-
- ret = mcp23s08_spi_init();
- if (ret)
- goto spi_fail;
-
- ret = mcp23s08_i2c_init();
- if (ret)
- goto i2c_fail;
-
- return 0;
-
- i2c_fail:
- mcp23s08_spi_exit();
- spi_fail:
- return ret;
+ return spi_register_driver(&mcp23s08_driver);
}
-/* register after spi/i2c postcore initcall and before
+/* register after spi postcore initcall and before
* subsys initcalls that may rely on these GPIOs
*/
subsys_initcall(mcp23s08_init);
static void __exit mcp23s08_exit(void)
{
- mcp23s08_spi_exit();
- mcp23s08_i2c_exit();
+ spi_unregister_driver(&mcp23s08_driver);
}
module_exit(mcp23s08_exit);
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/ml_ioh_gpio.c
index a9016f56ed7..1bc621ac353 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/ml_ioh_gpio.c
@@ -233,7 +233,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
return 0;
err_gpiochip_add:
- while (--i >= 0) {
+ for (; i != 0; i--) {
chip--;
ret = gpiochip_remove(&chip->gpio);
if (ret)
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/pca953x.c
index c43b8ff626a..0451d7ac94a 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -1,5 +1,5 @@
/*
- * PCA953x 4/8/16 bit I/O ports
+ * pca953x.c - 4/8/16 bit I/O ports
*
* Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
* Copyright (C) 2007 Marvell International Ltd.
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#ifdef CONFIG_OF_GPIO
#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
#endif
#define PCA953X_INPUT 0
@@ -84,6 +85,7 @@ struct pca953x_chip {
#endif
struct i2c_client *client;
+ struct pca953x_platform_data *dyn_pdata;
struct gpio_chip gpio_chip;
const char *const *names;
int chip_type;
@@ -435,7 +437,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
do {
level = __ffs(pending);
- handle_nested_irq(level + chip->irq_base);
+ generic_handle_irq(level + chip->irq_base);
pending &= ~(1 << level);
} while (pending);
@@ -444,13 +446,13 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
}
static int pca953x_irq_setup(struct pca953x_chip *chip,
- const struct i2c_device_id *id,
- int irq_base)
+ const struct i2c_device_id *id)
{
struct i2c_client *client = chip->client;
+ struct pca953x_platform_data *pdata = client->dev.platform_data;
int ret, offset = 0;
- if (irq_base != -1
+ if (pdata->irq_base != -1
&& (id->driver_data & PCA_INT)) {
int lvl;
@@ -472,19 +474,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
* this purpose.
*/
chip->irq_stat &= chip->reg_direction;
+ chip->irq_base = pdata->irq_base;
mutex_init(&chip->irq_lock);
- chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
- if (chip->irq_base < 0)
- goto out_failed;
-
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
int irq = lvl + chip->irq_base;
- irq_clear_status_flags(irq, IRQ_NOREQUEST);
irq_set_chip_data(irq, chip);
- irq_set_chip(irq, &pca953x_irq_chip);
- irq_set_nested_thread(irq, true);
+ irq_set_chip_and_handler(irq, &pca953x_irq_chip,
+ handle_simple_irq);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
@@ -495,7 +493,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
ret = request_threaded_irq(client->irq,
NULL,
pca953x_irq_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(&client->dev), chip);
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
@@ -515,19 +514,17 @@ out_failed:
static void pca953x_irq_teardown(struct pca953x_chip *chip)
{
- if (chip->irq_base != -1) {
- irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
+ if (chip->irq_base != -1)
free_irq(chip->client->irq, chip);
- }
}
#else /* CONFIG_GPIO_PCA953X_IRQ */
static int pca953x_irq_setup(struct pca953x_chip *chip,
- const struct i2c_device_id *id,
- int irq_base)
+ const struct i2c_device_id *id)
{
struct i2c_client *client = chip->client;
+ struct pca953x_platform_data *pdata = client->dev.platform_data;
- if (irq_base != -1 && (id->driver_data & PCA_INT))
+ if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0;
@@ -544,39 +541,46 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip)
#ifdef CONFIG_OF_GPIO
/*
* Translate OpenFirmware node properties into platform_data
- * WARNING: This is DEPRECATED and will be removed eventually!
*/
-void
-pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
+static struct pca953x_platform_data *
+pca953x_get_alt_pdata(struct i2c_client *client)
{
+ struct pca953x_platform_data *pdata;
struct device_node *node;
const __be32 *val;
int size;
node = client->dev.of_node;
if (node == NULL)
- return;
+ return NULL;
+
+ pdata = kzalloc(sizeof(struct pca953x_platform_data), GFP_KERNEL);
+ if (pdata == NULL) {
+ dev_err(&client->dev, "Unable to allocate platform_data\n");
+ return NULL;
+ }
- *gpio_base = -1;
+ pdata->gpio_base = -1;
val = of_get_property(node, "linux,gpio-base", &size);
- WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);
if (val) {
if (size != sizeof(*val))
dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
node->full_name);
else
- *gpio_base = be32_to_cpup(val);
+ pdata->gpio_base = be32_to_cpup(val);
}
val = of_get_property(node, "polarity", NULL);
- WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__);
if (val)
- *invert = *val;
+ pdata->invert = *val;
+
+ return pdata;
}
#else
-void
-pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
+static struct pca953x_platform_data *
+pca953x_get_alt_pdata(struct i2c_client *client)
{
+ return NULL;
}
#endif
@@ -638,7 +642,6 @@ static int __devinit pca953x_probe(struct i2c_client *client,
{
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
- int irq_base=0, invert=0;
int ret = 0;
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
@@ -646,22 +649,26 @@ static int __devinit pca953x_probe(struct i2c_client *client,
return -ENOMEM;
pdata = client->dev.platform_data;
- if (pdata) {
- irq_base = pdata->irq_base;
- chip->gpio_start = pdata->gpio_base;
- invert = pdata->invert;
- chip->names = pdata->names;
- } else {
- pca953x_get_alt_pdata(client, &chip->gpio_start, &invert);
-#ifdef CONFIG_OF_GPIO
- /* If I2C node has no interrupts property, disable GPIO interrupts */
- if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL)
- irq_base = -1;
-#endif
+ if (pdata == NULL) {
+ pdata = pca953x_get_alt_pdata(client);
+ /*
+ * Unlike normal platform_data, this is allocated
+ * dynamically and must be freed in the driver
+ */
+ chip->dyn_pdata = pdata;
+ }
+
+ if (pdata == NULL) {
+ dev_dbg(&client->dev, "no platform data\n");
+ ret = -EINVAL;
+ goto out_failed;
}
chip->client = client;
+ chip->gpio_start = pdata->gpio_base;
+
+ chip->names = pdata->names;
chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
mutex_init(&chip->i2c_lock);
@@ -672,13 +679,13 @@ static int __devinit pca953x_probe(struct i2c_client *client,
pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
if (chip->chip_type == PCA953X_TYPE)
- device_pca953x_init(chip, invert);
+ device_pca953x_init(chip, pdata->invert);
else if (chip->chip_type == PCA957X_TYPE)
- device_pca957x_init(chip, invert);
+ device_pca957x_init(chip, pdata->invert);
else
goto out_failed;
- ret = pca953x_irq_setup(chip, id, irq_base);
+ ret = pca953x_irq_setup(chip, id);
if (ret)
goto out_failed;
@@ -686,7 +693,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
if (ret)
goto out_failed_irq;
- if (pdata && pdata->setup) {
+ if (pdata->setup) {
ret = pdata->setup(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0)
@@ -699,6 +706,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
out_failed_irq:
pca953x_irq_teardown(chip);
out_failed:
+ kfree(chip->dyn_pdata);
kfree(chip);
return ret;
}
@@ -709,7 +717,7 @@ static int pca953x_remove(struct i2c_client *client)
struct pca953x_chip *chip = i2c_get_clientdata(client);
int ret = 0;
- if (pdata && pdata->teardown) {
+ if (pdata->teardown) {
ret = pdata->teardown(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context);
if (ret < 0) {
@@ -727,6 +735,7 @@ static int pca953x_remove(struct i2c_client *client)
}
pca953x_irq_teardown(chip);
+ kfree(chip->dyn_pdata);
kfree(chip);
return 0;
}
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/pcf857x.c
index 7369fdda92b..879b473aab5 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -1,5 +1,5 @@
/*
- * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
+ * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
*
* Copyright (C) 2007 David Brownell
*
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/pch_gpio.c
index 36919e77c49..36919e77c49 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/pch_gpio.c
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/pl061.c
index 2c5a18f32bf..6fcb28cdd86 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/pl061.c
@@ -1,5 +1,7 @@
/*
- * Copyright (C) 2008, 2009 Provigent Ltd.
+ * linux/drivers/gpio/pl061.c
+ *
+ * Copyright (C) 2008, 2009 Provigent Ltd.
*
* 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
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/rdc321x-gpio.c
index 2762698e020..2762698e020 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/rdc321x-gpio.c
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/sch_gpio.c
index 16351584549..56060421cdf 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/sch_gpio.c
@@ -1,5 +1,5 @@
/*
- * GPIO interface for Intel Poulsbo SCH
+ * sch_gpio.c - GPIO interface for Intel Poulsbo SCH
*
* Copyright (c) 2010 CompuLab Ltd
* Author: Denis Turischev <denis@compulab.co.il>
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/stmpe-gpio.c
index 4c980b57332..4c980b57332 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/stmpe-gpio.c
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/sx150x.c
index a4f73534394..a4f73534394 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/sx150x.c
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/tc3589x-gpio.c
index 2a82e8999a4..2a82e8999a4 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/tc3589x-gpio.c
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/timbgpio.c
index c593bd46bfb..0265872e57d 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/timbgpio.c
@@ -1,5 +1,5 @@
/*
- * Timberdale FPGA GPIO driver
+ * timbgpio.c timberdale FPGA GPIO driver
* Copyright (c) 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/tps65910-gpio.c
index b9c1c297669..15097ca616d 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/tps65910-gpio.c
@@ -1,5 +1,5 @@
/*
- * TI TPS6591x GPIO driver
+ * tps65910-gpio.c -- TI TPS6591x
*
* Copyright 2010 Texas Instruments Inc.
*
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/twl4030-gpio.c
index b8b4f228757..57635ac35a7 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -1,5 +1,5 @@
/*
- * Access to GPIOs on TWL4030/TPS659x0 chips
+ * twl4030_gpio.c -- access to GPIOs on TWL4030/TPS659x0 chips
*
* Copyright (C) 2006-2007 Texas Instruments, Inc.
* Copyright (C) 2006 MontaVista Software, Inc.
diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/ucb1400_gpio.c
index 50e6bd1392c..50e6bd1392c 100644
--- a/drivers/gpio/gpio-ucb1400.c
+++ b/drivers/gpio/ucb1400_gpio.c
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/vr41xx_giu.c
index 98723cb9ac6..a365be040b3 100644
--- a/drivers/gpio/gpio-vr41xx.c
+++ b/drivers/gpio/vr41xx_giu.c
@@ -518,7 +518,7 @@ static int __devinit giu_probe(struct platform_device *pdev)
if (!res)
return -EBUSY;
- giu_base = ioremap(res->start, resource_size(res));
+ giu_base = ioremap(res->start, res->end - res->start + 1);
if (!giu_base)
return -ENOMEM;
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/vx855_gpio.c
index ef5aabd8b8b..ef5aabd8b8b 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/vx855_gpio.c
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/wm831x-gpio.c
index deb949e75ec..2bcfb0be09f 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/wm831x-gpio.c
@@ -1,5 +1,5 @@
/*
- * gpiolib support for Wolfson WM831x PMICs
+ * wm831x-gpio.c -- gpiolib support for Wolfson WM831x PMICs
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/wm8350-gpiolib.c
index a06af515483..359999290f5 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/wm8350-gpiolib.c
@@ -1,5 +1,5 @@
/*
- * gpiolib support for Wolfson WM835x PMICs
+ * wm835x-gpiolib.c -- gpiolib support for Wolfson WM835x PMICs
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/wm8994-gpio.c
index 96198f3fab7..c822baacd8f 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/wm8994-gpio.c
@@ -1,5 +1,5 @@
/*
- * gpiolib support for Wolfson WM8994
+ * wm8994-gpio.c -- gpiolib support for Wolfson WM8994
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/xilinx_gpio.c
index 846fbd5e31b..846fbd5e31b 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/xilinx_gpio.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d1bf8724b58..45dc6aa62ba 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -267,7 +267,7 @@ config INPUT_TWL4030_PWRBUTTON
config INPUT_TWL4030_VIBRA
tristate "Support for TWL4030 Vibrator"
depends on TWL4030_CORE
- select MFD_TWL4030_AUDIO
+ select TWL4030_CODEC
select INPUT_FF_MEMLESS
help
This option enables support for TWL4030 Vibrator Driver.
@@ -275,17 +275,6 @@ config INPUT_TWL4030_VIBRA
To compile this driver as a module, choose M here. The module will
be called twl4030_vibra.
-config INPUT_TWL6040_VIBRA
- tristate "Support for TWL6040 Vibrator"
- depends on TWL4030_CORE
- select TWL6040_CORE
- select INPUT_FF_MEMLESS
- help
- This option enables support for TWL6040 Vibrator Driver.
-
- To compile this driver as a module, choose M here. The module will
- be called twl6040_vibra.
-
config INPUT_UINPUT
tristate "User level driver support"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 4da7c3a60e0..38efb2cb182 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -40,7 +40,6 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
-obj-$(CONFIG_INPUT_TWL6040_VIBRA) += twl6040-vibra.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 3c1a432c14d..014dd4ad0d4 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -28,7 +28,7 @@
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/i2c/twl.h>
-#include <linux/mfd/twl4030-audio.h>
+#include <linux/mfd/twl4030-codec.h>
#include <linux/input.h>
#include <linux/slab.h>
@@ -67,7 +67,7 @@ static void vibra_enable(struct vibra_info *info)
{
u8 reg;
- twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER);
+ twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
/* turn H-Bridge on */
twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
@@ -75,7 +75,7 @@ static void vibra_enable(struct vibra_info *info)
twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
(reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
- twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL);
+ twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
info->enabled = true;
}
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info)
twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
(reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL);
- twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL);
- twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER);
+ twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
+ twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
info->enabled = false;
}
@@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
{
- struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+ struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
struct vibra_info *info;
int ret;
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
deleted file mode 100644
index c43002e7ec7..00000000000
--- a/drivers/input/misc/twl6040-vibra.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * twl6040-vibra.c - TWL6040 Vibrator driver
- *
- * Author: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
- * Author: Misael Lopez Cruz <misael.lopez@ti.com>
- *
- * Copyright: (C) 2011 Texas Instruments, Inc.
- *
- * Based on twl4030-vibra.c by Henrik Saari <henrik.saari@nokia.com>
- * Felipe Balbi <felipe.balbi@nokia.com>
- * Jari Vanhala <ext-javi.vanhala@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., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/i2c/twl.h>
-#include <linux/mfd/twl6040.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/regulator/consumer.h>
-
-#define EFFECT_DIR_180_DEG 0x8000
-
-/* Recommended modulation index 85% */
-#define TWL6040_VIBRA_MOD 85
-
-#define TWL6040_NUM_SUPPLIES 2
-
-struct vibra_info {
- struct device *dev;
- struct input_dev *input_dev;
- struct workqueue_struct *workqueue;
- struct work_struct play_work;
- struct mutex mutex;
- int irq;
-
- bool enabled;
- int weak_speed;
- int strong_speed;
- int direction;
-
- unsigned int vibldrv_res;
- unsigned int vibrdrv_res;
- unsigned int viblmotor_res;
- unsigned int vibrmotor_res;
-
- struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES];
-
- struct twl6040 *twl6040;
-};
-
-static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
-{
- struct vibra_info *info = data;
- struct twl6040 *twl6040 = info->twl6040;
- u8 status;
-
- status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
- if (status & TWL6040_VIBLOCDET) {
- dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
- twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
- TWL6040_VIBENAL);
- }
- if (status & TWL6040_VIBROCDET) {
- dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
- twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
- TWL6040_VIBENAR);
- }
-
- return IRQ_HANDLED;
-}
-
-static void twl6040_vibra_enable(struct vibra_info *info)
-{
- struct twl6040 *twl6040 = info->twl6040;
- int ret;
-
- ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies);
- if (ret) {
- dev_err(info->dev, "failed to enable regulators %d\n", ret);
- return;
- }
-
- twl6040_power(info->twl6040, 1);
- if (twl6040->rev <= TWL6040_REV_ES1_1) {
- /*
- * ERRATA: Disable overcurrent protection for at least
- * 3ms when enabling vibrator drivers to avoid false
- * overcurrent detection
- */
- twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
- TWL6040_VIBENAL | TWL6040_VIBCTRLL);
- twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
- TWL6040_VIBENAR | TWL6040_VIBCTRLR);
- usleep_range(3000, 3500);
- }
-
- twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
- TWL6040_VIBENAL);
- twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
- TWL6040_VIBENAR);
-
- info->enabled = true;
-}
-
-static void twl6040_vibra_disable(struct vibra_info *info)
-{
- struct twl6040 *twl6040 = info->twl6040;
-
- twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL, 0x00);
- twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR, 0x00);
- twl6040_power(info->twl6040, 0);
-
- regulator_bulk_disable(ARRAY_SIZE(info->supplies), info->supplies);
-
- info->enabled = false;
-}
-
-static u8 twl6040_vibra_code(int vddvib, int vibdrv_res, int motor_res,
- int speed, int direction)
-{
- int vpk, max_code;
- u8 vibdat;
-
- /* output swing */
- vpk = (vddvib * motor_res * TWL6040_VIBRA_MOD) /
- (100 * (vibdrv_res + motor_res));
-
- /* 50mV per VIBDAT code step */
- max_code = vpk / 50;
- if (max_code > TWL6040_VIBDAT_MAX)
- max_code = TWL6040_VIBDAT_MAX;
-
- /* scale speed to max allowed code */
- vibdat = (u8)((speed * max_code) / USHRT_MAX);
-
- /* 2's complement for direction > 180 degrees */
- vibdat *= direction;
-
- return vibdat;
-}
-
-static void twl6040_vibra_set_effect(struct vibra_info *info)
-{
- struct twl6040 *twl6040 = info->twl6040;
- u8 vibdatl, vibdatr;
- int volt;
-
- /* weak motor */
- volt = regulator_get_voltage(info->supplies[0].consumer) / 1000;
- vibdatl = twl6040_vibra_code(volt, info->vibldrv_res,
- info->viblmotor_res,
- info->weak_speed, info->direction);
-
- /* strong motor */
- volt = regulator_get_voltage(info->supplies[1].consumer) / 1000;
- vibdatr = twl6040_vibra_code(volt, info->vibrdrv_res,
- info->vibrmotor_res,
- info->strong_speed, info->direction);
-
- twl6040_reg_write(twl6040, TWL6040_REG_VIBDATL, vibdatl);
- twl6040_reg_write(twl6040, TWL6040_REG_VIBDATR, vibdatr);
-}
-
-static void vibra_play_work(struct work_struct *work)
-{
- struct vibra_info *info = container_of(work,
- struct vibra_info, play_work);
-
- mutex_lock(&info->mutex);
-
- if (info->weak_speed || info->strong_speed) {
- if (!info->enabled)
- twl6040_vibra_enable(info);
-
- twl6040_vibra_set_effect(info);
- } else if (info->enabled)
- twl6040_vibra_disable(info);
-
- mutex_unlock(&info->mutex);
-}
-
-static int vibra_play(struct input_dev *input, void *data,
- struct ff_effect *effect)
-{
- struct vibra_info *info = input_get_drvdata(input);
- int ret;
-
- info->weak_speed = effect->u.rumble.weak_magnitude;
- info->strong_speed = effect->u.rumble.strong_magnitude;
- info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
-
- ret = queue_work(info->workqueue, &info->play_work);
- if (!ret) {
- dev_info(&input->dev, "work is already on queue\n");
- return ret;
- }
-
- return 0;
-}
-
-static void twl6040_vibra_close(struct input_dev *input)
-{
- struct vibra_info *info = input_get_drvdata(input);
-
- cancel_work_sync(&info->play_work);
-
- mutex_lock(&info->mutex);
-
- if (info->enabled)
- twl6040_vibra_disable(info);
-
- mutex_unlock(&info->mutex);
-}
-
-#if CONFIG_PM_SLEEP
-static int twl6040_vibra_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct vibra_info *info = platform_get_drvdata(pdev);
-
- mutex_lock(&info->mutex);
-
- if (info->enabled)
- twl6040_vibra_disable(info);
-
- mutex_unlock(&info->mutex);
-
- return 0;
-}
-
-#endif
-
-static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);
-
-static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
-{
- struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
- struct vibra_info *info;
- int ret;
-
- if (!pdata) {
- dev_err(&pdev->dev, "platform_data not available\n");
- return -EINVAL;
- }
-
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- dev_err(&pdev->dev, "couldn't allocate memory\n");
- return -ENOMEM;
- }
-
- info->dev = &pdev->dev;
- info->twl6040 = dev_get_drvdata(pdev->dev.parent);
- info->vibldrv_res = pdata->vibldrv_res;
- info->vibrdrv_res = pdata->vibrdrv_res;
- info->viblmotor_res = pdata->viblmotor_res;
- info->vibrmotor_res = pdata->vibrmotor_res;
- if ((!info->vibldrv_res && !info->viblmotor_res) ||
- (!info->vibrdrv_res && !info->vibrmotor_res)) {
- dev_err(info->dev, "invalid vibra driver/motor resistance\n");
- ret = -EINVAL;
- goto err_kzalloc;
- }
-
- info->irq = platform_get_irq(pdev, 0);
- if (info->irq < 0) {
- dev_err(info->dev, "invalid irq\n");
- ret = -EINVAL;
- goto err_kzalloc;
- }
-
- mutex_init(&info->mutex);
-
- info->input_dev = input_allocate_device();
- if (info->input_dev == NULL) {
- dev_err(info->dev, "couldn't allocate input device\n");
- ret = -ENOMEM;
- goto err_kzalloc;
- }
-
- input_set_drvdata(info->input_dev, info);
-
- info->input_dev->name = "twl6040:vibrator";
- info->input_dev->id.version = 1;
- info->input_dev->dev.parent = pdev->dev.parent;
- info->input_dev->close = twl6040_vibra_close;
- __set_bit(FF_RUMBLE, info->input_dev->ffbit);
-
- ret = input_ff_create_memless(info->input_dev, NULL, vibra_play);
- if (ret < 0) {
- dev_err(info->dev, "couldn't register vibrator to FF\n");
- goto err_ialloc;
- }
-
- ret = input_register_device(info->input_dev);
- if (ret < 0) {
- dev_err(info->dev, "couldn't register input device\n");
- goto err_iff;
- }
-
- platform_set_drvdata(pdev, info);
-
- ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0,
- "twl6040_irq_vib", info);
- if (ret) {
- dev_err(info->dev, "VIB IRQ request failed: %d\n", ret);
- goto err_irq;
- }
-
- info->supplies[0].supply = "vddvibl";
- info->supplies[1].supply = "vddvibr";
- ret = regulator_bulk_get(info->dev, ARRAY_SIZE(info->supplies),
- info->supplies);
- if (ret) {
- dev_err(info->dev, "couldn't get regulators %d\n", ret);
- goto err_regulator;
- }
-
- if (pdata->vddvibl_uV) {
- ret = regulator_set_voltage(info->supplies[0].consumer,
- pdata->vddvibl_uV,
- pdata->vddvibl_uV);
- if (ret) {
- dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
- ret);
- goto err_voltage;
- }
- }
-
- if (pdata->vddvibr_uV) {
- ret = regulator_set_voltage(info->supplies[1].consumer,
- pdata->vddvibr_uV,
- pdata->vddvibr_uV);
- if (ret) {
- dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
- ret);
- goto err_voltage;
- }
- }
-
- info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0);
- if (info->workqueue == NULL) {
- dev_err(info->dev, "couldn't create workqueue\n");
- ret = -ENOMEM;
- goto err_voltage;
- }
- INIT_WORK(&info->play_work, vibra_play_work);
-
- return 0;
-
-err_voltage:
- regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
-err_regulator:
- free_irq(info->irq, info);
-err_irq:
- input_unregister_device(info->input_dev);
- info->input_dev = NULL;
-err_iff:
- if (info->input_dev)
- input_ff_destroy(info->input_dev);
-err_ialloc:
- input_free_device(info->input_dev);
-err_kzalloc:
- kfree(info);
- return ret;
-}
-
-static int __devexit twl6040_vibra_remove(struct platform_device *pdev)
-{
- struct vibra_info *info = platform_get_drvdata(pdev);
-
- input_unregister_device(info->input_dev);
- free_irq(info->irq, info);
- regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
- destroy_workqueue(info->workqueue);
- kfree(info);
-
- return 0;
-}
-
-static struct platform_driver twl6040_vibra_driver = {
- .probe = twl6040_vibra_probe,
- .remove = __devexit_p(twl6040_vibra_remove),
- .driver = {
- .name = "twl6040-vibra",
- .owner = THIS_MODULE,
- .pm = &twl6040_vibra_pm_ops,
- },
-};
-
-static int __init twl6040_vibra_init(void)
-{
- return platform_driver_register(&twl6040_vibra_driver);
-}
-module_init(twl6040_vibra_init);
-
-static void __exit twl6040_vibra_exit(void)
-{
- platform_driver_unregister(&twl6040_vibra_driver);
-}
-module_exit(twl6040_vibra_exit);
-
-MODULE_ALIAS("platform:twl6040-vibra");
-MODULE_DESCRIPTION("TWL6040 Vibra driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
-MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 6c21c2986ca..713d43b4e56 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -92,7 +92,7 @@ config LEDS_NET48XX
config LEDS_NET5501
tristate "LED Support for Soekris net5501 series Error LED"
depends on LEDS_TRIGGERS
- depends on X86 && GPIO_CS5535
+ depends on X86 && LEDS_GPIO_PLATFORM && GPIO_CS5535
select LEDS_TRIGGER_DEFAULT_ON
default n
help
@@ -182,6 +182,23 @@ config LEDS_GPIO
defined as platform devices and/or OpenFirmware platform devices.
The code to use these bindings can be selected below.
+config LEDS_GPIO_PLATFORM
+ bool "Platform device bindings for GPIO LEDs"
+ depends on LEDS_GPIO
+ default y
+ help
+ Let the leds-gpio driver drive LEDs which have been defined as
+ platform devices. If you don't know what this means, say yes.
+
+config LEDS_GPIO_OF
+ bool "OpenFirmware platform device bindings for GPIO LEDs"
+ depends on LEDS_GPIO && OF_DEVICE
+ default y
+ help
+ Let the leds-gpio driver drive LEDs which have been defined as
+ of_platform devices. For instance, LEDs which are listed in a "dts"
+ file.
+
config LEDS_LP3944
tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
depends on LEDS_CLASS
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 3d8bc327a68..b0480c8fbcb 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -165,7 +165,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
}
/* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_OF_GPIO
+#ifdef CONFIG_LEDS_GPIO_OF
static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node, *child;
@@ -223,13 +223,13 @@ static const struct of_device_id of_gpio_leds_match[] = {
{ .compatible = "gpio-leds", },
{},
};
-#else /* CONFIG_OF_GPIO */
+#else
static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
{
return NULL;
}
#define of_gpio_leds_match NULL
-#endif /* CONFIG_OF_GPIO */
+#endif
static int __devinit gpio_led_probe(struct platform_device *pdev)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 37b83eb6d70..6ca938a6bf9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -218,7 +218,7 @@ config TWL4030_POWER
and load scripts controlling which resources are switched off/on
or reset when a sleep, wakeup or warm reset event occurs.
-config MFD_TWL4030_AUDIO
+config TWL4030_CODEC
bool
depends on TWL4030_CORE
select MFD_CORE
@@ -233,12 +233,6 @@ config TWL6030_PWM
Say yes here if you want support for TWL6030 PWM.
This is used to control charging LED brightness.
-config TWL6040_CORE
- bool
- depends on TWL4030_CORE && GENERIC_HARDIRQS
- select MFD_CORE
- default n
-
config MFD_STMPE
bool "Support STMicroelectronics STMPE"
depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 22a280fcb70..d7d47d2a4c7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -40,9 +40,8 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
-obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o
+obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
-obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index a2eddc70995..b8f2a4e7f6e 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -110,7 +110,7 @@
#endif
#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
- defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
+ defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE)
#define twl_has_codec() true
#else
#define twl_has_codec() false
@@ -815,19 +815,20 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}
- if (twl_has_codec() && pdata->audio && twl_class_is_4030()) {
+ if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
child = add_child(sub_chip_id, "twl4030-audio",
- pdata->audio, sizeof(*pdata->audio),
+ pdata->codec, sizeof(*pdata->codec),
false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}
- if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
+ /* Phoenix codec driver is probed directly atm */
+ if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
- child = add_child(sub_chip_id, "twl6040",
- pdata->audio, sizeof(*pdata->audio),
+ child = add_child(sub_chip_id, "twl6040-codec",
+ pdata->codec, sizeof(*pdata->codec),
false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
deleted file mode 100644
index ae51ab5d0e5..00000000000
--- a/drivers/mfd/twl4030-audio.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * MFD driver for twl4030 audio submodule, which contains an audio codec, and
- * the vibra control.
- *
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright: (C) 2009 Nokia Corporation
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/twl.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl4030-audio.h>
-
-#define TWL4030_AUDIO_CELLS 2
-
-static struct platform_device *twl4030_audio_dev;
-
-struct twl4030_audio_resource {
- int request_count;
- u8 reg;
- u8 mask;
-};
-
-struct twl4030_audio {
- unsigned int audio_mclk;
- struct mutex mutex;
- struct twl4030_audio_resource resource[TWL4030_AUDIO_RES_MAX];
- struct mfd_cell cells[TWL4030_AUDIO_CELLS];
-};
-
-/*
- * Modify the resource, the function returns the content of the register
- * after the modification.
- */
-static int twl4030_audio_set_resource(enum twl4030_audio_res id, int enable)
-{
- struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
- u8 val;
-
- twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
- audio->resource[id].reg);
-
- if (enable)
- val |= audio->resource[id].mask;
- else
- val &= ~audio->resource[id].mask;
-
- twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
- val, audio->resource[id].reg);
-
- return val;
-}
-
-static inline int twl4030_audio_get_resource(enum twl4030_audio_res id)
-{
- struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
- u8 val;
-
- twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
- audio->resource[id].reg);
-
- return val;
-}
-
-/*
- * Enable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_audio_enable_resource(enum twl4030_audio_res id)
-{
- struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
- int val;
-
- if (id >= TWL4030_AUDIO_RES_MAX) {
- dev_err(&twl4030_audio_dev->dev,
- "Invalid resource ID (%u)\n", id);
- return -EINVAL;
- }
-
- mutex_lock(&audio->mutex);
- if (!audio->resource[id].request_count)
- /* Resource was disabled, enable it */
- val = twl4030_audio_set_resource(id, 1);
- else
- val = twl4030_audio_get_resource(id);
-
- audio->resource[id].request_count++;
- mutex_unlock(&audio->mutex);
-
- return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource);
-
-/*
- * Disable the resource.
- * The function returns with error or the content of the register
- */
-int twl4030_audio_disable_resource(unsigned id)
-{
- struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
- int val;
-
- if (id >= TWL4030_AUDIO_RES_MAX) {
- dev_err(&twl4030_audio_dev->dev,
- "Invalid resource ID (%u)\n", id);
- return -EINVAL;
- }
-
- mutex_lock(&audio->mutex);
- if (!audio->resource[id].request_count) {
- dev_err(&twl4030_audio_dev->dev,
- "Resource has been disabled already (%u)\n", id);
- mutex_unlock(&audio->mutex);
- return -EPERM;
- }
- audio->resource[id].request_count--;
-
- if (!audio->resource[id].request_count)
- /* Resource can be disabled now */
- val = twl4030_audio_set_resource(id, 0);
- else
- val = twl4030_audio_get_resource(id);
-
- mutex_unlock(&audio->mutex);
-
- return val;
-}
-EXPORT_SYMBOL_GPL(twl4030_audio_disable_resource);
-
-unsigned int twl4030_audio_get_mclk(void)
-{
- struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
-
- return audio->audio_mclk;
-}
-EXPORT_SYMBOL_GPL(twl4030_audio_get_mclk);
-
-static int __devinit twl4030_audio_probe(struct platform_device *pdev)
-{
- struct twl4030_audio *audio;
- struct twl4030_audio_data *pdata = pdev->dev.platform_data;
- struct mfd_cell *cell = NULL;
- int ret, childs = 0;
- u8 val;
-
- if (!pdata) {
- dev_err(&pdev->dev, "Platform data is missing\n");
- return -EINVAL;
- }
-
- /* Configure APLL_INFREQ and disable APLL if enabled */
- val = 0;
- switch (pdata->audio_mclk) {
- case 19200000:
- val |= TWL4030_APLL_INFREQ_19200KHZ;
- break;
- case 26000000:
- val |= TWL4030_APLL_INFREQ_26000KHZ;
- break;
- case 38400000:
- val |= TWL4030_APLL_INFREQ_38400KHZ;
- break;
- default:
- dev_err(&pdev->dev, "Invalid audio_mclk\n");
- return -EINVAL;
- }
- twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
- val, TWL4030_REG_APLL_CTL);
-
- audio = kzalloc(sizeof(struct twl4030_audio), GFP_KERNEL);
- if (!audio)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, audio);
-
- twl4030_audio_dev = pdev;
- mutex_init(&audio->mutex);
- audio->audio_mclk = pdata->audio_mclk;
-
- /* Codec power */
- audio->resource[TWL4030_AUDIO_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
- audio->resource[TWL4030_AUDIO_RES_POWER].mask = TWL4030_CODECPDZ;
-
- /* PLL */
- audio->resource[TWL4030_AUDIO_RES_APLL].reg = TWL4030_REG_APLL_CTL;
- audio->resource[TWL4030_AUDIO_RES_APLL].mask = TWL4030_APLL_EN;
-
- if (pdata->codec) {
- cell = &audio->cells[childs];
- cell->name = "twl4030-codec";
- cell->platform_data = pdata->codec;
- cell->pdata_size = sizeof(*pdata->codec);
- childs++;
- }
- if (pdata->vibra) {
- cell = &audio->cells[childs];
- cell->name = "twl4030-vibra";
- cell->platform_data = pdata->vibra;
- cell->pdata_size = sizeof(*pdata->vibra);
- childs++;
- }
-
- if (childs)
- ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
- childs, NULL, 0);
- else {
- dev_err(&pdev->dev, "No platform data found for childs\n");
- ret = -ENODEV;
- }
-
- if (!ret)
- return 0;
-
- platform_set_drvdata(pdev, NULL);
- kfree(audio);
- twl4030_audio_dev = NULL;
- return ret;
-}
-
-static int __devexit twl4030_audio_remove(struct platform_device *pdev)
-{
- struct twl4030_audio *audio = platform_get_drvdata(pdev);
-
- mfd_remove_devices(&pdev->dev);
- platform_set_drvdata(pdev, NULL);
- kfree(audio);
- twl4030_audio_dev = NULL;
-
- return 0;
-}
-
-MODULE_ALIAS("platform:twl4030-audio");
-
-static struct platform_driver twl4030_audio_driver = {
- .probe = twl4030_audio_probe,
- .remove = __devexit_p(twl4030_audio_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "twl4030-audio",
- },
-};
-
-static int __devinit twl4030_audio_init(void)
-{
- return platform_driver_register(&twl4030_audio_driver);
-}
-module_init(twl4030_audio_init);
-
-static void __devexit twl4030_audio_exit(void)
-{
- platform_driver_unregister(&twl4030_audio_driver);
-}
-module_exit(twl4030_audio_exit);
-
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
new file mode 100644
index 00000000000..2bf4136464c
--- /dev/null
+++ b/drivers/mfd/twl4030-codec.c
@@ -0,0 +1,277 @@
+/*
+ * MFD driver for twl4030 codec submodule
+ *
+ * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * Copyright: (C) 2009 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/twl4030-codec.h>
+
+#define TWL4030_CODEC_CELLS 2
+
+static struct platform_device *twl4030_codec_dev;
+
+struct twl4030_codec_resource {
+ int request_count;
+ u8 reg;
+ u8 mask;
+};
+
+struct twl4030_codec {
+ unsigned int audio_mclk;
+ struct mutex mutex;
+ struct twl4030_codec_resource resource[TWL4030_CODEC_RES_MAX];
+ struct mfd_cell cells[TWL4030_CODEC_CELLS];
+};
+
+/*
+ * Modify the resource, the function returns the content of the register
+ * after the modification.
+ */
+static int twl4030_codec_set_resource(enum twl4030_codec_res id, int enable)
+{
+ struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
+ u8 val;
+
+ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+ codec->resource[id].reg);
+
+ if (enable)
+ val |= codec->resource[id].mask;
+ else
+ val &= ~codec->resource[id].mask;
+
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ val, codec->resource[id].reg);
+
+ return val;
+}
+
+static inline int twl4030_codec_get_resource(enum twl4030_codec_res id)
+{
+ struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
+ u8 val;
+
+ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val,
+ codec->resource[id].reg);
+
+ return val;
+}
+
+/*
+ * Enable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_codec_enable_resource(enum twl4030_codec_res id)
+{
+ struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
+ int val;
+
+ if (id >= TWL4030_CODEC_RES_MAX) {
+ dev_err(&twl4030_codec_dev->dev,
+ "Invalid resource ID (%u)\n", id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&codec->mutex);
+ if (!codec->resource[id].request_count)
+ /* Resource was disabled, enable it */
+ val = twl4030_codec_set_resource(id, 1);
+ else
+ val = twl4030_codec_get_resource(id);
+
+ codec->resource[id].request_count++;
+ mutex_unlock(&codec->mutex);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_codec_enable_resource);
+
+/*
+ * Disable the resource.
+ * The function returns with error or the content of the register
+ */
+int twl4030_codec_disable_resource(unsigned id)
+{
+ struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
+ int val;
+
+ if (id >= TWL4030_CODEC_RES_MAX) {
+ dev_err(&twl4030_codec_dev->dev,
+ "Invalid resource ID (%u)\n", id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&codec->mutex);
+ if (!codec->resource[id].request_count) {
+ dev_err(&twl4030_codec_dev->dev,
+ "Resource has been disabled already (%u)\n", id);
+ mutex_unlock(&codec->mutex);
+ return -EPERM;
+ }
+ codec->resource[id].request_count--;
+
+ if (!codec->resource[id].request_count)
+ /* Resource can be disabled now */
+ val = twl4030_codec_set_resource(id, 0);
+ else
+ val = twl4030_codec_get_resource(id);
+
+ mutex_unlock(&codec->mutex);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(twl4030_codec_disable_resource);
+
+unsigned int twl4030_codec_get_mclk(void)
+{
+ struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev);
+
+ return codec->audio_mclk;
+}
+EXPORT_SYMBOL_GPL(twl4030_codec_get_mclk);
+
+static int __devinit twl4030_codec_probe(struct platform_device *pdev)
+{
+ struct twl4030_codec *codec;
+ struct twl4030_codec_data *pdata = pdev->dev.platform_data;
+ struct mfd_cell *cell = NULL;
+ int ret, childs = 0;
+ u8 val;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Platform data is missing\n");
+ return -EINVAL;
+ }
+
+ /* Configure APLL_INFREQ and disable APLL if enabled */
+ val = 0;
+ switch (pdata->audio_mclk) {
+ case 19200000:
+ val |= TWL4030_APLL_INFREQ_19200KHZ;
+ break;
+ case 26000000:
+ val |= TWL4030_APLL_INFREQ_26000KHZ;
+ break;
+ case 38400000:
+ val |= TWL4030_APLL_INFREQ_38400KHZ;
+ break;
+ default:
+ dev_err(&pdev->dev, "Invalid audio_mclk\n");
+ return -EINVAL;
+ }
+ twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+ val, TWL4030_REG_APLL_CTL);
+
+ codec = kzalloc(sizeof(struct twl4030_codec), GFP_KERNEL);
+ if (!codec)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, codec);
+
+ twl4030_codec_dev = pdev;
+ mutex_init(&codec->mutex);
+ codec->audio_mclk = pdata->audio_mclk;
+
+ /* Codec power */
+ codec->resource[TWL4030_CODEC_RES_POWER].reg = TWL4030_REG_CODEC_MODE;
+ codec->resource[TWL4030_CODEC_RES_POWER].mask = TWL4030_CODECPDZ;
+
+ /* PLL */
+ codec->resource[TWL4030_CODEC_RES_APLL].reg = TWL4030_REG_APLL_CTL;
+ codec->resource[TWL4030_CODEC_RES_APLL].mask = TWL4030_APLL_EN;
+
+ if (pdata->audio) {
+ cell = &codec->cells[childs];
+ cell->name = "twl4030-codec";
+ cell->platform_data = pdata->audio;
+ cell->pdata_size = sizeof(*pdata->audio);
+ childs++;
+ }
+ if (pdata->vibra) {
+ cell = &codec->cells[childs];
+ cell->name = "twl4030-vibra";
+ cell->platform_data = pdata->vibra;
+ cell->pdata_size = sizeof(*pdata->vibra);
+ childs++;
+ }
+
+ if (childs)
+ ret = mfd_add_devices(&pdev->dev, pdev->id, codec->cells,
+ childs, NULL, 0);
+ else {
+ dev_err(&pdev->dev, "No platform data found for childs\n");
+ ret = -ENODEV;
+ }
+
+ if (!ret)
+ return 0;
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(codec);
+ twl4030_codec_dev = NULL;
+ return ret;
+}
+
+static int __devexit twl4030_codec_remove(struct platform_device *pdev)
+{
+ struct twl4030_codec *codec = platform_get_drvdata(pdev);
+
+ mfd_remove_devices(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(codec);
+ twl4030_codec_dev = NULL;
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:twl4030-audio");
+
+static struct platform_driver twl4030_codec_driver = {
+ .probe = twl4030_codec_probe,
+ .remove = __devexit_p(twl4030_codec_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "twl4030-audio",
+ },
+};
+
+static int __devinit twl4030_codec_init(void)
+{
+ return platform_driver_register(&twl4030_codec_driver);
+}
+module_init(twl4030_codec_init);
+
+static void __devexit twl4030_codec_exit(void)
+{
+ platform_driver_unregister(&twl4030_codec_driver);
+}
+module_exit(twl4030_codec_exit);
+
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
deleted file mode 100644
index 24d436c2fe4..00000000000
--- a/drivers/mfd/twl6040-core.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * MFD driver for TWL6040 audio device
- *
- * Authors: Misael Lopez Cruz <misael.lopez@ti.com>
- * Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
- * Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * Copyright: (C) 2011 Texas Instruments, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/i2c/twl.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl6040.h>
-
-static struct platform_device *twl6040_dev;
-
-int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
-{
- int ret;
- u8 val = 0;
-
- mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret < 0) {
- mutex_unlock(&twl6040->io_mutex);
- return ret;
- }
- mutex_unlock(&twl6040->io_mutex);
-
- return val;
-}
-EXPORT_SYMBOL(twl6040_reg_read);
-
-int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
-{
- int ret;
-
- mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
- mutex_unlock(&twl6040->io_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(twl6040_reg_write);
-
-int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
-{
- int ret;
- u8 val;
-
- mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret)
- goto out;
-
- val |= mask;
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
- mutex_unlock(&twl6040->io_mutex);
- return ret;
-}
-EXPORT_SYMBOL(twl6040_set_bits);
-
-int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
-{
- int ret;
- u8 val;
-
- mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret)
- goto out;
-
- val &= ~mask;
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
- mutex_unlock(&twl6040->io_mutex);
- return ret;
-}
-EXPORT_SYMBOL(twl6040_clear_bits);
-
-/* twl6040 codec manual power-up sequence */
-static int twl6040_power_up(struct twl6040 *twl6040)
-{
- u8 ldoctl, ncpctl, lppllctl;
- int ret;
-
- /* enable high-side LDO, reference system and internal oscillator */
- ldoctl = TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA;
- ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
- if (ret)
- return ret;
- usleep_range(10000, 10500);
-
- /* enable negative charge pump */
- ncpctl = TWL6040_NCPENA;
- ret = twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
- if (ret)
- goto ncp_err;
- usleep_range(1000, 1500);
-
- /* enable low-side LDO */
- ldoctl |= TWL6040_LSLDOENA;
- ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
- if (ret)
- goto lsldo_err;
- usleep_range(1000, 1500);
-
- /* enable low-power PLL */
- lppllctl = TWL6040_LPLLENA;
- ret = twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
- if (ret)
- goto lppll_err;
- usleep_range(5000, 5500);
-
- /* disable internal oscillator */
- ldoctl &= ~TWL6040_OSCENA;
- ret = twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
- if (ret)
- goto osc_err;
-
- return 0;
-
-osc_err:
- lppllctl &= ~TWL6040_LPLLENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-lppll_err:
- ldoctl &= ~TWL6040_LSLDOENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-lsldo_err:
- ncpctl &= ~TWL6040_NCPENA;
- twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
-ncp_err:
- ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
- twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-
- return ret;
-}
-
-/* twl6040 manual power-down sequence */
-static void twl6040_power_down(struct twl6040 *twl6040)
-{
- u8 ncpctl, ldoctl, lppllctl;
-
- ncpctl = twl6040_reg_read(twl6040, TWL6040_REG_NCPCTL);
- ldoctl = twl6040_reg_read(twl6040, TWL6040_REG_LDOCTL);
- lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
-
- /* enable internal oscillator */
- ldoctl |= TWL6040_OSCENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
- usleep_range(1000, 1500);
-
- /* disable low-power PLL */
- lppllctl &= ~TWL6040_LPLLENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-
- /* disable low-side LDO */
- ldoctl &= ~TWL6040_LSLDOENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-
- /* disable negative charge pump */
- ncpctl &= ~TWL6040_NCPENA;
- twl6040_reg_write(twl6040, TWL6040_REG_NCPCTL, ncpctl);
-
- /* disable high-side LDO, reference system and internal oscillator */
- ldoctl &= ~(TWL6040_HSLDOENA | TWL6040_REFENA | TWL6040_OSCENA);
- twl6040_reg_write(twl6040, TWL6040_REG_LDOCTL, ldoctl);
-}
-
-static irqreturn_t twl6040_naudint_handler(int irq, void *data)
-{
- struct twl6040 *twl6040 = data;
- u8 intid, status;
-
- intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
- if (intid & TWL6040_READYINT)
- complete(&twl6040->ready);
-
- if (intid & TWL6040_THINT) {
- status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS);
- if (status & TWL6040_TSHUTDET) {
- dev_warn(&twl6040_dev->dev,
- "Thermal shutdown, powering-off");
- twl6040_power(twl6040, 0);
- } else {
- dev_warn(&twl6040_dev->dev,
- "Leaving thermal shutdown, powering-on");
- twl6040_power(twl6040, 1);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static int twl6040_power_up_completion(struct twl6040 *twl6040,
- int naudint)
-{
- int time_left;
- u8 intid;
-
- time_left = wait_for_completion_timeout(&twl6040->ready,
- msecs_to_jiffies(144));
- if (!time_left) {
- intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
- if (!(intid & TWL6040_READYINT)) {
- dev_err(&twl6040_dev->dev,
- "timeout waiting for READYINT\n");
- return -ETIMEDOUT;
- }
- }
-
- return 0;
-}
-
-int twl6040_power(struct twl6040 *twl6040, int on)
-{
- int audpwron = twl6040->audpwron;
- int naudint = twl6040->irq;
- int ret = 0;
-
- mutex_lock(&twl6040->mutex);
-
- if (on) {
- /* already powered-up */
- if (twl6040->power_count++)
- goto out;
-
- if (gpio_is_valid(audpwron)) {
- /* use AUDPWRON line */
- gpio_set_value(audpwron, 1);
- /* wait for power-up completion */
- ret = twl6040_power_up_completion(twl6040, naudint);
- if (ret) {
- dev_err(&twl6040_dev->dev,
- "automatic power-down failed\n");
- twl6040->power_count = 0;
- goto out;
- }
- } else {
- /* use manual power-up sequence */
- ret = twl6040_power_up(twl6040);
- if (ret) {
- dev_err(&twl6040_dev->dev,
- "manual power-up failed\n");
- twl6040->power_count = 0;
- goto out;
- }
- }
- /* Default PLL configuration after power up */
- twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;
- twl6040->sysclk = 19200000;
- } else {
- /* already powered-down */
- if (!twl6040->power_count) {
- dev_err(&twl6040_dev->dev,
- "device is already powered-off\n");
- ret = -EPERM;
- goto out;
- }
-
- if (--twl6040->power_count)
- goto out;
-
- if (gpio_is_valid(audpwron)) {
- /* use AUDPWRON line */
- gpio_set_value(audpwron, 0);
-
- /* power-down sequence latency */
- usleep_range(500, 700);
- } else {
- /* use manual power-down sequence */
- twl6040_power_down(twl6040);
- }
- twl6040->sysclk = 0;
- }
-
-out:
- mutex_unlock(&twl6040->mutex);
- return ret;
-}
-EXPORT_SYMBOL(twl6040_power);
-
-int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
- unsigned int freq_in, unsigned int freq_out)
-{
- u8 hppllctl, lppllctl;
- int ret = 0;
-
- mutex_lock(&twl6040->mutex);
-
- hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);
- lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL);
-
- switch (pll_id) {
- case TWL6040_SYSCLK_SEL_LPPLL:
- /* low-power PLL divider */
- switch (freq_out) {
- case 17640000:
- lppllctl |= TWL6040_LPLLFIN;
- break;
- case 19200000:
- lppllctl &= ~TWL6040_LPLLFIN;
- break;
- default:
- dev_err(&twl6040_dev->dev,
- "freq_out %d not supported\n", freq_out);
- ret = -EINVAL;
- goto pll_out;
- }
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
-
- switch (freq_in) {
- case 32768:
- lppllctl |= TWL6040_LPLLENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
- lppllctl);
- mdelay(5);
- lppllctl &= ~TWL6040_HPLLSEL;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL,
- lppllctl);
- hppllctl &= ~TWL6040_HPLLENA;
- twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL,
- hppllctl);
- break;
- default:
- dev_err(&twl6040_dev->dev,
- "freq_in %d not supported\n", freq_in);
- ret = -EINVAL;
- goto pll_out;
- }
- break;
- case TWL6040_SYSCLK_SEL_HPPLL:
- /* high-performance PLL can provide only 19.2 MHz */
- if (freq_out != 19200000) {
- dev_err(&twl6040_dev->dev,
- "freq_out %d not supported\n", freq_out);
- ret = -EINVAL;
- goto pll_out;
- }
-
- hppllctl &= ~TWL6040_MCLK_MSK;
-
- switch (freq_in) {
- case 12000000:
- /* PLL enabled, active mode */
- hppllctl |= TWL6040_MCLK_12000KHZ |
- TWL6040_HPLLENA;
- break;
- case 19200000:
- /*
- * PLL disabled
- * (enable PLL if MCLK jitter quality
- * doesn't meet specification)
- */
- hppllctl |= TWL6040_MCLK_19200KHZ;
- break;
- case 26000000:
- /* PLL enabled, active mode */
- hppllctl |= TWL6040_MCLK_26000KHZ |
- TWL6040_HPLLENA;
- break;
- case 38400000:
- /* PLL enabled, active mode */
- hppllctl |= TWL6040_MCLK_38400KHZ |
- TWL6040_HPLLENA;
- break;
- default:
- dev_err(&twl6040_dev->dev,
- "freq_in %d not supported\n", freq_in);
- ret = -EINVAL;
- goto pll_out;
- }
-
- /* enable clock slicer to ensure input waveform is square */
- hppllctl |= TWL6040_HPLLSQRENA;
-
- twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl);
- usleep_range(500, 700);
- lppllctl |= TWL6040_HPLLSEL;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
- lppllctl &= ~TWL6040_LPLLENA;
- twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl);
- break;
- default:
- dev_err(&twl6040_dev->dev, "unknown pll id %d\n", pll_id);
- ret = -EINVAL;
- goto pll_out;
- }
-
- twl6040->sysclk = freq_out;
- twl6040->pll = pll_id;
-
-pll_out:
- mutex_unlock(&twl6040->mutex);
- return ret;
-}
-EXPORT_SYMBOL(twl6040_set_pll);
-
-int twl6040_get_pll(struct twl6040 *twl6040)
-{
- if (twl6040->power_count)
- return twl6040->pll;
- else
- return -ENODEV;
-}
-EXPORT_SYMBOL(twl6040_get_pll);
-
-unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
-{
- return twl6040->sysclk;
-}
-EXPORT_SYMBOL(twl6040_get_sysclk);
-
-static struct resource twl6040_vibra_rsrc[] = {
- {
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource twl6040_codec_rsrc[] = {
- {
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static int __devinit twl6040_probe(struct platform_device *pdev)
-{
- struct twl4030_audio_data *pdata = pdev->dev.platform_data;
- struct twl6040 *twl6040;
- struct mfd_cell *cell = NULL;
- int ret, children = 0;
-
- if (!pdata) {
- dev_err(&pdev->dev, "Platform data is missing\n");
- return -EINVAL;
- }
-
- /* In order to operate correctly we need valid interrupt config */
- if (!pdata->naudint_irq || !pdata->irq_base) {
- dev_err(&pdev->dev, "Invalid IRQ configuration\n");
- return -EINVAL;
- }
-
- twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
- if (!twl6040)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, twl6040);
-
- twl6040_dev = pdev;
- twl6040->dev = &pdev->dev;
- twl6040->audpwron = pdata->audpwron_gpio;
- twl6040->irq = pdata->naudint_irq;
- twl6040->irq_base = pdata->irq_base;
-
- mutex_init(&twl6040->mutex);
- mutex_init(&twl6040->io_mutex);
- init_completion(&twl6040->ready);
-
- twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
-
- if (gpio_is_valid(twl6040->audpwron)) {
- ret = gpio_request(twl6040->audpwron, "audpwron");
- if (ret)
- goto gpio1_err;
-
- ret = gpio_direction_output(twl6040->audpwron, 0);
- if (ret)
- goto gpio2_err;
- }
-
- /* ERRATA: Automatic power-up is not possible in ES1.0 */
- if (twl6040->rev == TWL6040_REV_ES1_0)
- twl6040->audpwron = -EINVAL;
-
- /* codec interrupt */
- ret = twl6040_irq_init(twl6040);
- if (ret)
- goto gpio2_err;
-
- ret = request_threaded_irq(twl6040->irq_base + TWL6040_IRQ_READY,
- NULL, twl6040_naudint_handler, 0,
- "twl6040_irq_ready", twl6040);
- if (ret) {
- dev_err(twl6040->dev, "READY IRQ request failed: %d\n",
- ret);
- goto irq_err;
- }
-
- /* dual-access registers controlled by I2C only */
- twl6040_set_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_I2CSEL);
-
- if (pdata->codec) {
- int irq = twl6040->irq_base + TWL6040_IRQ_PLUG;
-
- cell = &twl6040->cells[children];
- cell->name = "twl6040-codec";
- twl6040_codec_rsrc[0].start = irq;
- twl6040_codec_rsrc[0].end = irq;
- cell->resources = twl6040_codec_rsrc;
- cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
- cell->platform_data = pdata->codec;
- cell->pdata_size = sizeof(*pdata->codec);
- children++;
- }
-
- if (pdata->vibra) {
- int irq = twl6040->irq_base + TWL6040_IRQ_VIB;
-
- cell = &twl6040->cells[children];
- cell->name = "twl6040-vibra";
- twl6040_vibra_rsrc[0].start = irq;
- twl6040_vibra_rsrc[0].end = irq;
- cell->resources = twl6040_vibra_rsrc;
- cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
-
- cell->platform_data = pdata->vibra;
- cell->pdata_size = sizeof(*pdata->vibra);
- children++;
- }
-
- if (children) {
- ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
- children, NULL, 0);
- if (ret)
- goto mfd_err;
- } else {
- dev_err(&pdev->dev, "No platform data found for children\n");
- ret = -ENODEV;
- goto mfd_err;
- }
-
- return 0;
-
-mfd_err:
- free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
-irq_err:
- twl6040_irq_exit(twl6040);
-gpio2_err:
- if (gpio_is_valid(twl6040->audpwron))
- gpio_free(twl6040->audpwron);
-gpio1_err:
- platform_set_drvdata(pdev, NULL);
- kfree(twl6040);
- twl6040_dev = NULL;
- return ret;
-}
-
-static int __devexit twl6040_remove(struct platform_device *pdev)
-{
- struct twl6040 *twl6040 = platform_get_drvdata(pdev);
-
- if (twl6040->power_count)
- twl6040_power(twl6040, 0);
-
- if (gpio_is_valid(twl6040->audpwron))
- gpio_free(twl6040->audpwron);
-
- free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
- twl6040_irq_exit(twl6040);
-
- mfd_remove_devices(&pdev->dev);
- platform_set_drvdata(pdev, NULL);
- kfree(twl6040);
- twl6040_dev = NULL;
-
- return 0;
-}
-
-static struct platform_driver twl6040_driver = {
- .probe = twl6040_probe,
- .remove = __devexit_p(twl6040_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "twl6040",
- },
-};
-
-static int __devinit twl6040_init(void)
-{
- return platform_driver_register(&twl6040_driver);
-}
-module_init(twl6040_init);
-
-static void __devexit twl6040_exit(void)
-{
- platform_driver_unregister(&twl6040_driver);
-}
-
-module_exit(twl6040_exit);
-
-MODULE_DESCRIPTION("TWL6040 MFD");
-MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
-MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:twl6040");
diff --git a/drivers/mfd/twl6040-irq.c b/drivers/mfd/twl6040-irq.c
deleted file mode 100644
index b3f8ddaa28a..00000000000
--- a/drivers/mfd/twl6040-irq.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Interrupt controller support for TWL6040
- *
- * Author: Misael Lopez Cruz <misael.lopez@ti.com>
- *
- * Copyright: (C) 2011 Texas Instruments, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/twl6040.h>
-
-struct twl6040_irq_data {
- int mask;
- int status;
-};
-
-static struct twl6040_irq_data twl6040_irqs[] = {
- {
- .mask = TWL6040_THMSK,
- .status = TWL6040_THINT,
- },
- {
- .mask = TWL6040_PLUGMSK,
- .status = TWL6040_PLUGINT | TWL6040_UNPLUGINT,
- },
- {
- .mask = TWL6040_HOOKMSK,
- .status = TWL6040_HOOKINT,
- },
- {
- .mask = TWL6040_HFMSK,
- .status = TWL6040_HFINT,
- },
- {
- .mask = TWL6040_VIBMSK,
- .status = TWL6040_VIBINT,
- },
- {
- .mask = TWL6040_READYMSK,
- .status = TWL6040_READYINT,
- },
-};
-
-static inline
-struct twl6040_irq_data *irq_to_twl6040_irq(struct twl6040 *twl6040,
- int irq)
-{
- return &twl6040_irqs[irq - twl6040->irq_base];
-}
-
-static void twl6040_irq_lock(struct irq_data *data)
-{
- struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
-
- mutex_lock(&twl6040->irq_mutex);
-}
-
-static void twl6040_irq_sync_unlock(struct irq_data *data)
-{
- struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
-
- /* write back to hardware any change in irq mask */
- if (twl6040->irq_masks_cur != twl6040->irq_masks_cache) {
- twl6040->irq_masks_cache = twl6040->irq_masks_cur;
- twl6040_reg_write(twl6040, TWL6040_REG_INTMR,
- twl6040->irq_masks_cur);
- }
-
- mutex_unlock(&twl6040->irq_mutex);
-}
-
-static void twl6040_irq_enable(struct irq_data *data)
-{
- struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
- struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
- data->irq);
-
- twl6040->irq_masks_cur &= ~irq_data->mask;
-}
-
-static void twl6040_irq_disable(struct irq_data *data)
-{
- struct twl6040 *twl6040 = irq_data_get_irq_chip_data(data);
- struct twl6040_irq_data *irq_data = irq_to_twl6040_irq(twl6040,
- data->irq);
-
- twl6040->irq_masks_cur |= irq_data->mask;
-}
-
-static struct irq_chip twl6040_irq_chip = {
- .name = "twl6040",
- .irq_bus_lock = twl6040_irq_lock,
- .irq_bus_sync_unlock = twl6040_irq_sync_unlock,
- .irq_enable = twl6040_irq_enable,
- .irq_disable = twl6040_irq_disable,
-};
-
-static irqreturn_t twl6040_irq_thread(int irq, void *data)
-{
- struct twl6040 *twl6040 = data;
- u8 intid;
- int i;
-
- intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
- /* apply masking and report (backwards to handle READYINT first) */
- for (i = ARRAY_SIZE(twl6040_irqs) - 1; i >= 0; i--) {
- if (twl6040->irq_masks_cur & twl6040_irqs[i].mask)
- intid &= ~twl6040_irqs[i].status;
- if (intid & twl6040_irqs[i].status)
- handle_nested_irq(twl6040->irq_base + i);
- }
-
- /* ack unmasked irqs */
- twl6040_reg_write(twl6040, TWL6040_REG_INTID, intid);
-
- return IRQ_HANDLED;
-}
-
-int twl6040_irq_init(struct twl6040 *twl6040)
-{
- int cur_irq, ret;
- u8 val;
-
- mutex_init(&twl6040->irq_mutex);
-
- /* mask the individual interrupt sources */
- twl6040->irq_masks_cur = TWL6040_ALLINT_MSK;
- twl6040->irq_masks_cache = TWL6040_ALLINT_MSK;
- twl6040_reg_write(twl6040, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK);
-
- /* Register them with genirq */
- for (cur_irq = twl6040->irq_base;
- cur_irq < twl6040->irq_base + ARRAY_SIZE(twl6040_irqs);
- cur_irq++) {
- irq_set_chip_data(cur_irq, twl6040);
- irq_set_chip_and_handler(cur_irq, &twl6040_irq_chip,
- handle_level_irq);
- irq_set_nested_thread(cur_irq, 1);
-
- /* ARM needs us to explicitly flag the IRQ as valid
- * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
- set_irq_flags(cur_irq, IRQF_VALID);
-#else
- irq_set_noprobe(cur_irq);
-#endif
- }
-
- ret = request_threaded_irq(twl6040->irq, NULL, twl6040_irq_thread,
- IRQF_ONESHOT, "twl6040", twl6040);
- if (ret) {
- dev_err(twl6040->dev, "failed to request IRQ %d: %d\n",
- twl6040->irq, ret);
- return ret;
- }
-
- /* reset interrupts */
- val = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
- /* interrupts cleared on write */
- twl6040_clear_bits(twl6040, TWL6040_REG_ACCCTL, TWL6040_INTCLRMODE);
-
- return 0;
-}
-EXPORT_SYMBOL(twl6040_irq_init);
-
-void twl6040_irq_exit(struct twl6040 *twl6040)
-{
- free_irq(twl6040->irq, twl6040);
-}
-EXPORT_SYMBOL(twl6040_irq_exit);
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 14aa213b00d..cc20e025932 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -715,13 +715,13 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
int burstlen, ret;
/*
- * use burstlen of 64 (16 words) in 4 bit mode (--> reg value 0)
- * use burstlen of 16 (4 words) in 1 bit mode (--> reg value 16)
+ * use burstlen of 64 in 4 bit mode (--> reg value 0)
+ * use burstlen of 16 in 1 bit mode (--> reg value 16)
*/
if (ios->bus_width == MMC_BUS_WIDTH_4)
- burstlen = 16;
+ burstlen = 64;
else
- burstlen = 4;
+ burstlen = 16;
if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
host->burstlen = burstlen;
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 3007662ac61..905960338fb 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -21,9 +21,8 @@
#include <linux/slab.h>
/**
- * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+ * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API
* @np: device node to get GPIO from
- * @propname: property name containing gpio specifier(s)
* @index: index of the GPIO
* @flags: a flags pointer to fill in
*
@@ -31,8 +30,8 @@
* value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO.
*/
-int of_get_named_gpio_flags(struct device_node *np, const char *propname,
- int index, enum of_gpio_flags *flags)
+int of_get_gpio_flags(struct device_node *np, int index,
+ enum of_gpio_flags *flags)
{
int ret;
struct device_node *gpio_np;
@@ -41,7 +40,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
const void *gpio_spec;
const __be32 *gpio_cells;
- ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
+ ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
&gpio_np, &gpio_spec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
@@ -80,7 +79,7 @@ err0:
pr_debug("%s exited with status %d\n", __func__, ret);
return ret;
}
-EXPORT_SYMBOL(of_get_named_gpio_flags);
+EXPORT_SYMBOL(of_get_gpio_flags);
/**
* of_gpio_count - Count GPIOs for a device
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 69ae2fd2240..81af2b3bcc0 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -48,6 +48,9 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
int ret;
+ if (platform_scoop_config->pcmcia_init)
+ platform_scoop_config->pcmcia_init();
+
/* Register interrupts */
if (SCOOP_DEV[skt->nr].cd_irq >= 0) {
struct pcmcia_irqs cd_irq;
diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c
index 57ddb969d88..b829e655457 100644
--- a/drivers/pcmcia/pxa2xx_trizeps4.c
+++ b/drivers/pcmcia/pxa2xx_trizeps4.c
@@ -55,6 +55,10 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
}
skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY);
break;
+
+#ifndef CONFIG_MACH_TRIZEPS_CONXS
+ case 1:
+#endif
default:
break;
}
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 8f41e112346..636144cea93 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -457,6 +457,7 @@ config SERIAL_SAMSUNG_UARTS_4
config SERIAL_SAMSUNG_UARTS
int
depends on ARM && PLAT_SAMSUNG
+ default 2 if ARCH_S3C2400
default 6 if ARCH_S5P6450
default 4 if SERIAL_SAMSUNG_UARTS_4
default 3
@@ -488,6 +489,13 @@ config SERIAL_SAMSUNG_CONSOLE
your boot loader about how to pass options to the kernel at
boot time.)
+config SERIAL_S3C2400
+ tristate "Samsung S3C2410 Serial port support"
+ depends on ARM && SERIAL_SAMSUNG && CPU_S3C2400
+ default y if CPU_S3C2400
+ help
+ Serial port support for the Samsung S3C2400 SoC
+
config SERIAL_S3C2410
tristate "Samsung S3C2410 Serial port support"
depends on SERIAL_SAMSUNG && CPU_S3C2410
@@ -511,6 +519,13 @@ config SERIAL_S3C2440
help
Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC
+config SERIAL_S3C24A0
+ tristate "Samsung S3C24A0 Serial port support"
+ depends on SERIAL_SAMSUNG && CPU_S3C24A0
+ default y if CPU_S3C24A0
+ help
+ Serial port support for the Samsung S3C24A0 SoC
+
config SERIAL_S3C6400
tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 83b4da6a106..cb2628fee4c 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -38,9 +38,11 @@ obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
+obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
+obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
diff --git a/drivers/tty/serial/s3c2400.c b/drivers/tty/serial/s3c2400.c
new file mode 100644
index 00000000000..d13051b3df8
--- /dev/null
+++ b/drivers/tty/serial/s3c2400.c
@@ -0,0 +1,105 @@
+/*
+ * Driver for Samsung SoC onboard UARTs.
+ *
+ * Ben Dooks, Copyright (c) 2003-2005 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-gpio.h>
+
+#include "samsung.h"
+
+static int s3c2400_serial_getsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ clk->divisor = 1;
+ clk->name = "pclk";
+
+ return 0;
+}
+
+static int s3c2400_serial_setsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ return 0;
+}
+
+static int s3c2400_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
+{
+ dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
+ port, port->mapbase, cfg);
+
+ wr_regl(port, S3C2410_UCON, cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ return 0;
+}
+
+static struct s3c24xx_uart_info s3c2400_uart_inf = {
+ .name = "Samsung S3C2400 UART",
+ .type = PORT_S3C2400,
+ .fifosize = 16,
+ .rx_fifomask = S3C2410_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2410_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2410_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2410_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
+ .get_clksrc = s3c2400_serial_getsource,
+ .set_clksrc = s3c2400_serial_setsource,
+ .reset_port = s3c2400_serial_resetport,
+};
+
+static int s3c2400_serial_probe(struct platform_device *dev)
+{
+ return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
+}
+
+static struct platform_driver s3c2400_serial_driver = {
+ .probe = s3c2400_serial_probe,
+ .remove = __devexit_p(s3c24xx_serial_remove),
+ .driver = {
+ .name = "s3c2400-uart",
+ .owner = THIS_MODULE,
+ },
+};
+
+s3c24xx_console_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
+
+static inline int s3c2400_serial_init(void)
+{
+ return s3c24xx_serial_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
+}
+
+static inline void s3c2400_serial_exit(void)
+{
+ platform_driver_unregister(&s3c2400_serial_driver);
+}
+
+module_init(s3c2400_serial_init);
+module_exit(s3c2400_serial_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("Samsung S3C2400 SoC Serial port driver");
+MODULE_ALIAS("platform:s3c2400-uart");
diff --git a/drivers/tty/serial/s3c24a0.c b/drivers/tty/serial/s3c24a0.c
new file mode 100644
index 00000000000..914eff22e49
--- /dev/null
+++ b/drivers/tty/serial/s3c24a0.c
@@ -0,0 +1,117 @@
+/*
+ * Driver for Samsung S3C24A0 SoC onboard UARTs.
+ *
+ * Based on drivers/serial/s3c2410.c
+ *
+ * Author: Sandeep Patil <sandeep.patil@azingo.com>
+ *
+ * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <mach/hardware.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-gpio.h>
+
+#include "samsung.h"
+
+static int s3c24a0_serial_setsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ if (strcmp(clk->name, "uclk") == 0)
+ ucon |= S3C2410_UCON_UCLK;
+ else
+ ucon &= ~S3C2410_UCON_UCLK;
+
+ wr_regl(port, S3C2410_UCON, ucon);
+ return 0;
+}
+
+static int s3c24a0_serial_getsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ clk->divisor = 1;
+ clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
+
+ return 0;
+}
+
+static int s3c24a0_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
+{
+ dbg("s3c24a0_serial_resetport: port=%p (%08lx), cfg=%p\n",
+ port, port->mapbase, cfg);
+
+ wr_regl(port, S3C2410_UCON, cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ return 0;
+}
+
+static struct s3c24xx_uart_info s3c24a0_uart_inf = {
+ .name = "Samsung S3C24A0 UART",
+ .type = PORT_S3C2410,
+ .fifosize = 16,
+ .rx_fifomask = S3C24A0_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C24A0_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C24A0_UFSTAT_RXFULL,
+ .tx_fifofull = S3C24A0_UFSTAT_TXFULL,
+ .tx_fifomask = S3C24A0_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C24A0_UFSTAT_TXSHIFT,
+ .get_clksrc = s3c24a0_serial_getsource,
+ .set_clksrc = s3c24a0_serial_setsource,
+ .reset_port = s3c24a0_serial_resetport,
+};
+
+static int s3c24a0_serial_probe(struct platform_device *dev)
+{
+ return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
+}
+
+static struct platform_driver s3c24a0_serial_driver = {
+ .probe = s3c24a0_serial_probe,
+ .remove = __devexit_p(s3c24xx_serial_remove),
+ .driver = {
+ .name = "s3c24a0-uart",
+ .owner = THIS_MODULE,
+ },
+};
+
+s3c24xx_console_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
+
+static int __init s3c24a0_serial_init(void)
+{
+ return s3c24xx_serial_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
+}
+
+static void __exit s3c24a0_serial_exit(void)
+{
+ platform_driver_unregister(&s3c24a0_serial_driver);
+}
+
+module_init(s3c24a0_serial_init);
+module_exit(s3c24a0_serial_exit);
+
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 6ddb401552c..609a2807317 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -30,13 +30,6 @@ config PANEL_NEC_NL8048HL11_01B
This NEC NL8048HL11-01B panel is TFT LCD
used in the Zoom2/3/3630 sdp boards.
-config PANEL_PICODLP
- tristate "TI PICO DLP mini-projector"
- depends on OMAP2_DSS && I2C
- help
- A mini-projector used in TI's SDP4430 and EVM boards
- For more info please visit http://www.dlp.com/projector/
-
config PANEL_TAAL
tristate "Taal DSI Panel"
depends on OMAP2_DSS_DSI
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index d90f73c8716..0f601ab3abf 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -4,6 +4,5 @@ obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
-obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
deleted file mode 100644
index 8d6190c544f..00000000000
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * picodlp panel driver
- * picodlp_i2c_driver: i2c_client driver
- *
- * Copyright (C) 2009-2011 Texas Instruments
- * Author: Mythri P K <mythripk@ti.com>
- * Mayuresh Janorkar <mayur@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/>.
- */
-
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-picodlp.h>
-
-#include "panel-picodlp.h"
-
-struct picodlp_data {
- struct mutex lock;
- struct i2c_client *picodlp_i2c_client;
-};
-
-static struct i2c_board_info picodlp_i2c_board_info = {
- I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
-};
-
-struct picodlp_i2c_data {
- struct mutex xfer_lock;
-};
-
-static struct i2c_device_id picodlp_i2c_id[] = {
- { "picodlp_i2c_driver", 0 },
-};
-
-struct picodlp_i2c_command {
- u8 reg;
- u32 value;
-};
-
-static struct omap_video_timings pico_ls_timings = {
- .x_res = 864,
- .y_res = 480,
- .hsw = 7,
- .hfp = 11,
- .hbp = 7,
-
- .pixel_clock = 19200,
-
- .vsw = 2,
- .vfp = 3,
- .vbp = 14,
-};
-
-static inline struct picodlp_panel_data
- *get_panel_data(const struct omap_dss_device *dssdev)
-{
- return (struct picodlp_panel_data *) dssdev->data;
-}
-
-static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
-{
- u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
- struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
- struct i2c_msg msg[2];
-
- mutex_lock(&picodlp_i2c_data->xfer_lock);
-
- msg[0].addr = client->addr;
- msg[0].flags = 0;
- msg[0].len = 2;
- msg[0].buf = read_cmd;
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].len = 4;
- msg[1].buf = data;
-
- i2c_transfer(client->adapter, msg, 2);
- mutex_unlock(&picodlp_i2c_data->xfer_lock);
- return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
-}
-
-static int picodlp_i2c_write_block(struct i2c_client *client,
- u8 *data, int len)
-{
- struct i2c_msg msg;
- int i, r, msg_count = 1;
-
- struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
-
- if (len < 1 || len > 32) {
- dev_err(&client->dev,
- "too long syn_write_block len %d\n", len);
- return -EIO;
- }
- mutex_lock(&picodlp_i2c_data->xfer_lock);
-
- msg.addr = client->addr;
- msg.flags = 0;
- msg.len = len;
- msg.buf = data;
- r = i2c_transfer(client->adapter, &msg, msg_count);
- mutex_unlock(&picodlp_i2c_data->xfer_lock);
-
- /*
- * i2c_transfer returns:
- * number of messages sent in case of success
- * a negative error number in case of failure
- */
- if (r != msg_count)
- goto err;
-
- /* In case of success */
- for (i = 0; i < len; i++)
- dev_dbg(&client->dev,
- "addr %x bw 0x%02x[%d]: 0x%02x\n",
- client->addr, data[0] + i, i, data[i]);
-
- return 0;
-err:
- dev_err(&client->dev, "picodlp_i2c_write error\n");
- return r;
-}
-
-static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
-{
- u8 data[5];
- int i;
-
- data[0] = reg;
- for (i = 1; i < 5; i++)
- data[i] = (value >> (32 - (i) * 8)) & 0xFF;
-
- return picodlp_i2c_write_block(client, data, 5);
-}
-
-static int picodlp_i2c_write_array(struct i2c_client *client,
- const struct picodlp_i2c_command commands[],
- int count)
-{
- int i, r = 0;
- for (i = 0; i < count; i++) {
- r = picodlp_i2c_write(client, commands[i].reg,
- commands[i].value);
- if (r)
- return r;
- }
- return r;
-}
-
-static int picodlp_wait_for_dma_done(struct i2c_client *client)
-{
- u8 trial = 100;
-
- do {
- msleep(1);
- if (!trial--)
- return -ETIMEDOUT;
- } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
-
- return 0;
-}
-
-/**
- * picodlp_i2c_init: i2c_initialization routine
- * client: i2c_client for communication
- *
- * return
- * 0 : Success, no error
- * error code : Failure
- */
-static int picodlp_i2c_init(struct i2c_client *client)
-{
- int r;
- static const struct picodlp_i2c_command init_cmd_set1[] = {
- {SOFT_RESET, 1},
- {DMD_PARK_TRIGGER, 1},
- {MISC_REG, 5},
- {SEQ_CONTROL, 0},
- {SEQ_VECTOR, 0x100},
- {DMD_BLOCK_COUNT, 7},
- {DMD_VCC_CONTROL, 0x109},
- {DMD_PARK_PULSE_COUNT, 0xA},
- {DMD_PARK_PULSE_WIDTH, 0xB},
- {DMD_PARK_DELAY, 0x2ED},
- {DMD_SHADOW_ENABLE, 0},
- {FLASH_OPCODE, 0xB},
- {FLASH_DUMMY_BYTES, 1},
- {FLASH_ADDR_BYTES, 3},
- {PBC_CONTROL, 0},
- {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
- {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
- {CMT_SPLASH_LUT_START_ADDR, 0},
- {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
- {PBC_CONTROL, 1},
- };
-
- static const struct picodlp_i2c_command init_cmd_set2[] = {
- {PBC_CONTROL, 0},
- {CMT_SPLASH_LUT_DEST_SELECT, 0},
- {PBC_CONTROL, 0},
- {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
- {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
- {SEQ_RESET_LUT_START_ADDR, 0},
- {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
- {PBC_CONTROL, 1},
- };
-
- static const struct picodlp_i2c_command init_cmd_set3[] = {
- {PBC_CONTROL, 0},
- {SEQ_RESET_LUT_DEST_SELECT, 0},
- {PBC_CONTROL, 0},
- {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
- {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
- {SEQ_RESET_LUT_START_ADDR, 0},
- {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
- {PBC_CONTROL, 1},
- };
-
- static const struct picodlp_i2c_command init_cmd_set4[] = {
- {PBC_CONTROL, 0},
- {SEQ_RESET_LUT_DEST_SELECT, 0},
- {SDC_ENABLE, 1},
- {AGC_CTRL, 7},
- {CCA_C1A, 0x100},
- {CCA_C1B, 0x0},
- {CCA_C1C, 0x0},
- {CCA_C2A, 0x0},
- {CCA_C2B, 0x100},
- {CCA_C2C, 0x0},
- {CCA_C3A, 0x0},
- {CCA_C3B, 0x0},
- {CCA_C3C, 0x100},
- {CCA_C7A, 0x100},
- {CCA_C7B, 0x100},
- {CCA_C7C, 0x100},
- {CCA_ENABLE, 1},
- {CPU_IF_MODE, 1},
- {SHORT_FLIP, 1},
- {CURTAIN_CONTROL, 0},
- {DMD_PARK_TRIGGER, 0},
- {R_DRIVE_CURRENT, 0x298},
- {G_DRIVE_CURRENT, 0x298},
- {B_DRIVE_CURRENT, 0x298},
- {RGB_DRIVER_ENABLE, 7},
- {SEQ_CONTROL, 0},
- {ACTGEN_CONTROL, 0x10},
- {SEQUENCE_MODE, SEQ_LOCK},
- {DATA_FORMAT, RGB888},
- {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
- {INPUT_SOURCE, PARALLEL_RGB},
- {CPU_IF_SYNC_METHOD, 1},
- {SEQ_CONTROL, 1}
- };
-
- r = picodlp_i2c_write_array(client, init_cmd_set1,
- ARRAY_SIZE(init_cmd_set1));
- if (r)
- return r;
-
- r = picodlp_wait_for_dma_done(client);
- if (r)
- return r;
-
- r = picodlp_i2c_write_array(client, init_cmd_set2,
- ARRAY_SIZE(init_cmd_set2));
- if (r)
- return r;
-
- r = picodlp_wait_for_dma_done(client);
- if (r)
- return r;
-
- r = picodlp_i2c_write_array(client, init_cmd_set3,
- ARRAY_SIZE(init_cmd_set3));
- if (r)
- return r;
-
- r = picodlp_wait_for_dma_done(client);
- if (r)
- return r;
-
- r = picodlp_i2c_write_array(client, init_cmd_set4,
- ARRAY_SIZE(init_cmd_set4));
- if (r)
- return r;
-
- return 0;
-}
-
-static int picodlp_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct picodlp_i2c_data *picodlp_i2c_data;
-
- picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
-
- if (!picodlp_i2c_data)
- return -ENOMEM;
-
- mutex_init(&picodlp_i2c_data->xfer_lock);
- i2c_set_clientdata(client, picodlp_i2c_data);
-
- return 0;
-}
-
-static int picodlp_i2c_remove(struct i2c_client *client)
-{
- struct picodlp_i2c_data *picodlp_i2c_data =
- i2c_get_clientdata(client);
- kfree(picodlp_i2c_data);
- return 0;
-}
-
-static struct i2c_driver picodlp_i2c_driver = {
- .driver = {
- .name = "picodlp_i2c_driver",
- },
- .probe = picodlp_i2c_probe,
- .remove = picodlp_i2c_remove,
- .id_table = picodlp_i2c_id,
-};
-
-static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
-{
- int r, trial = 100;
- struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
- struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
-
- if (dssdev->platform_enable) {
- r = dssdev->platform_enable(dssdev);
- if (r)
- return r;
- }
-
- gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
- msleep(1);
- gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
-
- while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
- if (!trial--) {
- dev_err(&dssdev->dev, "emu_done signal not"
- " going high\n");
- return -ETIMEDOUT;
- }
- msleep(5);
- }
- /*
- * As per dpp2600 programming guide,
- * it is required to sleep for 510ms after emu_done signal goes high
- * then only i2c commands can be successfully sent to dpp2600
- */
- msleep(510);
- if (omapdss_dpi_display_enable(dssdev)) {
- dev_err(&dssdev->dev, "failed to enable DPI\n");
- goto err1;
- }
- dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
- r = picodlp_i2c_init(picod->picodlp_i2c_client);
- if (r)
- goto err;
-
- return r;
-err:
- omapdss_dpi_display_disable(dssdev);
-err1:
- if (dssdev->platform_disable)
- dssdev->platform_disable(dssdev);
-
- return r;
-}
-
-static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
-{
- struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
-
- omapdss_dpi_display_disable(dssdev);
-
- gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
- gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
-
- if (dssdev->platform_disable)
- dssdev->platform_disable(dssdev);
-}
-
-static int picodlp_panel_probe(struct omap_dss_device *dssdev)
-{
- struct picodlp_data *picod;
- struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
- struct i2c_adapter *adapter;
- struct i2c_client *picodlp_i2c_client;
- int r = 0, picodlp_adapter_id;
-
- dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF |
- OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS;
- dssdev->panel.acb = 0x0;
- dssdev->panel.timings = pico_ls_timings;
-
- picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
- if (!picod)
- return -ENOMEM;
-
- mutex_init(&picod->lock);
-
- picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
-
- adapter = i2c_get_adapter(picodlp_adapter_id);
- if (!adapter) {
- dev_err(&dssdev->dev, "can't get i2c adapter\n");
- r = -ENODEV;
- goto err;
- }
-
- picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
- if (!picodlp_i2c_client) {
- dev_err(&dssdev->dev, "can't add i2c device::"
- " picodlp_i2c_client is NULL\n");
- r = -ENODEV;
- goto err;
- }
-
- picod->picodlp_i2c_client = picodlp_i2c_client;
-
- dev_set_drvdata(&dssdev->dev, picod);
- return r;
-err:
- kfree(picod);
- return r;
-}
-
-static void picodlp_panel_remove(struct omap_dss_device *dssdev)
-{
- struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
-
- i2c_unregister_device(picod->picodlp_i2c_client);
- dev_set_drvdata(&dssdev->dev, NULL);
- dev_dbg(&dssdev->dev, "removing picodlp panel\n");
-
- kfree(picod);
-}
-
-static int picodlp_panel_enable(struct omap_dss_device *dssdev)
-{
- struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
- int r;
-
- dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
-
- mutex_lock(&picod->lock);
- if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
- mutex_unlock(&picod->lock);
- return -EINVAL;
- }
-
- r = picodlp_panel_power_on(dssdev);
- mutex_unlock(&picod->lock);
-
- return r;
-}
-
-static void picodlp_panel_disable(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)
- picodlp_panel_power_off(dssdev);
-
- dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
- mutex_unlock(&picod->lock);
-
- 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)
-{
- *xres = dssdev->panel.timings.x_res;
- *yres = dssdev->panel.timings.y_res;
-}
-
-static struct omap_dss_driver picodlp_driver = {
- .probe = picodlp_panel_probe,
- .remove = picodlp_panel_remove,
-
- .enable = picodlp_panel_enable,
- .disable = picodlp_panel_disable,
-
- .get_resolution = picodlp_get_resolution,
-
- .suspend = picodlp_panel_suspend,
- .resume = picodlp_panel_resume,
-
- .driver = {
- .name = "picodlp_panel",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init picodlp_init(void)
-{
- int r = 0;
-
- r = i2c_add_driver(&picodlp_i2c_driver);
- if (r) {
- printk(KERN_WARNING "picodlp_i2c_driver" \
- " registration failed\n");
- return r;
- }
-
- r = omap_dss_register_driver(&picodlp_driver);
- if (r)
- i2c_del_driver(&picodlp_i2c_driver);
-
- return r;
-}
-
-static void __exit picodlp_exit(void)
-{
- i2c_del_driver(&picodlp_i2c_driver);
- omap_dss_unregister_driver(&picodlp_driver);
-}
-
-module_init(picodlp_init);
-module_exit(picodlp_exit);
-
-MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
-MODULE_DESCRIPTION("picodlp driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
deleted file mode 100644
index a34b431a726..00000000000
--- a/drivers/video/omap2/displays/panel-picodlp.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Header file required by picodlp panel driver
- *
- * Copyright (C) 2009-2011 Texas Instruments
- * Author: Mythri P K <mythripk@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_DISPLAY_PANEL_PICODLP_H
-#define __OMAP2_DISPLAY_PANEL_PICODLP_H
-
-/* Commands used for configuring picodlp panel */
-
-#define MAIN_STATUS 0x03
-#define PBC_CONTROL 0x08
-#define INPUT_SOURCE 0x0B
-#define INPUT_RESOLUTION 0x0C
-#define DATA_FORMAT 0x0D
-#define IMG_ROTATION 0x0E
-#define LONG_FLIP 0x0F
-#define SHORT_FLIP 0x10
-#define TEST_PAT_SELECT 0x11
-#define R_DRIVE_CURRENT 0x12
-#define G_DRIVE_CURRENT 0x13
-#define B_DRIVE_CURRENT 0x14
-#define READ_REG_SELECT 0x15
-#define RGB_DRIVER_ENABLE 0x16
-
-#define CPU_IF_MODE 0x18
-#define FRAME_RATE 0x19
-#define CPU_IF_SYNC_METHOD 0x1A
-#define CPU_IF_SOF 0x1B
-#define CPU_IF_EOF 0x1C
-#define CPU_IF_SLEEP 0x1D
-
-#define SEQUENCE_MODE 0x1E
-#define SOFT_RESET 0x1F
-#define FRONT_END_RESET 0x21
-#define AUTO_PWR_ENABLE 0x22
-
-#define VSYNC_LINE_DELAY 0x23
-#define CPU_PI_HORIZ_START 0x24
-#define CPU_PI_VERT_START 0x25
-#define CPU_PI_HORIZ_WIDTH 0x26
-#define CPU_PI_VERT_HEIGHT 0x27
-
-#define PIXEL_MASK_CROP 0x28
-#define CROP_FIRST_LINE 0x29
-#define CROP_LAST_LINE 0x2A
-#define CROP_FIRST_PIXEL 0x2B
-#define CROP_LAST_PIXEL 0x2C
-#define DMD_PARK_TRIGGER 0x2D
-
-#define MISC_REG 0x30
-
-/* AGC registers */
-#define AGC_CTRL 0x50
-#define AGC_CLIPPED_PIXS 0x55
-#define AGC_BRIGHT_PIXS 0x56
-#define AGC_BG_PIXS 0x57
-#define AGC_SAFETY_MARGIN 0x17
-
-/* Color Coordinate Adjustment registers */
-#define CCA_ENABLE 0x5E
-#define CCA_C1A 0x5F
-#define CCA_C1B 0x60
-#define CCA_C1C 0x61
-#define CCA_C2A 0x62
-#define CCA_C2B 0x63
-#define CCA_C2C 0x64
-#define CCA_C3A 0x65
-#define CCA_C3B 0x66
-#define CCA_C3C 0x67
-#define CCA_C7A 0x71
-#define CCA_C7B 0x72
-#define CCA_C7C 0x73
-
-/**
- * DLP Pico Processor 2600 comes with flash
- * We can do DMA operations from flash for accessing Look Up Tables
- */
-#define DMA_STATUS 0x100
-#define FLASH_ADDR_BYTES 0x74
-#define FLASH_DUMMY_BYTES 0x75
-#define FLASH_WRITE_BYTES 0x76
-#define FLASH_READ_BYTES 0x77
-#define FLASH_OPCODE 0x78
-#define FLASH_START_ADDR 0x79
-#define FLASH_DUMMY2 0x7A
-#define FLASH_WRITE_DATA 0x7B
-
-#define TEMPORAL_DITH_DISABLE 0x7E
-#define SEQ_CONTROL 0x82
-#define SEQ_VECTOR 0x83
-
-/* DMD is Digital Micromirror Device */
-#define DMD_BLOCK_COUNT 0x84
-#define DMD_VCC_CONTROL 0x86
-#define DMD_PARK_PULSE_COUNT 0x87
-#define DMD_PARK_PULSE_WIDTH 0x88
-#define DMD_PARK_DELAY 0x89
-#define DMD_SHADOW_ENABLE 0x8E
-#define SEQ_STATUS 0x8F
-#define FLASH_CLOCK_CONTROL 0x98
-#define DMD_PARK 0x2D
-
-#define SDRAM_BIST_ENABLE 0x46
-#define DDR_DRIVER_STRENGTH 0x9A
-#define SDC_ENABLE 0x9D
-#define SDC_BUFF_SWAP_DISABLE 0xA3
-#define CURTAIN_CONTROL 0xA6
-#define DDR_BUS_SWAP_ENABLE 0xA7
-#define DMD_TRC_ENABLE 0xA8
-#define DMD_BUS_SWAP_ENABLE 0xA9
-
-#define ACTGEN_ENABLE 0xAE
-#define ACTGEN_CONTROL 0xAF
-#define ACTGEN_HORIZ_BP 0xB0
-#define ACTGEN_VERT_BP 0xB1
-
-/* Look Up Table access */
-#define CMT_SPLASH_LUT_START_ADDR 0xFA
-#define CMT_SPLASH_LUT_DEST_SELECT 0xFB
-#define CMT_SPLASH_LUT_DATA 0xFC
-#define SEQ_RESET_LUT_START_ADDR 0xFD
-#define SEQ_RESET_LUT_DEST_SELECT 0xFE
-#define SEQ_RESET_LUT_DATA 0xFF
-
-/* Input source definitions */
-#define PARALLEL_RGB 0
-#define INT_TEST_PATTERN 1
-#define SPLASH_SCREEN 2
-#define CPU_INTF 3
-#define BT656 4
-
-/* Standard input resolution definitions */
-#define QWVGA_LANDSCAPE 3 /* (427h*240v) */
-#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */
-#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */
-
-/* Standard data format definitions */
-#define RGB565 0
-#define RGB666 1
-#define RGB888 2
-
-/* Test Pattern definitions */
-#define TPG_CHECKERBOARD 0
-#define TPG_BLACK 1
-#define TPG_WHITE 2
-#define TPG_RED 3
-#define TPG_BLUE 4
-#define TPG_GREEN 5
-#define TPG_VLINES_BLACK 6
-#define TPG_HLINES_BLACK 7
-#define TPG_VLINES_ALT 8
-#define TPG_HLINES_ALT 9
-#define TPG_DIAG_LINES 10
-#define TPG_GREYRAMP_VERT 11
-#define TPG_GREYRAMP_HORIZ 12
-#define TPG_ANSI_CHECKERBOARD 13
-
-/* sequence mode definitions */
-#define SEQ_FREE_RUN 0
-#define SEQ_LOCK 1
-
-/* curtain color definitions */
-#define CURTAIN_BLACK 0
-#define CURTAIN_RED 1
-#define CURTAIN_GREEN 2
-#define CURTAIN_BLUE 3
-#define CURTAIN_YELLOW 4
-#define CURTAIN_MAGENTA 5
-#define CURTAIN_CYAN 6
-#define CURTAIN_WHITE 7
-
-/* LUT definitions */
-#define CMT_LUT_NONE 0
-#define CMT_LUT_GREEN 1
-#define CMT_LUT_RED 2
-#define CMT_LUT_BLUE 3
-#define CMT_LUT_ALL 4
-#define SPLASH_LUT 5
-
-#define SEQ_LUT_NONE 0
-#define SEQ_DRC_LUT_0 1
-#define SEQ_DRC_LUT_1 2
-#define SEQ_DRC_LUT_2 3
-#define SEQ_DRC_LUT_3 4
-#define SEQ_SEQ_LUT 5
-#define SEQ_DRC_LUT_ALL 6
-#define WPC_PROGRAM_LUT 7
-
-#define BITSTREAM_START_ADDR 0x00000000
-#define BITSTREAM_SIZE 0x00040000
-
-#define WPC_FW_0_START_ADDR 0x00040000
-#define WPC_FW_0_SIZE 0x00000ce8
-
-#define SEQUENCE_0_START_ADDR 0x00044000
-#define SEQUENCE_0_SIZE 0x00001000
-
-#define SEQUENCE_1_START_ADDR 0x00045000
-#define SEQUENCE_1_SIZE 0x00000d10
-
-#define SEQUENCE_2_START_ADDR 0x00046000
-#define SEQUENCE_2_SIZE 0x00000d10
-
-#define SEQUENCE_3_START_ADDR 0x00047000
-#define SEQUENCE_3_SIZE 0x00000d10
-
-#define SEQUENCE_4_START_ADDR 0x00048000
-#define SEQUENCE_4_SIZE 0x00000d10
-
-#define SEQUENCE_5_START_ADDR 0x00049000
-#define SEQUENCE_5_SIZE 0x00000d10
-
-#define SEQUENCE_6_START_ADDR 0x0004a000
-#define SEQUENCE_6_SIZE 0x00000d10
-
-#define CMT_LUT_0_START_ADDR 0x0004b200
-#define CMT_LUT_0_SIZE 0x00000600
-
-#define CMT_LUT_1_START_ADDR 0x0004b800
-#define CMT_LUT_1_SIZE 0x00000600
-
-#define CMT_LUT_2_START_ADDR 0x0004be00
-#define CMT_LUT_2_SIZE 0x00000600
-
-#define CMT_LUT_3_START_ADDR 0x0004c400
-#define CMT_LUT_3_SIZE 0x00000600
-
-#define CMT_LUT_4_START_ADDR 0x0004ca00
-#define CMT_LUT_4_SIZE 0x00000600
-
-#define CMT_LUT_5_START_ADDR 0x0004d000
-#define CMT_LUT_5_SIZE 0x00000600
-
-#define CMT_LUT_6_START_ADDR 0x0004d600
-#define CMT_LUT_6_SIZE 0x00000600
-
-#define DRC_TABLE_0_START_ADDR 0x0004dc00
-#define DRC_TABLE_0_SIZE 0x00000100
-
-#define SPLASH_0_START_ADDR 0x0004dd00
-#define SPLASH_0_SIZE 0x00032280
-
-#define SEQUENCE_7_START_ADDR 0x00080000
-#define SEQUENCE_7_SIZE 0x00000d10
-
-#define SEQUENCE_8_START_ADDR 0x00081800
-#define SEQUENCE_8_SIZE 0x00000d10
-
-#define SEQUENCE_9_START_ADDR 0x00083000
-#define SEQUENCE_9_SIZE 0x00000d10
-
-#define CMT_LUT_7_START_ADDR 0x0008e000
-#define CMT_LUT_7_SIZE 0x00000600
-
-#define CMT_LUT_8_START_ADDR 0x0008e800
-#define CMT_LUT_8_SIZE 0x00000600
-
-#define CMT_LUT_9_START_ADDR 0x0008f000
-#define CMT_LUT_9_SIZE 0x00000600
-
-#define SPLASH_1_START_ADDR 0x0009a000
-#define SPLASH_1_SIZE 0x00032280
-
-#define SPLASH_2_START_ADDR 0x000cd000
-#define SPLASH_2_SIZE 0x00032280
-
-#define SPLASH_3_START_ADDR 0x00100000
-#define SPLASH_3_SIZE 0x00032280
-
-#define OPT_SPLASH_0_START_ADDR 0x00134000
-#define OPT_SPLASH_0_SIZE 0x000cb100
-
-#endif
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4cb0449d509..fdd5d4ae437 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -504,18 +504,14 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
r = omapdss_dsi_display_enable(dssdev);
- if (r) {
- dev_err(&dssdev->dev, "failed to enable DSI\n");
- goto err1;
- }
+ if (r)
+ goto err;
omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
r = _taal_enable_te(dssdev, true);
- if (r) {
- dev_err(&dssdev->dev, "failed to re-enable TE");
- goto err2;
- }
+ if (r)
+ goto err;
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
@@ -525,15 +521,13 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
return 0;
-err2:
- dev_err(&dssdev->dev, "failed to exit ULPS");
-
+err:
+ dev_err(&dssdev->dev, "exit ULPS failed");
r = taal_panel_reset(dssdev);
- if (!r) {
- enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
- td->ulps_enabled = false;
- }
-err1:
+
+ enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
+ td->ulps_enabled = false;
+
taal_queue_ulps_work(dssdev);
return r;
@@ -1323,11 +1317,8 @@ static void taal_disable(struct omap_dss_device *dssdev)
dsi_bus_lock(dssdev);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
- int r;
-
- r = taal_wake_up(dssdev);
- if (!r)
- taal_power_off(dssdev);
+ taal_wake_up(dssdev);
+ taal_power_off(dssdev);
}
dsi_bus_unlock(dssdev);
@@ -1906,6 +1897,20 @@ err:
mutex_unlock(&td->lock);
}
+static int taal_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+{
+ if (mode != OMAP_DSS_UPDATE_MANUAL)
+ return -EINVAL;
+ return 0;
+}
+
+static enum omap_dss_update_mode taal_get_update_mode(
+ struct omap_dss_device *dssdev)
+{
+ return OMAP_DSS_UPDATE_MANUAL;
+}
+
static struct omap_dss_driver taal_driver = {
.probe = taal_probe,
.remove = __exit_p(taal_remove),
@@ -1915,6 +1920,9 @@ static struct omap_dss_driver taal_driver = {
.suspend = taal_suspend,
.resume = taal_resume,
+ .set_update_mode = taal_set_update_mode,
+ .get_update_mode = taal_get_update_mode,
+
.update = taal_update,
.sync = taal_sync,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 0d12524db14..6b3e2da1141 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -117,6 +117,18 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
Max FCK is 173MHz, so this doesn't work if your PCK
is very high.
+config OMAP2_DSS_SLEEP_BEFORE_RESET
+ bool "Sleep 50ms before DSS reset"
+ default y
+ help
+ For some unknown reason we may get SYNC_LOST errors from the display
+ subsystem at initialization time if we don't sleep before resetting
+ the DSS. See the source (dss.c) for more comments.
+
+ However, 50ms is quite long time to sleep, and with some
+ configurations the SYNC_LOST may never happen, so the sleep can
+ be disabled here.
+
config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
bool "Sleep 20ms after VENC reset"
default y
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index f0bae6d5340..3da426719dd 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -183,11 +183,8 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_dss;
}
- r = dispc_init_platform_driver();
- if (r) {
- DSSERR("Failed to initialize dispc platform driver\n");
- goto err_dispc;
- }
+ /* keep clocks enabled to prevent context saves/restores during init */
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
r = rfbi_init_platform_driver();
if (r) {
@@ -195,6 +192,12 @@ static int omap_dss_probe(struct platform_device *pdev)
goto err_rfbi;
}
+ r = dispc_init_platform_driver();
+ if (r) {
+ DSSERR("Failed to initialize dispc platform driver\n");
+ goto err_dispc;
+ }
+
r = venc_init_platform_driver();
if (r) {
DSSERR("Failed to initialize venc platform driver\n");
@@ -235,6 +238,8 @@ static int omap_dss_probe(struct platform_device *pdev)
pdata->default_device = dssdev;
}
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+
return 0;
err_register:
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index eac768ff2d3..7a9a2e7d968 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -33,8 +33,6 @@
#include <linux/workqueue.h>
#include <linux/hardirq.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
#include <plat/sram.h>
#include <plat/clock.h>
@@ -94,11 +92,7 @@ struct dispc_irq_stats {
static struct {
struct platform_device *pdev;
void __iomem *base;
-
- int ctx_loss_cnt;
-
int irq;
- struct clk *dss_clk;
u32 fifo_size[3];
@@ -108,7 +102,6 @@ static struct {
u32 error_irqs;
struct work_struct error_work;
- bool ctx_valid;
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -141,34 +134,18 @@ static inline u32 dispc_read_reg(const u16 idx)
return __raw_readl(dispc.base + idx);
}
-static int dispc_get_ctx_loss_count(void)
-{
- struct device *dev = &dispc.pdev->dev;
- struct omap_display_platform_data *pdata = dev->platform_data;
- struct omap_dss_board_info *board_data = pdata->board_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;
-}
-
#define SR(reg) \
dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
#define RR(reg) \
dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
-static void dispc_save_context(void)
+void dispc_save_context(void)
{
int i;
+ if (cpu_is_omap24xx())
+ return;
- DSSDBG("dispc_save_context\n");
-
+ SR(SYSCONFIG);
SR(IRQENABLE);
SR(CONTROL);
SR(CONFIG);
@@ -181,8 +158,7 @@ static void dispc_save_context(void)
SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
- SR(GLOBAL_ALPHA);
+ SR(GLOBAL_ALPHA);
SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -212,25 +188,20 @@ static void dispc_save_context(void)
SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
+ SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+ SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+ SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- }
+ SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+ SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+ SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_GFX));
+ SR(OVL_PRELOAD(OMAP_DSS_GFX));
/* VID1 */
SR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -255,10 +226,8 @@ static void dispc_save_context(void)
for (i = 0; i < 5; i++)
SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
- }
+ for (i = 0; i < 8; i++)
+ SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -279,8 +248,7 @@ static void dispc_save_context(void)
if (dss_has_feature(FEAT_ATTR2))
SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+ SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
/* VID2 */
SR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -305,10 +273,8 @@ static void dispc_save_context(void)
for (i = 0; i < 5; i++)
SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
- }
+ for (i = 0; i < 8; i++)
+ SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -329,35 +295,16 @@ static void dispc_save_context(void)
if (dss_has_feature(FEAT_ATTR2))
SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+ SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
if (dss_has_feature(FEAT_CORE_CLK_DIV))
SR(DIVISOR);
-
- dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
- dispc.ctx_valid = true;
-
- DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
}
-static void dispc_restore_context(void)
+void dispc_restore_context(void)
{
- int i, ctx;
-
- DSSDBG("dispc_restore_context\n");
-
- if (!dispc.ctx_valid)
- return;
-
- ctx = dispc_get_ctx_loss_count();
-
- if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
- return;
-
- DSSDBG("ctx_loss_count: saved %d, current %d\n",
- dispc.ctx_loss_cnt, ctx);
-
+ int i;
+ RR(SYSCONFIG);
/*RR(IRQENABLE);*/
/*RR(CONTROL);*/
RR(CONFIG);
@@ -370,8 +317,7 @@ static void dispc_restore_context(void)
RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
- RR(GLOBAL_ALPHA);
+ RR(GLOBAL_ALPHA);
RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -401,25 +347,20 @@ static void dispc_restore_context(void)
RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
+ RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+ RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+ RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- }
+ RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
+ RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+ RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_GFX));
+ RR(OVL_PRELOAD(OMAP_DSS_GFX));
/* VID1 */
RR(OVL_BA0(OMAP_DSS_VIDEO1));
@@ -444,10 +385,8 @@ static void dispc_restore_context(void)
for (i = 0; i < 5; i++)
RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
- }
+ for (i = 0; i < 8; i++)
+ RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -468,8 +407,7 @@ static void dispc_restore_context(void)
if (dss_has_feature(FEAT_ATTR2))
RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
+ RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
/* VID2 */
RR(OVL_BA0(OMAP_DSS_VIDEO2));
@@ -494,10 +432,8 @@ static void dispc_restore_context(void)
for (i = 0; i < 5; i++)
RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (i = 0; i < 8; i++)
- RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
- }
+ for (i = 0; i < 8; i++)
+ RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -518,8 +454,7 @@ static void dispc_restore_context(void)
if (dss_has_feature(FEAT_ATTR2))
RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
+ RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
if (dss_has_feature(FEAT_CORE_CLK_DIV))
RR(DIVISOR);
@@ -536,35 +471,19 @@ static void dispc_restore_context(void)
* the context is fully restored
*/
RR(IRQENABLE);
-
- DSSDBG("context restored\n");
}
#undef SR
#undef RR
-int dispc_runtime_get(void)
-{
- int r;
-
- DSSDBG("dispc_runtime_get\n");
-
- r = pm_runtime_get_sync(&dispc.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-void dispc_runtime_put(void)
+static inline void enable_clocks(bool enable)
{
- int r;
-
- DSSDBG("dispc_runtime_put\n");
-
- r = pm_runtime_put(&dispc.pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
-
bool dispc_go_busy(enum omap_channel channel)
{
int bit;
@@ -586,6 +505,8 @@ void dispc_go(enum omap_channel channel)
int bit;
bool enable_bit, go_bit;
+ enable_clocks(1);
+
if (channel == OMAP_DSS_CHANNEL_LCD ||
channel == OMAP_DSS_CHANNEL_LCD2)
bit = 0; /* LCDENABLE */
@@ -599,7 +520,7 @@ void dispc_go(enum omap_channel channel)
enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
if (!enable_bit)
- return;
+ goto end;
if (channel == OMAP_DSS_CHANNEL_LCD ||
channel == OMAP_DSS_CHANNEL_LCD2)
@@ -614,7 +535,7 @@ void dispc_go(enum omap_channel channel)
if (go_bit) {
DSSERR("GO bit not down for channel %d\n", channel);
- return;
+ goto end;
}
DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
@@ -624,6 +545,8 @@ void dispc_go(enum omap_channel channel)
REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
else
REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
+end:
+ enable_clocks(0);
}
static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
@@ -997,7 +920,7 @@ static void _dispc_set_color_mode(enum omap_plane plane,
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
}
-void dispc_set_channel_out(enum omap_plane plane,
+static void _dispc_set_channel_out(enum omap_plane plane,
enum omap_channel channel)
{
int shift;
@@ -1050,6 +973,8 @@ void dispc_set_burst_size(enum omap_plane plane,
int shift;
u32 val;
+ enable_clocks(1);
+
switch (plane) {
case OMAP_DSS_GFX:
shift = 6;
@@ -1066,6 +991,8 @@ void dispc_set_burst_size(enum omap_plane plane,
val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
val = FLD_MOD(val, burst_size, shift+1, shift);
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
+
+ enable_clocks(0);
}
void dispc_enable_gamma_table(bool enable)
@@ -1102,7 +1029,9 @@ void dispc_enable_replication(enum omap_plane plane, bool enable)
else
bit = 10;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
+ enable_clocks(0);
}
void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
@@ -1110,7 +1039,9 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
u32 val;
BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ enable_clocks(1);
dispc_write_reg(DISPC_SIZE_MGR(channel), val);
+ enable_clocks(0);
}
void dispc_set_digit_size(u16 width, u16 height)
@@ -1118,7 +1049,9 @@ void dispc_set_digit_size(u16 width, u16 height)
u32 val;
BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ enable_clocks(1);
dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
+ enable_clocks(0);
}
static void dispc_read_plane_fifo_sizes(void)
@@ -1127,6 +1060,8 @@ static void dispc_read_plane_fifo_sizes(void)
int plane;
u8 start, end;
+ enable_clocks(1);
+
dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
@@ -1134,6 +1069,8 @@ static void dispc_read_plane_fifo_sizes(void)
start, end);
dispc.fifo_size[plane] = size;
}
+
+ enable_clocks(0);
}
u32 dispc_get_plane_fifo_size(enum omap_plane plane)
@@ -1148,6 +1085,8 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
+ enable_clocks(1);
+
DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
plane,
REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
@@ -1159,12 +1098,18 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
FLD_VAL(high, hi_start, hi_end) |
FLD_VAL(low, lo_start, lo_end));
+
+ enable_clocks(0);
}
void dispc_enable_fifomerge(bool enable)
{
+ enable_clocks(1);
+
DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
+
+ enable_clocks(0);
}
static void _dispc_set_fir(enum omap_plane plane,
@@ -1784,7 +1729,14 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
return dispc_pclk_rate(channel) * vf * hf;
}
-int dispc_setup_plane(enum omap_plane plane,
+void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
+{
+ enable_clocks(1);
+ _dispc_set_channel_out(plane, channel_out);
+ enable_clocks(0);
+}
+
+static int _dispc_setup_plane(enum omap_plane plane,
u32 paddr, u16 screen_width,
u16 pos_x, u16 pos_y,
u16 width, u16 height,
@@ -1792,7 +1744,7 @@ int dispc_setup_plane(enum omap_plane plane,
enum omap_color_mode color_mode,
bool ilace,
enum omap_dss_rotation_type rotation_type,
- u8 rotation, bool mirror,
+ u8 rotation, int mirror,
u8 global_alpha, u8 pre_mult_alpha,
enum omap_channel channel, u32 puv_addr)
{
@@ -1806,14 +1758,6 @@ int dispc_setup_plane(enum omap_plane plane,
u16 frame_height = height;
unsigned int field_offset = 0;
- DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
- "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
- plane, paddr, screen_width, pos_x, pos_y,
- width, height,
- out_width, out_height,
- ilace, color_mode,
- rotation, mirror, channel);
-
if (paddr == 0)
return -EINVAL;
@@ -1959,13 +1903,9 @@ int dispc_setup_plane(enum omap_plane plane,
return 0;
}
-int dispc_enable_plane(enum omap_plane plane, bool enable)
+static void _dispc_enable_plane(enum omap_plane plane, bool enable)
{
- DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
-
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
-
- return 0;
}
static void dispc_disable_isr(void *data, u32 mask)
@@ -1989,6 +1929,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
int r;
u32 irq;
+ enable_clocks(1);
+
/* 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 */
@@ -2022,6 +1964,8 @@ static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
if (r)
DSSERR("failed to unregister FRAMEDONE isr\n");
}
+
+ enable_clocks(0);
}
static void _enable_digit_out(bool enable)
@@ -2034,8 +1978,12 @@ static void dispc_enable_digit_out(bool enable)
struct completion frame_done_completion;
int r;
- if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
+ enable_clocks(1);
+
+ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) {
+ enable_clocks(0);
return;
+ }
if (enable) {
unsigned long flags;
@@ -2087,6 +2035,8 @@ static void dispc_enable_digit_out(bool enable)
_omap_dispc_set_irqs();
spin_unlock_irqrestore(&dispc.irq_lock, flags);
}
+
+ enable_clocks(0);
}
bool dispc_is_channel_enabled(enum omap_channel channel)
@@ -2117,7 +2067,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high)
if (!dss_has_feature(FEAT_LCDENABLEPOL))
return;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
+ enable_clocks(0);
}
void dispc_lcd_enable_signal(bool enable)
@@ -2125,7 +2077,9 @@ void dispc_lcd_enable_signal(bool enable)
if (!dss_has_feature(FEAT_LCDENABLESIGNAL))
return;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
+ enable_clocks(0);
}
void dispc_pck_free_enable(bool enable)
@@ -2133,15 +2087,19 @@ void dispc_pck_free_enable(bool enable)
if (!dss_has_feature(FEAT_PCKFREEENABLE))
return;
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
+ enable_clocks(0);
}
void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
{
+ enable_clocks(1);
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
else
REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
+ enable_clocks(0);
}
@@ -2164,21 +2122,27 @@ void dispc_set_lcd_display_type(enum omap_channel channel,
return;
}
+ enable_clocks(1);
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
else
REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
+ enable_clocks(0);
}
void dispc_set_loadmode(enum omap_dss_load_mode mode)
{
+ enable_clocks(1);
REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
+ enable_clocks(0);
}
void dispc_set_default_color(enum omap_channel channel, u32 color)
{
+ enable_clocks(1);
dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
+ enable_clocks(0);
}
u32 dispc_get_default_color(enum omap_channel channel)
@@ -2189,7 +2153,9 @@ u32 dispc_get_default_color(enum omap_channel channel)
channel != OMAP_DSS_CHANNEL_LCD &&
channel != OMAP_DSS_CHANNEL_LCD2);
+ enable_clocks(1);
l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
+ enable_clocks(0);
return l;
}
@@ -2198,6 +2164,7 @@ void dispc_set_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type type,
u32 trans_key)
{
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2206,12 +2173,14 @@ void dispc_set_trans_key(enum omap_channel ch,
REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
+ enable_clocks(0);
}
void dispc_get_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type *type,
u32 *trans_key)
{
+ enable_clocks(1);
if (type) {
if (ch == OMAP_DSS_CHANNEL_LCD)
*type = REG_GET(DISPC_CONFIG, 11, 11);
@@ -2225,28 +2194,33 @@ void dispc_get_trans_key(enum omap_channel ch,
if (trans_key)
*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
+ enable_clocks(0);
}
void dispc_enable_trans_key(enum omap_channel ch, bool enable)
{
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
else /* OMAP_DSS_CHANNEL_LCD2 */
REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
+ enable_clocks(0);
}
void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
{
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
return;
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
else /* OMAP_DSS_CHANNEL_LCD2 */
REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
+ enable_clocks(0);
}
bool dispc_alpha_blending_enabled(enum omap_channel ch)
{
@@ -2255,6 +2229,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
return false;
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
enabled = REG_GET(DISPC_CONFIG, 18, 18);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2263,6 +2238,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
enabled = REG_GET(DISPC_CONFIG2, 18, 18);
else
BUG();
+ enable_clocks(0);
return enabled;
}
@@ -2272,6 +2248,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
{
bool enabled;
+ enable_clocks(1);
if (ch == OMAP_DSS_CHANNEL_LCD)
enabled = REG_GET(DISPC_CONFIG, 10, 10);
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
@@ -2280,6 +2257,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch)
enabled = REG_GET(DISPC_CONFIG2, 10, 10);
else
BUG();
+ enable_clocks(0);
return enabled;
}
@@ -2307,10 +2285,12 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
return;
}
+ enable_clocks(1);
if (channel == OMAP_DSS_CHANNEL_LCD2)
REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
else
REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
+ enable_clocks(0);
}
void dispc_set_parallel_interface_mode(enum omap_channel channel,
@@ -2342,6 +2322,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
return;
}
+ enable_clocks(1);
+
if (channel == OMAP_DSS_CHANNEL_LCD2) {
l = dispc_read_reg(DISPC_CONTROL2);
l = FLD_MOD(l, stallmode, 11, 11);
@@ -2353,6 +2335,8 @@ void dispc_set_parallel_interface_mode(enum omap_channel channel,
l = FLD_MOD(l, gpout1, 16, 16);
dispc_write_reg(DISPC_CONTROL, l);
}
+
+ enable_clocks(0);
}
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
@@ -2405,8 +2389,10 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
FLD_VAL(vbp, 31, 20);
}
+ enable_clocks(1);
dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
+ enable_clocks(0);
}
/* change name to mode? */
@@ -2449,8 +2435,10 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
BUG_ON(lck_div < 1);
BUG_ON(pck_div < 2);
+ enable_clocks(1);
dispc_write_reg(DISPC_DIVISORo(channel),
FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+ enable_clocks(0);
}
static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
@@ -2469,7 +2457,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_clk_get_rate(DSS_CLK_FCK);
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
dsidev = dsi_get_dsidev_from_id(0);
@@ -2499,7 +2487,7 @@ unsigned long dispc_lclk_rate(enum omap_channel channel)
switch (dss_get_lcd_clk_source(channel)) {
case OMAP_DSS_CLK_SRC_FCK:
- r = clk_get_rate(dispc.dss_clk);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
break;
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
dsidev = dsi_get_dsidev_from_id(0);
@@ -2538,8 +2526,7 @@ void dispc_dump_clocks(struct seq_file *s)
enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
enum omap_dss_clk_source lcd_clk_src;
- if (dispc_runtime_get())
- return;
+ enable_clocks(1);
seq_printf(s, "- DISPC -\n");
@@ -2587,8 +2574,7 @@ void dispc_dump_clocks(struct seq_file *s)
seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
}
-
- dispc_runtime_put();
+ enable_clocks(0);
}
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -2643,8 +2629,7 @@ void dispc_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
- if (dispc_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DISPC_REVISION);
DUMPREG(DISPC_SYSCONFIG);
@@ -2664,8 +2649,7 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_GLOBAL_ALPHA))
- DUMPREG(DISPC_GLOBAL_ALPHA);
+ DUMPREG(DISPC_GLOBAL_ALPHA);
DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
@@ -2696,25 +2680,20 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
- if (dss_has_feature(FEAT_CPR)) {
- DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
- DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
- }
+ DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
+ DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
+ DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
if (dss_has_feature(FEAT_MGR_LCD2)) {
DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
- if (dss_has_feature(FEAT_CPR)) {
- DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
- DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
- }
+ DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
+ DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
+ DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
}
- if (dss_has_feature(FEAT_PRELOAD))
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
+ DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
@@ -2765,16 +2744,14 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
- }
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
@@ -2835,17 +2812,14 @@ void dispc_dump_regs(struct seq_file *s)
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
- DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
- }
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
+ DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
@@ -2884,12 +2858,10 @@ void dispc_dump_regs(struct seq_file *s)
if (dss_has_feature(FEAT_ATTR2))
DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
- if (dss_has_feature(FEAT_PRELOAD)) {
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
- DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
- }
+ DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
+ DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
- dispc_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -2910,7 +2882,9 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
l |= FLD_VAL(acbi, 11, 8);
l |= FLD_VAL(acb, 7, 0);
+ enable_clocks(1);
dispc_write_reg(DISPC_POL_FREQ(channel), l);
+ enable_clocks(0);
}
void dispc_set_pol_freq(enum omap_channel channel,
@@ -3031,11 +3005,15 @@ static void _omap_dispc_set_irqs(void)
mask |= isr_data->mask;
}
+ enable_clocks(1);
+
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);
+
+ enable_clocks(0);
}
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
@@ -3544,6 +3522,13 @@ static void _omap_dispc_initial_config(void)
{
u32 l;
+ l = dispc_read_reg(DISPC_SYSCONFIG);
+ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
+ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */
+ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
+ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */
+ dispc_write_reg(DISPC_SYSCONFIG, l);
+
/* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
l = dispc_read_reg(DISPC_DIVISOR);
@@ -3569,25 +3554,67 @@ static void _omap_dispc_initial_config(void)
dispc_read_plane_fifo_sizes();
}
+int dispc_enable_plane(enum omap_plane plane, bool enable)
+{
+ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
+
+ enable_clocks(1);
+ _dispc_enable_plane(plane, enable);
+ enable_clocks(0);
+
+ return 0;
+}
+
+int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror, u8 global_alpha,
+ u8 pre_mult_alpha, enum omap_channel channel,
+ u32 puv_addr)
+{
+ int r = 0;
+
+ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d, %d, %dx%d -> "
+ "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
+ plane, paddr, screen_width, pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ ilace, color_mode,
+ rotation, mirror, channel);
+
+ enable_clocks(1);
+
+ r = _dispc_setup_plane(plane,
+ paddr, screen_width,
+ pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ color_mode, ilace,
+ rotation_type,
+ rotation, mirror,
+ global_alpha,
+ pre_mult_alpha,
+ channel, puv_addr);
+
+ enable_clocks(0);
+
+ return r;
+}
+
/* DISPC HW IP initialisation */
static int omap_dispchw_probe(struct platform_device *pdev)
{
u32 rev;
int r = 0;
struct resource *dispc_mem;
- struct clk *clk;
dispc.pdev = pdev;
- clk = clk_get(&pdev->dev, "dss_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get dss_clk\n");
- r = PTR_ERR(clk);
- goto err_get_clk;
- }
-
- dispc.dss_clk = clk;
-
spin_lock_init(&dispc.irq_lock);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -3601,103 +3628,62 @@ static int omap_dispchw_probe(struct platform_device *pdev)
if (!dispc_mem) {
DSSERR("can't get IORESOURCE_MEM DISPC\n");
r = -EINVAL;
- goto err_ioremap;
+ goto fail0;
}
dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
if (!dispc.base) {
DSSERR("can't ioremap DISPC\n");
r = -ENOMEM;
- goto err_ioremap;
+ goto fail0;
}
dispc.irq = platform_get_irq(dispc.pdev, 0);
if (dispc.irq < 0) {
DSSERR("platform_get_irq failed\n");
r = -ENODEV;
- goto err_irq;
+ goto fail1;
}
r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
"OMAP DISPC", dispc.pdev);
if (r < 0) {
DSSERR("request_irq failed\n");
- goto err_irq;
+ goto fail1;
}
- pm_runtime_enable(&pdev->dev);
-
- r = dispc_runtime_get();
- if (r)
- goto err_runtime_get;
+ enable_clocks(1);
_omap_dispc_initial_config();
_omap_dispc_initialize_irq();
+ dispc_save_context();
+
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));
- dispc_runtime_put();
+ enable_clocks(0);
return 0;
-
-err_runtime_get:
- pm_runtime_disable(&pdev->dev);
- free_irq(dispc.irq, dispc.pdev);
-err_irq:
+fail1:
iounmap(dispc.base);
-err_ioremap:
- clk_put(dispc.dss_clk);
-err_get_clk:
+fail0:
return r;
}
static int omap_dispchw_remove(struct platform_device *pdev)
{
- pm_runtime_disable(&pdev->dev);
-
- clk_put(dispc.dss_clk);
-
free_irq(dispc.irq, dispc.pdev);
iounmap(dispc.base);
return 0;
}
-static int dispc_runtime_suspend(struct device *dev)
-{
- dispc_save_context();
- clk_disable(dispc.dss_clk);
- dss_runtime_put();
-
- return 0;
-}
-
-static int dispc_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- return r;
-
- clk_enable(dispc.dss_clk);
- dispc_restore_context();
-
- return 0;
-}
-
-static const struct dev_pm_ops dispc_pm_ops = {
- .runtime_suspend = dispc_runtime_suspend,
- .runtime_resume = dispc_runtime_resume,
-};
-
static struct platform_driver omap_dispchw_driver = {
.probe = omap_dispchw_probe,
.remove = omap_dispchw_remove,
.driver = {
.name = "omapdss_dispc",
.owner = THIS_MODULE,
- .pm = &dispc_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index a0bbdf6684b..c2dfc8c5005 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -65,6 +65,48 @@ static ssize_t display_enabled_store(struct device *dev,
return size;
}
+static ssize_t display_upd_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
+ if (dssdev->driver->get_update_mode)
+ mode = dssdev->driver->get_update_mode(dssdev);
+ return snprintf(buf, PAGE_SIZE, "%d\n", mode);
+}
+
+static ssize_t display_upd_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ int val, r;
+ enum omap_dss_update_mode mode;
+
+ if (!dssdev->driver->set_update_mode)
+ return -EINVAL;
+
+ r = kstrtoint(buf, 0, &val);
+ if (r)
+ return r;
+
+ switch (val) {
+ case OMAP_DSS_UPDATE_DISABLED:
+ case OMAP_DSS_UPDATE_AUTO:
+ case OMAP_DSS_UPDATE_MANUAL:
+ mode = (enum omap_dss_update_mode)val;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ r = dssdev->driver->set_update_mode(dssdev, mode);
+ if (r)
+ return r;
+
+ return size;
+}
+
static ssize_t display_tear_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -252,6 +294,8 @@ static ssize_t display_wss_store(struct device *dev,
static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR,
+ display_upd_mode_show, display_upd_mode_store);
static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
display_tear_show, display_tear_store);
static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
@@ -265,6 +309,7 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
static struct device_attribute *display_sysfs_attrs[] = {
&dev_attr_enabled,
+ &dev_attr_update_mode,
&dev_attr_tear_elim,
&dev_attr_timings,
&dev_attr_rotate,
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index f053b180ecd..ff6bd30132d 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -23,6 +23,7 @@
#define DSS_SUBSYS_NAME "DPI"
#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
@@ -129,6 +130,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
bool is_tft;
int r = 0;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+
dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
@@ -141,7 +144,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
if (r)
- return r;
+ goto err0;
pck = fck / lck_div / pck_div / 1000;
@@ -155,10 +158,12 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
dispc_set_lcd_timings(dssdev->manager->id, t);
- return 0;
+err0:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
+ return r;
}
-static void dpi_basic_init(struct omap_dss_device *dssdev)
+static int dpi_basic_init(struct omap_dss_device *dssdev)
{
bool is_tft;
@@ -170,6 +175,8 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)
OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
dispc_set_tft_data_lines(dssdev->manager->id,
dssdev->phy.dpi.data_lines);
+
+ return 0;
}
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
@@ -179,38 +186,31 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
- goto err_start_dev;
+ goto err0;
}
if (cpu_is_omap34xx()) {
r = regulator_enable(dpi.vdds_dsi_reg);
if (r)
- goto err_reg_enable;
+ goto err1;
}
- r = dss_runtime_get();
- if (r)
- goto err_get_dss;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
- r = dispc_runtime_get();
+ r = dpi_basic_init(dssdev);
if (r)
- goto err_get_dispc;
-
- dpi_basic_init(dssdev);
+ goto err2;
if (dpi_use_dsi_pll(dssdev)) {
- r = dsi_runtime_get(dpi.dsidev);
- if (r)
- goto err_get_dsi;
-
+ dss_clk_enable(DSS_CLK_SYSCK);
r = dsi_pll_init(dpi.dsidev, 0, 1);
if (r)
- goto err_dsi_pll_init;
+ goto err3;
}
r = dpi_set_mode(dssdev);
if (r)
- goto err_set_mode;
+ goto err4;
mdelay(2);
@@ -218,22 +218,19 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
return 0;
-err_set_mode:
+err4:
if (dpi_use_dsi_pll(dssdev))
dsi_pll_uninit(dpi.dsidev, true);
-err_dsi_pll_init:
+err3:
if (dpi_use_dsi_pll(dssdev))
- dsi_runtime_put(dpi.dsidev);
-err_get_dsi:
- dispc_runtime_put();
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
+ dss_clk_disable(DSS_CLK_SYSCK);
+err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
-err_reg_enable:
+err1:
omap_dss_stop_device(dssdev);
-err_start_dev:
+err0:
return r;
}
EXPORT_SYMBOL(omapdss_dpi_display_enable);
@@ -245,11 +242,10 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
if (dpi_use_dsi_pll(dssdev)) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_pll_uninit(dpi.dsidev, true);
- dsi_runtime_put(dpi.dsidev);
+ dss_clk_disable(DSS_CLK_SYSCK);
}
- dispc_runtime_put();
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
regulator_disable(dpi.vdds_dsi_reg);
@@ -261,26 +257,11 @@ EXPORT_SYMBOL(omapdss_dpi_display_disable);
void dpi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
- int r;
-
DSSDBG("dpi_set_timings\n");
dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
- r = dss_runtime_get();
- if (r)
- return;
-
- r = dispc_runtime_get();
- if (r) {
- dss_runtime_put();
- return;
- }
-
dpi_set_mode(dssdev);
dispc_go(dssdev->manager->id);
-
- dispc_runtime_put();
- dss_runtime_put();
}
}
EXPORT_SYMBOL(dpi_set_timings);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b6a57bb7a61..345757cfcbe 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -36,7 +36,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/clock.h>
@@ -268,12 +267,8 @@ struct dsi_isr_tables {
struct dsi_data {
struct platform_device *pdev;
void __iomem *base;
-
int irq;
- struct clk *dss_clk;
- struct clk *sys_clk;
-
void (*dsi_mux_pads)(bool enable);
struct dsi_clock_info current_cinfo;
@@ -394,6 +389,15 @@ static inline u32 dsi_read_reg(struct platform_device *dsidev,
return __raw_readl(dsi->base + idx.idx);
}
+
+void dsi_save_context(void)
+{
+}
+
+void dsi_restore_context(void)
+{
+}
+
void dsi_bus_lock(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -489,18 +493,9 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
total_bytes * 1000 / total_us);
}
#else
-static inline void dsi_perf_mark_setup(struct platform_device *dsidev)
-{
-}
-
-static inline void dsi_perf_mark_start(struct platform_device *dsidev)
-{
-}
-
-static inline void dsi_perf_show(struct platform_device *dsidev,
- const char *name)
-{
-}
+#define dsi_perf_mark_setup(x)
+#define dsi_perf_mark_start(x)
+#define dsi_perf_show(x, y)
#endif
static void print_irq_status(u32 status)
@@ -1044,27 +1039,13 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
return e;
}
-int dsi_runtime_get(struct platform_device *dsidev)
+/* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */
+static inline void enable_clocks(bool enable)
{
- int r;
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
- DSSDBG("dsi_runtime_get\n");
-
- r = pm_runtime_get_sync(&dsi->pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-void dsi_runtime_put(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- int r;
-
- DSSDBG("dsi_runtime_put\n");
-
- r = pm_runtime_put(&dsi->pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
/* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1074,9 +1055,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
if (enable)
- clk_enable(dsi->sys_clk);
+ dss_clk_enable(DSS_CLK_SYSCK);
else
- clk_disable(dsi->sys_clk);
+ dss_clk_disable(DSS_CLK_SYSCK);
if (enable && dsi->pll_locked) {
if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1169,11 +1150,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
{
unsigned long r;
int dsi_module = dsi_get_dsidev_id(dsidev);
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
/* DSI FCLK source is DSS_CLK_FCK */
- r = clk_get_rate(dsi->dss_clk);
+ r = dss_clk_get_rate(DSS_CLK_FCK);
} else {
/* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */
r = dsi_get_pll_hsdiv_dsi_rate(dsidev);
@@ -1282,7 +1262,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
return -EINVAL;
if (cinfo->use_sys_clk) {
- cinfo->clkin = clk_get_rate(dsi->sys_clk);
+ cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK);
/* XXX it is unclear if highfreq should be used
* with DSS_SYS_CLK source also */
cinfo->highfreq = 0;
@@ -1331,7 +1311,7 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
int match = 0;
unsigned long dss_sys_clk, max_dss_fck;
- dss_sys_clk = clk_get_rate(dsi->sys_clk);
+ dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK);
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
@@ -1621,6 +1601,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
dsi->vdds_dsi_reg = vdds_dsi;
}
+ enable_clocks(1);
dsi_enable_pll_clock(dsidev, 1);
/*
* Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
@@ -1672,6 +1653,7 @@ err1:
}
err0:
dsi_disable_scp_clk(dsidev);
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
return r;
}
@@ -1689,6 +1671,7 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
}
dsi_disable_scp_clk(dsidev);
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
DSSDBG("PLL uninit done\n");
@@ -1705,8 +1688,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
dispc_clk_src = dss_get_dispc_clk_source();
dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
- if (dsi_runtime_get(dsidev))
- return;
+ enable_clocks(1);
seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
@@ -1749,7 +1731,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk);
- dsi_runtime_put(dsidev);
+ enable_clocks(0);
}
void dsi_dump_clocks(struct seq_file *s)
@@ -1891,8 +1873,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(dsidev, r))
- if (dsi_runtime_get(dsidev))
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
dsi_enable_scp_clk(dsidev);
DUMPREG(DSI_REVISION);
@@ -1966,7 +1947,7 @@ static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
DUMPREG(DSI_PLL_CONFIGURATION2);
dsi_disable_scp_clk(dsidev);
- dsi_runtime_put(dsidev);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -2482,6 +2463,28 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
dsi->dsi_mux_pads(false);
}
+static int _dsi_wait_reset(struct platform_device *dsidev)
+{
+ int t = 0;
+
+ while (REG_GET(dsidev, DSI_SYSSTATUS, 0, 0) == 0) {
+ if (++t > 5) {
+ DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int _dsi_reset(struct platform_device *dsidev)
+{
+ /* Soft reset */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 1, 1);
+ return _dsi_wait_reset(dsidev);
+}
+
static void dsi_config_tx_fifo(struct platform_device *dsidev,
enum fifo_size size1, enum fifo_size size2,
enum fifo_size size3, enum fifo_size size4)
@@ -3383,10 +3386,6 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion,
DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
- /* Reset LANEx_ULPS_SIG2 */
- REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
- 7, 5);
-
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
dsi_if_enable(dsidev, false);
@@ -4199,6 +4198,22 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
dsi_pll_uninit(dsidev, disconnect_lanes);
}
+static int dsi_core_init(struct platform_device *dsidev)
+{
+ /* Autoidle */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 0, 0);
+
+ /* ENWAKEUP */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 1, 2, 2);
+
+ /* SIDLEMODE smart-idle */
+ REG_FLD_MOD(dsidev, DSI_SYSCONFIG, 2, 4, 3);
+
+ _dsi_initialize_irq(dsidev);
+
+ return 0;
+}
+
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -4214,37 +4229,37 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
- goto err_start_dev;
+ goto err0;
}
- r = dsi_runtime_get(dsidev);
- if (r)
- goto err_get_dsi;
-
+ enable_clocks(1);
dsi_enable_pll_clock(dsidev, 1);
- _dsi_initialize_irq(dsidev);
+ r = _dsi_reset(dsidev);
+ if (r)
+ goto err1;
+
+ dsi_core_init(dsidev);
r = dsi_display_init_dispc(dssdev);
if (r)
- goto err_init_dispc;
+ goto err1;
r = dsi_display_init_dsi(dssdev);
if (r)
- goto err_init_dsi;
+ goto err2;
mutex_unlock(&dsi->lock);
return 0;
-err_init_dsi:
+err2:
dsi_display_uninit_dispc(dssdev);
-err_init_dispc:
+err1:
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
- dsi_runtime_put(dsidev);
-err_get_dsi:
omap_dss_stop_device(dssdev);
-err_start_dev:
+err0:
mutex_unlock(&dsi->lock);
DSSDBG("dsi_display_enable FAILED\n");
return r;
@@ -4267,7 +4282,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps);
- dsi_runtime_put(dsidev);
+ enable_clocks(0);
dsi_enable_pll_clock(dsidev, 0);
omap_dss_stop_device(dssdev);
@@ -4422,44 +4437,7 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
}
-static int dsi_get_clocks(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- struct clk *clk;
-
- clk = clk_get(&dsidev->dev, "dss_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get dss_clk\n");
- return PTR_ERR(clk);
- }
-
- dsi->dss_clk = clk;
-
- clk = clk_get(&dsidev->dev, "sys_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get sys_clk\n");
- clk_put(dsi->dss_clk);
- dsi->dss_clk = NULL;
- return PTR_ERR(clk);
- }
-
- dsi->sys_clk = clk;
-
- return 0;
-}
-
-static void dsi_put_clocks(struct platform_device *dsidev)
-{
- struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
-
- if (dsi->dss_clk)
- clk_put(dsi->dss_clk);
- if (dsi->sys_clk)
- clk_put(dsi->sys_clk);
-}
-
-/* DSI1 HW IP initialisation */
-static int omap_dsi1hw_probe(struct platform_device *dsidev)
+static int dsi_init(struct platform_device *dsidev)
{
struct omap_display_platform_data *dss_plat_data;
struct omap_dss_board_info *board_info;
@@ -4471,7 +4449,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
if (!dsi) {
r = -ENOMEM;
- goto err_alloc;
+ goto err0;
}
dsi->pdev = dsidev;
@@ -4494,12 +4472,6 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
mutex_init(&dsi->lock);
sema_init(&dsi->bus_lock, 1);
- r = dsi_get_clocks(dsidev);
- if (r)
- goto err_get_clk;
-
- pm_runtime_enable(&dsidev->dev);
-
INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
dsi_framedone_timeout_work_callback);
@@ -4512,26 +4484,26 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
if (!dsi_mem) {
DSSERR("can't get IORESOURCE_MEM DSI\n");
r = -EINVAL;
- goto err_ioremap;
+ goto err1;
}
dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
if (!dsi->base) {
DSSERR("can't ioremap DSI\n");
r = -ENOMEM;
- goto err_ioremap;
+ goto err1;
}
dsi->irq = platform_get_irq(dsi->pdev, 0);
if (dsi->irq < 0) {
DSSERR("platform_get_irq failed\n");
r = -ENODEV;
- goto err_get_irq;
+ goto err2;
}
r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
dev_name(&dsidev->dev), dsi->pdev);
if (r < 0) {
DSSERR("request_irq failed\n");
- goto err_get_irq;
+ goto err2;
}
/* DSI VCs initialization */
@@ -4543,9 +4515,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dsi_calc_clock_param_ranges(dsidev);
- r = dsi_runtime_get(dsidev);
- if (r)
- goto err_get_dsi;
+ enable_clocks(1);
rev = dsi_read_reg(dsidev, DSI_REVISION);
dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
@@ -4553,32 +4523,21 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev)
dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
- dsi_runtime_put(dsidev);
+ enable_clocks(0);
return 0;
-
-err_get_dsi:
- free_irq(dsi->irq, dsi->pdev);
-err_get_irq:
+err2:
iounmap(dsi->base);
-err_ioremap:
- pm_runtime_disable(&dsidev->dev);
-err_get_clk:
+err1:
kfree(dsi);
-err_alloc:
+err0:
return r;
}
-static int omap_dsi1hw_remove(struct platform_device *dsidev)
+static void dsi_exit(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
- WARN_ON(dsi->scp_clk_refcount > 0);
-
- pm_runtime_disable(&dsidev->dev);
-
- dsi_put_clocks(dsidev);
-
if (dsi->vdds_dsi_reg != NULL) {
if (dsi->vdds_dsi_enabled) {
regulator_disable(dsi->vdds_dsi_reg);
@@ -4594,56 +4553,38 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev)
kfree(dsi);
- return 0;
+ DSSDBG("omap_dsi_exit\n");
}
-static int dsi_runtime_suspend(struct device *dev)
+/* DSI1 HW IP initialisation */
+static int omap_dsi1hw_probe(struct platform_device *dsidev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
-
- clk_disable(dsi->dss_clk);
-
- dispc_runtime_put();
- dss_runtime_put();
+ int r;
- return 0;
+ r = dsi_init(dsidev);
+ if (r) {
+ DSSERR("Failed to initialize DSI\n");
+ goto err_dsi;
+ }
+err_dsi:
+ return r;
}
-static int dsi_runtime_resume(struct device *dev)
+static int omap_dsi1hw_remove(struct platform_device *dsidev)
{
- struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
- int r;
-
- r = dss_runtime_get();
- if (r)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r)
- goto err_get_dispc;
-
- clk_enable(dsi->dss_clk);
+ struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ dsi_exit(dsidev);
+ WARN_ON(dsi->scp_clk_refcount > 0);
return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
}
-static const struct dev_pm_ops dsi_pm_ops = {
- .runtime_suspend = dsi_runtime_suspend,
- .runtime_resume = dsi_runtime_resume,
-};
-
static struct platform_driver omap_dsi1hw_driver = {
.probe = omap_dsi1hw_probe,
.remove = omap_dsi1hw_remove,
.driver = {
.name = "omapdss_dsi1",
.owner = THIS_MODULE,
- .pm = &dsi_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 5c6499a4d6a..d9489d5c4f0 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -28,8 +28,6 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/clock.h>
@@ -61,9 +59,15 @@ struct dss_reg {
static struct {
struct platform_device *pdev;
void __iomem *base;
+ int ctx_id;
struct clk *dpll4_m4_ck;
- struct clk *dss_clk;
+ struct clk *dss_ick;
+ struct clk *dss_fck;
+ struct clk *dss_sys_clk;
+ struct clk *dss_tv_fck;
+ struct clk *dss_video_fck;
+ unsigned num_clks_enabled;
unsigned long cache_req_pck;
unsigned long cache_prate;
@@ -74,7 +78,6 @@ static struct {
enum omap_dss_clk_source dispc_clk_source;
enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
- bool ctx_valid;
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
} dss;
@@ -84,6 +87,13 @@ static const char * const dss_generic_clk_source_names[] = {
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
};
+static void dss_clk_enable_all_no_ctx(void);
+static void dss_clk_disable_all_no_ctx(void);
+static void dss_clk_enable_no_ctx(enum dss_clock clks);
+static void dss_clk_disable_no_ctx(enum dss_clock clks);
+
+static int _omap_dss_wait_reset(void);
+
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
{
__raw_writel(val, dss.base + idx.idx);
@@ -99,10 +109,12 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
#define RR(reg) \
dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
-static void dss_save_context(void)
+void dss_save_context(void)
{
- DSSDBG("dss_save_context\n");
+ if (cpu_is_omap24xx())
+ return;
+ SR(SYSCONFIG);
SR(CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -110,19 +122,14 @@ static void dss_save_context(void)
SR(SDI_CONTROL);
SR(PLL_CONTROL);
}
-
- dss.ctx_valid = true;
-
- DSSDBG("context saved\n");
}
-static void dss_restore_context(void)
+void dss_restore_context(void)
{
- DSSDBG("dss_restore_context\n");
-
- if (!dss.ctx_valid)
- return;
+ if (_omap_dss_wait_reset())
+ DSSERR("DSS not coming out of reset after sleep\n");
+ RR(SYSCONFIG);
RR(CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -130,8 +137,6 @@ static void dss_restore_context(void)
RR(SDI_CONTROL);
RR(PLL_CONTROL);
}
-
- DSSDBG("context restored\n");
}
#undef SR
@@ -229,7 +234,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
return dss_generic_clk_source_names[clk_src];
}
-
void dss_dump_clocks(struct seq_file *s)
{
unsigned long dpll4_ck_rate;
@@ -237,14 +241,13 @@ void dss_dump_clocks(struct seq_file *s)
const char *fclk_name, *fclk_real_name;
unsigned long fclk_rate;
- if (dss_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
seq_printf(s, "- DSS -\n");
fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
- fclk_rate = clk_get_rate(dss.dss_clk);
+ fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
if (dss.dpll4_m4_ck) {
dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -270,15 +273,14 @@ void dss_dump_clocks(struct seq_file *s)
fclk_rate);
}
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
void dss_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
- if (dss_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(DSS_REVISION);
DUMPREG(DSS_SYSCONFIG);
@@ -292,7 +294,7 @@ void dss_dump_regs(struct seq_file *s)
DUMPREG(DSS_SDI_STATUS);
}
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -435,7 +437,7 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
} else {
if (cinfo->fck_div != 0)
return -EINVAL;
- cinfo->fck = clk_get_rate(dss.dss_clk);
+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
}
return 0;
@@ -465,7 +467,7 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
int dss_get_clock_div(struct dss_clock_info *cinfo)
{
- cinfo->fck = clk_get_rate(dss.dss_clk);
+ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK);
if (dss.dpll4_m4_ck) {
unsigned long prate;
@@ -510,7 +512,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
- fck = clk_get_rate(dss.dss_clk);
+ fck = dss_clk_get_rate(DSS_CLK_FCK);
if (req_pck == dss.cache_req_pck &&
((cpu_is_omap34xx() && prate == dss.cache_prate) ||
dss.cache_dss_cinfo.fck == fck)) {
@@ -537,7 +539,7 @@ retry:
if (dss.dpll4_m4_ck == NULL) {
struct dispc_clock_info cur_dispc;
/* XXX can we change the clock on omap2? */
- fck = clk_get_rate(dss.dss_clk);
+ fck = dss_clk_get_rate(DSS_CLK_FCK);
fck_div = 1;
dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
@@ -614,6 +616,28 @@ found:
return 0;
}
+static int _omap_dss_wait_reset(void)
+{
+ int t = 0;
+
+ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
+ if (++t > 1000) {
+ DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int _omap_dss_reset(void)
+{
+ /* Soft reset */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
+ return _omap_dss_wait_reset();
+}
+
void dss_set_venc_output(enum omap_dss_venc_type type)
{
int l = 0;
@@ -639,83 +663,424 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
}
-static int dss_get_clocks(void)
+static int dss_init(void)
{
- struct clk *clk;
int r;
+ u32 rev;
+ struct resource *dss_mem;
+ struct clk *dpll4_m4_ck;
- clk = clk_get(&dss.pdev->dev, "dss_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get clock dss_clk\n");
- r = PTR_ERR(clk);
- goto err;
+ dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
+ if (!dss_mem) {
+ DSSERR("can't get IORESOURCE_MEM DSS\n");
+ r = -EINVAL;
+ goto fail0;
+ }
+ dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
+ if (!dss.base) {
+ DSSERR("can't ioremap DSS\n");
+ r = -ENOMEM;
+ goto fail0;
}
- dss.dss_clk = clk;
+ /* disable LCD and DIGIT output. This seems to fix the synclost
+ * problem that we get, if the bootloader starts the DSS and
+ * the kernel resets it */
+ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
+
+#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
+ /* We need to wait here a bit, otherwise we sometimes start to
+ * get synclost errors, and after that only power cycle will
+ * restore DSS functionality. I have no idea why this happens.
+ * And we have to wait _before_ resetting the DSS, but after
+ * enabling clocks.
+ *
+ * This bug was at least present on OMAP3430. It's unknown
+ * if it happens on OMAP2 or OMAP3630.
+ */
+ msleep(50);
+#endif
+ _omap_dss_reset();
+
+ /* autoidle */
+ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
+
+ /* Select DPLL */
+ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+
+#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 */
+ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
+#endif
if (cpu_is_omap34xx()) {
- clk = clk_get(NULL, "dpll4_m4_ck");
- if (IS_ERR(clk)) {
+ dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
+ if (IS_ERR(dpll4_m4_ck)) {
DSSERR("Failed to get dpll4_m4_ck\n");
- r = PTR_ERR(clk);
- goto err;
+ r = PTR_ERR(dpll4_m4_ck);
+ goto fail1;
}
} else if (cpu_is_omap44xx()) {
- clk = clk_get(NULL, "dpll_per_m5x2_ck");
- if (IS_ERR(clk)) {
- DSSERR("Failed to get dpll_per_m5x2_ck\n");
- r = PTR_ERR(clk);
- goto err;
+ dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck");
+ if (IS_ERR(dpll4_m4_ck)) {
+ DSSERR("Failed to get dpll4_m4_ck\n");
+ r = PTR_ERR(dpll4_m4_ck);
+ goto fail1;
}
} else { /* omap24xx */
- clk = NULL;
+ dpll4_m4_ck = NULL;
}
- dss.dpll4_m4_ck = clk;
+ dss.dpll4_m4_ck = dpll4_m4_ck;
- return 0;
+ dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+ dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+ dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
+ dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
-err:
- if (dss.dss_clk)
- clk_put(dss.dss_clk);
- if (dss.dpll4_m4_ck)
- clk_put(dss.dpll4_m4_ck);
+ dss_save_context();
+
+ rev = dss_read_reg(DSS_REVISION);
+ printk(KERN_INFO "OMAP DSS rev %d.%d\n",
+ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ return 0;
+fail1:
+ iounmap(dss.base);
+fail0:
return r;
}
-static void dss_put_clocks(void)
+static void dss_exit(void)
{
if (dss.dpll4_m4_ck)
clk_put(dss.dpll4_m4_ck);
- clk_put(dss.dss_clk);
+
+ iounmap(dss.base);
}
-int dss_runtime_get(void)
+/* CONTEXT */
+static int dss_get_ctx_id(void)
{
+ struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
int r;
- DSSDBG("dss_runtime_get\n");
+ if (!pdata->board_data->get_last_off_on_transaction_id)
+ return 0;
+ r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev);
+ if (r < 0) {
+ dev_err(&dss.pdev->dev, "getting transaction ID failed, "
+ "will force context restore\n");
+ r = -1;
+ }
+ return r;
+}
+
+int dss_need_ctx_restore(void)
+{
+ int id = dss_get_ctx_id();
+
+ if (id < 0 || id != dss.ctx_id) {
+ DSSDBG("ctx id %d -> id %d\n",
+ dss.ctx_id, id);
+ dss.ctx_id = id;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void save_all_ctx(void)
+{
+ DSSDBG("save context\n");
+
+ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
+
+ dss_save_context();
+ dispc_save_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_save_context();
+#endif
+
+ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK);
+}
+
+static void restore_all_ctx(void)
+{
+ DSSDBG("restore context\n");
+
+ dss_clk_enable_all_no_ctx();
- r = pm_runtime_get_sync(&dss.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
+ dss_restore_context();
+ dispc_restore_context();
+#ifdef CONFIG_OMAP2_DSS_DSI
+ dsi_restore_context();
+#endif
+
+ dss_clk_disable_all_no_ctx();
}
-void dss_runtime_put(void)
+static int dss_get_clock(struct clk **clock, const char *clk_name)
+{
+ struct clk *clk;
+
+ clk = clk_get(&dss.pdev->dev, clk_name);
+
+ if (IS_ERR(clk)) {
+ DSSERR("can't get clock %s", clk_name);
+ return PTR_ERR(clk);
+ }
+
+ *clock = clk;
+
+ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
+
+ return 0;
+}
+
+static int dss_get_clocks(void)
{
int r;
+ struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data;
+
+ dss.dss_ick = NULL;
+ dss.dss_fck = NULL;
+ dss.dss_sys_clk = NULL;
+ dss.dss_tv_fck = NULL;
+ dss.dss_video_fck = NULL;
+
+ r = dss_get_clock(&dss.dss_ick, "ick");
+ if (r)
+ goto err;
+
+ r = dss_get_clock(&dss.dss_fck, "fck");
+ if (r)
+ goto err;
+
+ if (!pdata->opt_clock_available) {
+ r = -ENODEV;
+ goto err;
+ }
+
+ if (pdata->opt_clock_available("sys_clk")) {
+ r = dss_get_clock(&dss.dss_sys_clk, "sys_clk");
+ if (r)
+ goto err;
+ }
+
+ if (pdata->opt_clock_available("tv_clk")) {
+ r = dss_get_clock(&dss.dss_tv_fck, "tv_clk");
+ if (r)
+ goto err;
+ }
+
+ if (pdata->opt_clock_available("video_clk")) {
+ r = dss_get_clock(&dss.dss_video_fck, "video_clk");
+ if (r)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ if (dss.dss_ick)
+ clk_put(dss.dss_ick);
+ if (dss.dss_fck)
+ clk_put(dss.dss_fck);
+ if (dss.dss_sys_clk)
+ clk_put(dss.dss_sys_clk);
+ if (dss.dss_tv_fck)
+ clk_put(dss.dss_tv_fck);
+ if (dss.dss_video_fck)
+ clk_put(dss.dss_video_fck);
- DSSDBG("dss_runtime_put\n");
+ return r;
+}
- r = pm_runtime_put(&dss.pdev->dev);
- WARN_ON(r < 0);
+static void dss_put_clocks(void)
+{
+ if (dss.dss_video_fck)
+ clk_put(dss.dss_video_fck);
+ if (dss.dss_tv_fck)
+ clk_put(dss.dss_tv_fck);
+ if (dss.dss_sys_clk)
+ clk_put(dss.dss_sys_clk);
+ clk_put(dss.dss_fck);
+ clk_put(dss.dss_ick);
+}
+
+unsigned long dss_clk_get_rate(enum dss_clock clk)
+{
+ switch (clk) {
+ case DSS_CLK_ICK:
+ return clk_get_rate(dss.dss_ick);
+ case DSS_CLK_FCK:
+ return clk_get_rate(dss.dss_fck);
+ case DSS_CLK_SYSCK:
+ return clk_get_rate(dss.dss_sys_clk);
+ case DSS_CLK_TVFCK:
+ return clk_get_rate(dss.dss_tv_fck);
+ case DSS_CLK_VIDFCK:
+ return clk_get_rate(dss.dss_video_fck);
+ }
+
+ BUG();
+ return 0;
}
+static unsigned count_clk_bits(enum dss_clock clks)
+{
+ unsigned num_clks = 0;
+
+ if (clks & DSS_CLK_ICK)
+ ++num_clks;
+ if (clks & DSS_CLK_FCK)
+ ++num_clks;
+ if (clks & DSS_CLK_SYSCK)
+ ++num_clks;
+ if (clks & DSS_CLK_TVFCK)
+ ++num_clks;
+ if (clks & DSS_CLK_VIDFCK)
+ ++num_clks;
+
+ return num_clks;
+}
+
+static void dss_clk_enable_no_ctx(enum dss_clock clks)
+{
+ unsigned num_clks = count_clk_bits(clks);
+
+ if (clks & DSS_CLK_ICK)
+ clk_enable(dss.dss_ick);
+ if (clks & DSS_CLK_FCK)
+ clk_enable(dss.dss_fck);
+ if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
+ clk_enable(dss.dss_sys_clk);
+ if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
+ clk_enable(dss.dss_tv_fck);
+ if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
+ clk_enable(dss.dss_video_fck);
+
+ dss.num_clks_enabled += num_clks;
+}
+
+void dss_clk_enable(enum dss_clock clks)
+{
+ bool check_ctx = dss.num_clks_enabled == 0;
+
+ dss_clk_enable_no_ctx(clks);
+
+ /*
+ * HACK: On omap4 the registers may not be accessible right after
+ * enabling the clocks. At some point this will be handled by
+ * pm_runtime, but for the time begin this should make things work.
+ */
+ if (cpu_is_omap44xx() && check_ctx)
+ udelay(10);
+
+ if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
+ restore_all_ctx();
+}
+
+static void dss_clk_disable_no_ctx(enum dss_clock clks)
+{
+ unsigned num_clks = count_clk_bits(clks);
+
+ if (clks & DSS_CLK_ICK)
+ clk_disable(dss.dss_ick);
+ if (clks & DSS_CLK_FCK)
+ clk_disable(dss.dss_fck);
+ if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk)
+ clk_disable(dss.dss_sys_clk);
+ if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck)
+ clk_disable(dss.dss_tv_fck);
+ if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck)
+ clk_disable(dss.dss_video_fck);
+
+ dss.num_clks_enabled -= num_clks;
+}
+
+void dss_clk_disable(enum dss_clock clks)
+{
+ if (cpu_is_omap34xx()) {
+ unsigned num_clks = count_clk_bits(clks);
+
+ BUG_ON(dss.num_clks_enabled < num_clks);
+
+ if (dss.num_clks_enabled == num_clks)
+ save_all_ctx();
+ }
+
+ dss_clk_disable_no_ctx(clks);
+}
+
+static void dss_clk_enable_all_no_ctx(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
+ if (cpu_is_omap34xx())
+ clks |= DSS_CLK_VIDFCK;
+ dss_clk_enable_no_ctx(clks);
+}
+
+static void dss_clk_disable_all_no_ctx(void)
+{
+ enum dss_clock clks;
+
+ clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK;
+ if (cpu_is_omap34xx())
+ clks |= DSS_CLK_VIDFCK;
+ dss_clk_disable_no_ctx(clks);
+}
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
+/* CLOCKS */
+static void core_dump_clocks(struct seq_file *s)
+{
+ int i;
+ struct clk *clocks[5] = {
+ dss.dss_ick,
+ dss.dss_fck,
+ dss.dss_sys_clk,
+ dss.dss_tv_fck,
+ dss.dss_video_fck
+ };
+
+ const char *names[5] = {
+ "ick",
+ "fck",
+ "sys_clk",
+ "tv_fck",
+ "video_fck"
+ };
+
+ seq_printf(s, "- CORE -\n");
+
+ seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
+
+ for (i = 0; i < 5; i++) {
+ if (!clocks[i])
+ continue;
+ seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
+ names[i],
+ clocks[i]->name,
+ 24 - strlen(names[i]) - strlen(clocks[i]->name),
+ "",
+ clk_get_rate(clocks[i]),
+ clocks[i]->usecount);
+ }
+}
+#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */
+
/* DEBUGFS */
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
void dss_debug_dump_clocks(struct seq_file *s)
{
+ core_dump_clocks(s);
dss_dump_clocks(s);
dispc_dump_clocks(s);
#ifdef CONFIG_OMAP2_DSS_DSI
@@ -724,51 +1089,28 @@ void dss_debug_dump_clocks(struct seq_file *s)
}
#endif
+
/* DSS HW IP initialisation */
static int omap_dsshw_probe(struct platform_device *pdev)
{
- struct resource *dss_mem;
- u32 rev;
int r;
dss.pdev = pdev;
- dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
- if (!dss_mem) {
- DSSERR("can't get IORESOURCE_MEM DSS\n");
- r = -EINVAL;
- goto err_ioremap;
- }
- dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
- if (!dss.base) {
- DSSERR("can't ioremap DSS\n");
- r = -ENOMEM;
- goto err_ioremap;
- }
-
r = dss_get_clocks();
if (r)
goto err_clocks;
- pm_runtime_enable(&pdev->dev);
-
- r = dss_runtime_get();
- if (r)
- goto err_runtime_get;
+ dss_clk_enable_all_no_ctx();
- /* Select DPLL */
- REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
+ dss.ctx_id = dss_get_ctx_id();
+ DSSDBG("initial ctx id %u\n", dss.ctx_id);
-#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 */
- REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
-#endif
- dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
- dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
- dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
- dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
- dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
+ r = dss_init();
+ if (r) {
+ DSSERR("Failed to initialize DSS\n");
+ goto err_dss;
+ }
r = dpi_init();
if (r) {
@@ -782,66 +1124,42 @@ static int omap_dsshw_probe(struct platform_device *pdev)
goto err_sdi;
}
- rev = dss_read_reg(DSS_REVISION);
- printk(KERN_INFO "OMAP DSS rev %d.%d\n",
- FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
-
- dss_runtime_put();
-
+ dss_clk_disable_all_no_ctx();
return 0;
err_sdi:
dpi_exit();
err_dpi:
- dss_runtime_put();
-err_runtime_get:
- pm_runtime_disable(&pdev->dev);
+ dss_exit();
+err_dss:
+ dss_clk_disable_all_no_ctx();
dss_put_clocks();
err_clocks:
- iounmap(dss.base);
-err_ioremap:
return r;
}
static int omap_dsshw_remove(struct platform_device *pdev)
{
- dpi_exit();
- sdi_exit();
- iounmap(dss.base);
+ dss_exit();
- pm_runtime_disable(&pdev->dev);
+ /*
+ * As part of hwmod changes, DSS is not the only controller of dss
+ * clocks; hwmod framework itself will also enable clocks during hwmod
+ * init for dss, and autoidle is set in h/w for DSS. Hence, there's no
+ * need to disable clocks if their usecounts > 1.
+ */
+ WARN_ON(dss.num_clks_enabled > 0);
dss_put_clocks();
-
- return 0;
-}
-
-static int dss_runtime_suspend(struct device *dev)
-{
- dss_save_context();
- clk_disable(dss.dss_clk);
return 0;
}
-static int dss_runtime_resume(struct device *dev)
-{
- clk_enable(dss.dss_clk);
- dss_restore_context();
- return 0;
-}
-
-static const struct dev_pm_ops dss_pm_ops = {
- .runtime_suspend = dss_runtime_suspend,
- .runtime_resume = dss_runtime_resume,
-};
-
static struct platform_driver omap_dsshw_driver = {
.probe = omap_dsshw_probe,
.remove = omap_dsshw_remove,
.driver = {
.name = "omapdss_dss",
.owner = THIS_MODULE,
- .pm = &dss_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index ce17a613a30..8ab6d43329b 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -109,6 +109,14 @@ enum omap_parallel_interface_mode {
OMAP_DSS_PARALLELMODE_DSI,
};
+enum dss_clock {
+ DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */
+ DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */
+ DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */
+ DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */
+ DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/
+};
+
enum dss_hdmi_venc_clk_source_select {
DSS_VENC_TV_CLK = 0,
DSS_HDMI_M_PCLK = 1,
@@ -212,10 +220,13 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
int dss_init_platform_driver(void);
void dss_uninit_platform_driver(void);
-int dss_runtime_get(void);
-void dss_runtime_put(void);
-
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
+void dss_save_context(void);
+void dss_restore_context(void);
+void dss_clk_enable(enum dss_clock clks);
+void dss_clk_disable(enum dss_clock clks);
+unsigned long dss_clk_get_rate(enum dss_clock clk);
+int dss_need_ctx_restore(void);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
@@ -272,15 +283,15 @@ struct file_operations;
int dsi_init_platform_driver(void);
void dsi_uninit_platform_driver(void);
-int dsi_runtime_get(struct platform_device *dsidev);
-void dsi_runtime_put(struct platform_device *dsidev);
-
void dsi_dump_clocks(struct seq_file *s);
void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
+void dsi_save_context(void);
+void dsi_restore_context(void);
+
int dsi_init_display(struct omap_dss_device *display);
void dsi_irq_handler(void);
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
@@ -306,13 +317,6 @@ static inline int dsi_init_platform_driver(void)
static inline void dsi_uninit_platform_driver(void)
{
}
-static inline int dsi_runtime_get(struct platform_device *dsidev)
-{
- return 0;
-}
-static inline void dsi_runtime_put(struct platform_device *dsidev)
-{
-}
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
{
WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -380,8 +384,8 @@ void dispc_dump_regs(struct seq_file *s);
void dispc_irq_handler(void);
void dispc_fake_vsync_irq(void);
-int dispc_runtime_get(void);
-void dispc_runtime_put(void);
+void dispc_save_context(void);
+void dispc_restore_context(void);
void dispc_enable_sidle(void);
void dispc_disable_sidle(void);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index bd420f9650c..1c18888e5df 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -286,9 +286,7 @@ static const struct omap_dss_features omap3430_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
- FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
- FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
- FEAT_FIR_COEF_V,
+ FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
.num_mgrs = 2,
.num_ovls = 3,
@@ -308,8 +306,7 @@ static const struct omap_dss_features omap3630_dss_features = {
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
- FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
- FEAT_FIR_COEF_V,
+ FEAT_DSI_PLL_FREQSEL,
.num_mgrs = 2,
.num_ovls = 3,
@@ -330,8 +327,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
- FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
- FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
+ FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
.num_mgrs = 3,
.num_ovls = 3,
@@ -352,8 +348,7 @@ static const struct omap_dss_features omap4_dss_features = {
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
- FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
- FEAT_PRELOAD | FEAT_FIR_COEF_V,
+ FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
.num_mgrs = 3,
.num_ovls = 3,
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 5be8103a159..07b346f7d91 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -51,10 +51,6 @@ enum dss_feat_id {
FEAT_HDMI_CTS_SWMODE = 1 << 19,
FEAT_HANDLE_UV_SEPARATE = 1 << 20,
FEAT_ATTR2 = 1 << 21,
- FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22,
- FEAT_CPR = 1 << 23,
- FEAT_PRELOAD = 1 << 24,
- FEAT_FIR_COEF_V = 1 << 25,
};
/* DSS register field id */
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 1bbf31329c7..b0555f4f0a7 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -29,9 +29,6 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
#include <video/omapdss.h>
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -54,9 +51,6 @@ static struct {
u8 edid_set;
bool custom_set;
struct hdmi_config cfg;
-
- struct clk *sys_clk;
- struct clk *hdmi_clk;
} hdmi;
/*
@@ -168,27 +162,6 @@ static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
return val;
}
-static int hdmi_runtime_get(void)
-{
- int r;
-
- DSSDBG("hdmi_runtime_get\n");
-
- r = pm_runtime_get_sync(&hdmi.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-static void hdmi_runtime_put(void)
-{
- int r;
-
- DSSDBG("hdmi_runtime_put\n");
-
- r = pm_runtime_put(&hdmi.pdev->dev);
- WARN_ON(r < 0);
-}
-
int hdmi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
@@ -338,11 +311,30 @@ static int hdmi_phy_init(void)
return 0;
}
+static int hdmi_wait_softreset(void)
+{
+ /* reset W1 */
+ REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0);
+
+ /* wait till SOFTRESET == 0 */
+ if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) {
+ DSSERR("sysconfig reset failed\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static int hdmi_pll_program(struct hdmi_pll_info *fmt)
{
u16 r = 0;
enum hdmi_clk_refsel refsel;
+ /* wait for wrapper reset */
+ r = hdmi_wait_softreset();
+ if (r)
+ return r;
+
r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
if (r)
return r;
@@ -1072,7 +1064,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
unsigned long clkin, refclk;
u32 mf;
- clkin = clk_get_rate(hdmi.sys_clk) / 10000;
+ clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
/*
* Input clock is predivided by N + 1
* out put of which is reference clk
@@ -1106,6 +1098,16 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
}
+static void hdmi_enable_clocks(int enable)
+{
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK |
+ DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK |
+ DSS_CLK_SYSCK | DSS_CLK_VIDFCK);
+}
+
static int hdmi_power_on(struct omap_dss_device *dssdev)
{
int r, code = 0;
@@ -1113,9 +1115,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
struct omap_video_timings *p;
unsigned long phy;
- r = hdmi_runtime_get();
- if (r)
- return r;
+ hdmi_enable_clocks(1);
dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
@@ -1180,7 +1180,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
return 0;
err:
- hdmi_runtime_put();
+ hdmi_enable_clocks(0);
return -EIO;
}
@@ -1191,7 +1191,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
hdmi_wp_video_start(0);
hdmi_phy_off();
hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
- hdmi_runtime_put();
+ hdmi_enable_clocks(0);
hdmi.edid_set = 0;
}
@@ -1686,43 +1686,14 @@ static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
};
#endif
-static int hdmi_get_clocks(struct platform_device *pdev)
-{
- struct clk *clk;
-
- clk = clk_get(&pdev->dev, "sys_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get sys_clk\n");
- return PTR_ERR(clk);
- }
-
- hdmi.sys_clk = clk;
-
- clk = clk_get(&pdev->dev, "hdmi_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get hdmi_clk\n");
- clk_put(hdmi.sys_clk);
- return PTR_ERR(clk);
- }
-
- hdmi.hdmi_clk = clk;
-
- return 0;
-}
-
-static void hdmi_put_clocks(void)
-{
- if (hdmi.sys_clk)
- clk_put(hdmi.sys_clk);
- if (hdmi.hdmi_clk)
- clk_put(hdmi.hdmi_clk);
-}
-
/* HDMI HW IP initialisation */
static int omapdss_hdmihw_probe(struct platform_device *pdev)
{
struct resource *hdmi_mem;
- int r;
+#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
+ defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
+ int ret;
+#endif
hdmi.pdata = pdev->dev.platform_data;
hdmi.pdev = pdev;
@@ -1742,25 +1713,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
return -ENOMEM;
}
- r = hdmi_get_clocks(pdev);
- if (r) {
- iounmap(hdmi.base_wp);
- return r;
- }
-
- pm_runtime_enable(&pdev->dev);
-
hdmi_panel_init();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
/* Register ASoC codec DAI */
- r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
+ ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
&hdmi_codec_dai_drv, 1);
- if (r) {
+ if (ret) {
DSSERR("can't register ASoC HDMI audio codec\n");
- return r;
+ return ret;
}
#endif
return 0;
@@ -1775,62 +1738,17 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
snd_soc_unregister_codec(&pdev->dev);
#endif
- pm_runtime_disable(&pdev->dev);
-
- hdmi_put_clocks();
-
iounmap(hdmi.base_wp);
return 0;
}
-static int hdmi_runtime_suspend(struct device *dev)
-{
- clk_disable(hdmi.hdmi_clk);
- clk_disable(hdmi.sys_clk);
-
- dispc_runtime_put();
- dss_runtime_put();
-
- return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r < 0)
- goto err_get_dispc;
-
-
- clk_enable(hdmi.sys_clk);
- clk_enable(hdmi.hdmi_clk);
-
- return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
-}
-
-static const struct dev_pm_ops hdmi_pm_ops = {
- .runtime_suspend = hdmi_runtime_suspend,
- .runtime_resume = hdmi_runtime_resume,
-};
-
static struct platform_driver omapdss_hdmihw_driver = {
.probe = omapdss_hdmihw_probe,
.remove = omapdss_hdmihw_remove,
.driver = {
.name = "omapdss_hdmi",
.owner = THIS_MODULE,
- .pm = &hdmi_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index c6d26c6e697..9aeea50e33f 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -416,6 +416,8 @@ struct overlay_cache_data {
enum omap_burst_size burst_size;
u32 fifo_low;
u32 fifo_high;
+
+ bool manual_update;
};
struct manager_cache_data {
@@ -435,6 +437,7 @@ struct manager_cache_data {
bool alpha_enabled;
+ bool manual_upd_display;
bool manual_update;
bool do_manual_update;
@@ -536,15 +539,24 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return 0;
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- return 0;
-
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
} else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ enum omap_dss_update_mode mode;
+ mode = dssdev->driver->get_update_mode(dssdev);
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return 0;
+
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_FRAMEDONE
+ : DISPC_IRQ_FRAMEDONE2;
+ } else {
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_VSYNC
+ : DISPC_IRQ_VSYNC2;
+ }
}
mc = &dss_cache.manager_cache[mgr->id];
@@ -605,15 +617,24 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return 0;
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- return 0;
-
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
} else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
+ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
+ enum omap_dss_update_mode mode;
+ mode = dssdev->driver->get_update_mode(dssdev);
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return 0;
+
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_FRAMEDONE
+ : DISPC_IRQ_FRAMEDONE2;
+ } else {
+ irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
+ DISPC_IRQ_VSYNC
+ : DISPC_IRQ_VSYNC2;
+ }
}
oc = &dss_cache.overlay_cache[ovl->id];
@@ -742,7 +763,7 @@ static int configure_overlay(enum omap_plane plane)
orig_outw = outw;
orig_outh = outh;
- if (mc->manual_update && mc->do_manual_update) {
+ if (c->manual_update && mc->do_manual_update) {
unsigned bpp;
unsigned scale_x_m = w, scale_x_d = outw;
unsigned scale_y_m = h, scale_y_d = outh;
@@ -907,7 +928,7 @@ static int configure_dispc(void)
if (!oc->dirty)
continue;
- if (mc->manual_update && !mc->do_manual_update)
+ if (oc->manual_update && !mc->do_manual_update)
continue;
if (mgr_busy[oc->channel]) {
@@ -955,7 +976,7 @@ static int configure_dispc(void)
/* We don't need GO with manual update display. LCD iface will
* always be turned off after frame, and new settings will be
* taken in to use at next update */
- if (!mc->manual_update)
+ if (!mc->manual_upd_display)
dispc_go(i);
}
@@ -1215,10 +1236,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
- r = dispc_runtime_get();
- if (r)
- return r;
-
spin_lock_irqsave(&dss_cache.lock, flags);
/* Configure overlays */
@@ -1285,6 +1302,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
oc->enabled = true;
+ oc->manual_update =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ dssdev->driver->get_update_mode(dssdev) !=
+ OMAP_DSS_UPDATE_AUTO;
+
++num_planes_enabled;
}
@@ -1319,8 +1341,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
mc->trans_enabled = mgr->info.trans_enabled;
mc->alpha_enabled = mgr->info.alpha_enabled;
- mc->manual_update =
+ mc->manual_upd_display =
dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
+
+ mc->manual_update =
+ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
+ dssdev->driver->get_update_mode(dssdev) !=
+ OMAP_DSS_UPDATE_AUTO;
}
/* XXX TODO: Try to get fifomerge working. The problem is that it
@@ -1382,6 +1409,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
}
r = 0;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
if (!dss_cache.irq_enabled) {
u32 mask;
@@ -1394,11 +1422,10 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
dss_cache.irq_enabled = true;
}
configure_dispc();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
spin_unlock_irqrestore(&dss_cache.lock, flags);
- dispc_runtime_put();
-
return r;
}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index c84380c53c3..0f08025b1f0 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -84,42 +84,32 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
old_mgr = ovl->manager;
- r = dispc_runtime_get();
- if (r)
- return r;
-
/* detach old manager */
if (old_mgr) {
r = ovl->unset_manager(ovl);
if (r) {
DSSERR("detach failed\n");
- goto err;
+ return r;
}
r = old_mgr->apply(old_mgr);
if (r)
- goto err;
+ return r;
}
if (mgr) {
r = ovl->set_manager(ovl, mgr);
if (r) {
DSSERR("Failed to attach overlay\n");
- goto err;
+ return r;
}
r = mgr->apply(mgr);
if (r)
- goto err;
+ return r;
}
- dispc_runtime_put();
-
return size;
-
-err:
- dispc_runtime_put();
- return r;
}
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
@@ -248,9 +238,6 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
- if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
- return -ENODEV;
-
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
@@ -517,6 +504,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
ovl->manager = mgr;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
/* 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.
@@ -530,6 +518,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
* the overlay, but before moving the overlay to TV.
*/
dispc_set_channel_out(ovl->id, mgr->id);
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
return 0;
}
@@ -730,8 +719,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
}
if (mgr) {
- dispc_runtime_get();
-
for (i = 0; i < dss_feat_get_num_ovls(); i++) {
struct omap_overlay *ovl;
ovl = omap_dss_get_overlay(i);
@@ -741,8 +728,6 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
omap_dss_set_manager(ovl, mgr);
}
}
-
- dispc_runtime_put();
}
}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index c57e3fbf239..c06fbe0bc67 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -33,8 +33,6 @@
#include <linux/hrtimer.h>
#include <linux/seq_file.h>
#include <linux/semaphore.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include "dss.h"
@@ -122,25 +120,12 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx)
return __raw_readl(rfbi.base + idx.idx);
}
-static int rfbi_runtime_get(void)
+static void rfbi_enable_clocks(bool enable)
{
- int r;
-
- DSSDBG("rfbi_runtime_get\n");
-
- r = pm_runtime_get_sync(&rfbi.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-static void rfbi_runtime_put(void)
-{
- int r;
-
- DSSDBG("rfbi_runtime_put\n");
-
- r = pm_runtime_put(&rfbi.pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
void rfbi_bus_lock(void)
@@ -820,8 +805,7 @@ void rfbi_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
- if (rfbi_runtime_get())
- return;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
DUMPREG(RFBI_REVISION);
DUMPREG(RFBI_SYSCONFIG);
@@ -852,7 +836,7 @@ void rfbi_dump_regs(struct seq_file *s)
DUMPREG(RFBI_VSYNC_WIDTH);
DUMPREG(RFBI_HSYNC_WIDTH);
- rfbi_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
#undef DUMPREG
}
@@ -860,9 +844,7 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
- r = rfbi_runtime_get();
- if (r)
- return r;
+ rfbi_enable_clocks(1);
r = omap_dss_start_device(dssdev);
if (r) {
@@ -897,7 +879,6 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
err1:
omap_dss_stop_device(dssdev);
err0:
- rfbi_runtime_put();
return r;
}
EXPORT_SYMBOL(omapdss_rfbi_display_enable);
@@ -908,7 +889,7 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
DISPC_IRQ_FRAMEDONE);
omap_dss_stop_device(dssdev);
- rfbi_runtime_put();
+ rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
@@ -923,9 +904,8 @@ int rfbi_init_display(struct omap_dss_device *dssdev)
static int omap_rfbihw_probe(struct platform_device *pdev)
{
u32 rev;
+ u32 l;
struct resource *rfbi_mem;
- struct clk *clk;
- int r;
rfbi.pdev = pdev;
@@ -934,99 +914,46 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
if (!rfbi_mem) {
DSSERR("can't get IORESOURCE_MEM RFBI\n");
- r = -EINVAL;
- goto err_ioremap;
+ return -EINVAL;
}
rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
if (!rfbi.base) {
DSSERR("can't ioremap RFBI\n");
- r = -ENOMEM;
- goto err_ioremap;
+ return -ENOMEM;
}
- pm_runtime_enable(&pdev->dev);
-
- r = rfbi_runtime_get();
- if (r)
- goto err_get_rfbi;
+ rfbi_enable_clocks(1);
msleep(10);
- clk = clk_get(&pdev->dev, "rfbi_iclk");
- if (IS_ERR(clk)) {
- DSSERR("can't get rfbi_iclk\n");
- r = PTR_ERR(clk);
- goto err_get_ick;
- }
-
- rfbi.l4_khz = clk_get_rate(clk) / 1000;
+ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;
- clk_put(clk);
+ /* Enable autoidle and smart-idle */
+ l = rfbi_read_reg(RFBI_SYSCONFIG);
+ l |= (1 << 0) | (2 << 3);
+ rfbi_write_reg(RFBI_SYSCONFIG, l);
rev = rfbi_read_reg(RFBI_REVISION);
dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
- rfbi_runtime_put();
+ rfbi_enable_clocks(0);
return 0;
-
-err_get_ick:
- rfbi_runtime_put();
-err_get_rfbi:
- pm_runtime_disable(&pdev->dev);
- iounmap(rfbi.base);
-err_ioremap:
- return r;
}
static int omap_rfbihw_remove(struct platform_device *pdev)
{
- pm_runtime_disable(&pdev->dev);
iounmap(rfbi.base);
return 0;
}
-static int rfbi_runtime_suspend(struct device *dev)
-{
- dispc_runtime_put();
- dss_runtime_put();
-
- return 0;
-}
-
-static int rfbi_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r < 0)
- goto err_get_dispc;
-
- return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
-}
-
-static const struct dev_pm_ops rfbi_pm_ops = {
- .runtime_suspend = rfbi_runtime_suspend,
- .runtime_resume = rfbi_runtime_resume,
-};
-
static struct platform_driver omap_rfbihw_driver = {
.probe = omap_rfbihw_probe,
.remove = omap_rfbihw_remove,
.driver = {
.name = "omapdss_rfbi",
.owner = THIS_MODULE,
- .pm = &rfbi_pm_ops,
},
};
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 3a688c871a4..0bd4b0350f8 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -20,11 +20,13 @@
#define DSS_SUBSYS_NAME "SDI"
#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include <video/omapdss.h>
+#include <plat/cpu.h>
#include "dss.h"
static struct {
@@ -58,20 +60,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
- goto err_start_dev;
+ goto err0;
}
r = regulator_enable(sdi.vdds_sdi_reg);
if (r)
- goto err_reg_enable;
+ goto err1;
- r = dss_runtime_get();
- if (r)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r)
- goto err_get_dispc;
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
sdi_basic_init(dssdev);
@@ -84,7 +80,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = dss_calc_clock_div(1, t->pixel_clock * 1000,
&dss_cinfo, &dispc_cinfo);
if (r)
- goto err_calc_clock_div;
+ goto err2;
fck = dss_cinfo.fck;
lck_div = dispc_cinfo.lck_div;
@@ -105,34 +101,27 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
r = dss_set_clock_div(&dss_cinfo);
if (r)
- goto err_set_dss_clock_div;
+ goto err2;
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
- goto err_set_dispc_clock_div;
+ goto err2;
dss_sdi_init(dssdev->phy.sdi.datapairs);
r = dss_sdi_enable();
if (r)
- goto err_sdi_enable;
+ goto err1;
mdelay(2);
dssdev->manager->enable(dssdev->manager);
return 0;
-
-err_sdi_enable:
-err_set_dispc_clock_div:
-err_set_dss_clock_div:
-err_calc_clock_div:
- dispc_runtime_put();
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
+err2:
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
regulator_disable(sdi.vdds_sdi_reg);
-err_reg_enable:
+err1:
omap_dss_stop_device(dssdev);
-err_start_dev:
+err0:
return r;
}
EXPORT_SYMBOL(omapdss_sdi_display_enable);
@@ -143,8 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
dss_sdi_disable();
- dispc_runtime_put();
- dss_runtime_put();
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
regulator_disable(sdi.vdds_sdi_reg);
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index f75159dc7f7..980f919ed98 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -33,13 +33,11 @@
#include <linux/seq_file.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/pm_runtime.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
-#include "dss_features.h"
/* Venc registers */
#define VENC_REV_ID 0x00
@@ -294,9 +292,6 @@ static struct {
struct mutex venc_lock;
u32 wss_data;
struct regulator *vdda_dac_reg;
-
- struct clk *tv_clk;
- struct clk *tv_dac_clk;
} venc;
static inline void venc_write_reg(int idx, u32 val)
@@ -385,25 +380,14 @@ static void venc_reset(void)
#endif
}
-static int venc_runtime_get(void)
-{
- int r;
-
- DSSDBG("venc_runtime_get\n");
-
- r = pm_runtime_get_sync(&venc.pdev->dev);
- WARN_ON(r < 0);
- return r < 0 ? r : 0;
-}
-
-static void venc_runtime_put(void)
+static void venc_enable_clocks(int enable)
{
- int r;
-
- DSSDBG("venc_runtime_put\n");
-
- r = pm_runtime_put(&venc.pdev->dev);
- WARN_ON(r < 0);
+ if (enable)
+ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+ DSS_CLK_VIDFCK);
+ else
+ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK |
+ DSS_CLK_VIDFCK);
}
static const struct venc_config *venc_timings_to_config(
@@ -422,6 +406,8 @@ static void venc_power_on(struct omap_dss_device *dssdev)
{
u32 l;
+ venc_enable_clocks(1);
+
venc_reset();
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
@@ -462,6 +448,8 @@ static void venc_power_off(struct omap_dss_device *dssdev)
dssdev->platform_disable(dssdev);
regulator_disable(venc.vdda_dac_reg);
+
+ venc_enable_clocks(0);
}
@@ -499,10 +487,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
goto err1;
}
- r = venc_runtime_get();
- if (r)
- goto err1;
-
venc_power_on(dssdev);
venc.wss_data = 0;
@@ -536,8 +520,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
venc_power_off(dssdev);
- venc_runtime_put();
-
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev);
@@ -556,6 +538,20 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
return venc_panel_enable(dssdev);
}
+static enum omap_dss_update_mode venc_get_update_mode(
+ struct omap_dss_device *dssdev)
+{
+ return OMAP_DSS_UPDATE_AUTO;
+}
+
+static int venc_set_update_mode(struct omap_dss_device *dssdev,
+ enum omap_dss_update_mode mode)
+{
+ if (mode != OMAP_DSS_UPDATE_AUTO)
+ return -EINVAL;
+ return 0;
+}
+
static void venc_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
@@ -602,7 +598,6 @@ static u32 venc_get_wss(struct omap_dss_device *dssdev)
static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
const struct venc_config *config;
- int r;
DSSDBG("venc_set_wss\n");
@@ -613,19 +608,16 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
/* Invert due to VENC_L21_WC_CTL:INV=1 */
venc.wss_data = (wss ^ 0xfffff) << 8;
- r = venc_runtime_get();
- if (r)
- goto err;
+ venc_enable_clocks(1);
venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data |
venc.wss_data);
- venc_runtime_put();
+ venc_enable_clocks(0);
-err:
mutex_unlock(&venc.venc_lock);
- return r;
+ return 0;
}
static struct omap_dss_driver venc_driver = {
@@ -640,6 +632,9 @@ static struct omap_dss_driver venc_driver = {
.get_resolution = omapdss_default_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
+ .set_update_mode = venc_set_update_mode,
+ .get_update_mode = venc_get_update_mode,
+
.get_timings = venc_get_timings,
.set_timings = venc_set_timings,
.check_timings = venc_check_timings,
@@ -678,8 +673,7 @@ void venc_dump_regs(struct seq_file *s)
{
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
- if (venc_runtime_get())
- return;
+ venc_enable_clocks(1);
DUMPREG(VENC_F_CONTROL);
DUMPREG(VENC_VIDOUT_CTRL);
@@ -723,53 +717,16 @@ void venc_dump_regs(struct seq_file *s)
DUMPREG(VENC_OUTPUT_CONTROL);
DUMPREG(VENC_OUTPUT_TEST);
- venc_runtime_put();
+ venc_enable_clocks(0);
#undef DUMPREG
}
-static int venc_get_clocks(struct platform_device *pdev)
-{
- struct clk *clk;
-
- clk = clk_get(&pdev->dev, "tv_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get tv_clk\n");
- return PTR_ERR(clk);
- }
-
- venc.tv_clk = clk;
-
- if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
- clk = clk_get(&pdev->dev, "tv_dac_clk");
- if (IS_ERR(clk)) {
- DSSERR("can't get tv_dac_clk\n");
- clk_put(venc.tv_clk);
- return PTR_ERR(clk);
- }
- } else {
- clk = NULL;
- }
-
- venc.tv_dac_clk = clk;
-
- return 0;
-}
-
-static void venc_put_clocks(void)
-{
- if (venc.tv_clk)
- clk_put(venc.tv_clk);
- if (venc.tv_dac_clk)
- clk_put(venc.tv_dac_clk);
-}
-
/* VENC HW IP initialisation */
static int omap_venchw_probe(struct platform_device *pdev)
{
u8 rev_id;
struct resource *venc_mem;
- int r;
venc.pdev = pdev;
@@ -780,40 +737,22 @@ static int omap_venchw_probe(struct platform_device *pdev)
venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
if (!venc_mem) {
DSSERR("can't get IORESOURCE_MEM VENC\n");
- r = -EINVAL;
- goto err_ioremap;
+ return -EINVAL;
}
venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
if (!venc.base) {
DSSERR("can't ioremap VENC\n");
- r = -ENOMEM;
- goto err_ioremap;
+ return -ENOMEM;
}
- r = venc_get_clocks(pdev);
- if (r)
- goto err_get_clk;
-
- pm_runtime_enable(&pdev->dev);
-
- r = venc_runtime_get();
- if (r)
- goto err_get_venc;
+ venc_enable_clocks(1);
rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
- venc_runtime_put();
+ venc_enable_clocks(0);
return omap_dss_register_driver(&venc_driver);
-
-err_get_venc:
- pm_runtime_disable(&pdev->dev);
- venc_put_clocks();
-err_get_clk:
- iounmap(venc.base);
-err_ioremap:
- return r;
}
static int omap_venchw_remove(struct platform_device *pdev)
@@ -824,61 +763,16 @@ static int omap_venchw_remove(struct platform_device *pdev)
}
omap_dss_unregister_driver(&venc_driver);
- pm_runtime_disable(&pdev->dev);
- venc_put_clocks();
-
iounmap(venc.base);
return 0;
}
-static int venc_runtime_suspend(struct device *dev)
-{
- if (venc.tv_dac_clk)
- clk_disable(venc.tv_dac_clk);
- clk_disable(venc.tv_clk);
-
- dispc_runtime_put();
- dss_runtime_put();
-
- return 0;
-}
-
-static int venc_runtime_resume(struct device *dev)
-{
- int r;
-
- r = dss_runtime_get();
- if (r < 0)
- goto err_get_dss;
-
- r = dispc_runtime_get();
- if (r < 0)
- goto err_get_dispc;
-
- clk_enable(venc.tv_clk);
- if (venc.tv_dac_clk)
- clk_enable(venc.tv_dac_clk);
-
- return 0;
-
-err_get_dispc:
- dss_runtime_put();
-err_get_dss:
- return r;
-}
-
-static const struct dev_pm_ops venc_pm_ops = {
- .runtime_suspend = venc_runtime_suspend,
- .runtime_resume = venc_runtime_resume,
-};
-
static struct platform_driver omap_venchw_driver = {
.probe = omap_venchw_probe,
.remove = omap_venchw_remove,
.driver = {
.name = "omapdss_venc",
.owner = THIS_MODULE,
- .pm = &venc_pm_ops,
},
};
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 6b1ac23dbbd..cff450392b7 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -316,67 +316,67 @@ int omapfb_update_window(struct fb_info *fbi,
}
EXPORT_SYMBOL(omapfb_update_window);
-int omapfb_set_update_mode(struct fb_info *fbi,
+static int omapfb_set_update_mode(struct fb_info *fbi,
enum omapfb_update_mode mode)
{
struct omap_dss_device *display = fb2display(fbi);
- struct omapfb_info *ofbi = FB2OFB(fbi);
- struct omapfb2_device *fbdev = ofbi->fbdev;
- struct omapfb_display_data *d;
+ enum omap_dss_update_mode um;
int r;
- if (!display)
- return -EINVAL;
-
- if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE)
+ if (!display || !display->driver->set_update_mode)
return -EINVAL;
- omapfb_lock(fbdev);
-
- d = get_display_data(fbdev, display);
-
- if (d->update_mode == mode) {
- omapfb_unlock(fbdev);
- return 0;
- }
+ switch (mode) {
+ case OMAPFB_UPDATE_DISABLED:
+ um = OMAP_DSS_UPDATE_DISABLED;
+ break;
- r = 0;
+ case OMAPFB_AUTO_UPDATE:
+ um = OMAP_DSS_UPDATE_AUTO;
+ break;
- if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
- if (mode == OMAPFB_AUTO_UPDATE)
- omapfb_start_auto_update(fbdev, display);
- else /* MANUAL_UPDATE */
- omapfb_stop_auto_update(fbdev, display);
+ case OMAPFB_MANUAL_UPDATE:
+ um = OMAP_DSS_UPDATE_MANUAL;
+ break;
- d->update_mode = mode;
- } else { /* AUTO_UPDATE */
- if (mode == OMAPFB_MANUAL_UPDATE)
- r = -EINVAL;
+ default:
+ return -EINVAL;
}
- omapfb_unlock(fbdev);
+ r = display->driver->set_update_mode(display, um);
return r;
}
-int omapfb_get_update_mode(struct fb_info *fbi,
+static int omapfb_get_update_mode(struct fb_info *fbi,
enum omapfb_update_mode *mode)
{
struct omap_dss_device *display = fb2display(fbi);
- struct omapfb_info *ofbi = FB2OFB(fbi);
- struct omapfb2_device *fbdev = ofbi->fbdev;
- struct omapfb_display_data *d;
+ enum omap_dss_update_mode m;
if (!display)
return -EINVAL;
- omapfb_lock(fbdev);
-
- d = get_display_data(fbdev, display);
+ if (!display->driver->get_update_mode) {
+ *mode = OMAPFB_AUTO_UPDATE;
+ return 0;
+ }
- *mode = d->update_mode;
+ m = display->driver->get_update_mode(display);
- omapfb_unlock(fbdev);
+ switch (m) {
+ case OMAP_DSS_UPDATE_DISABLED:
+ *mode = OMAPFB_UPDATE_DISABLED;
+ break;
+ case OMAP_DSS_UPDATE_AUTO:
+ *mode = OMAPFB_AUTO_UPDATE;
+ break;
+ case OMAP_DSS_UPDATE_MANUAL:
+ *mode = OMAPFB_MANUAL_UPDATE;
+ break;
+ default:
+ BUG();
+ }
return 0;
}
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 602b71a92d3..505bc12a303 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -46,10 +46,6 @@ static char *def_vram;
static int def_vrfb;
static int def_rotate;
static int def_mirror;
-static bool auto_update;
-static unsigned int auto_update_freq;
-module_param(auto_update, bool, 0);
-module_param(auto_update_freq, uint, 0644);
#ifdef DEBUG
unsigned int omapfb_debug;
@@ -1246,7 +1242,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_dss_device *display = fb2display(fbi);
- struct omapfb_display_data *d;
int r = 0;
if (!display)
@@ -1254,8 +1249,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
omapfb_lock(fbdev);
- d = get_display_data(fbdev, display);
-
switch (blank) {
case FB_BLANK_UNBLANK:
if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
@@ -1264,11 +1257,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->driver->resume)
r = display->driver->resume(display);
- if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
- d->update_mode == OMAPFB_AUTO_UPDATE &&
- !d->auto_update_work_enabled)
- omapfb_start_auto_update(fbdev, display);
-
break;
case FB_BLANK_NORMAL:
@@ -1280,9 +1268,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
goto exit;
- if (d->auto_update_work_enabled)
- omapfb_stop_auto_update(fbdev, display);
-
if (display->driver->suspend)
r = display->driver->suspend(display);
@@ -1739,78 +1724,6 @@ err:
return r;
}
-static void omapfb_auto_update_work(struct work_struct *work)
-{
- struct omap_dss_device *dssdev;
- struct omap_dss_driver *dssdrv;
- struct omapfb_display_data *d;
- u16 w, h;
- unsigned int freq;
- struct omapfb2_device *fbdev;
-
- d = container_of(work, struct omapfb_display_data,
- auto_update_work.work);
-
- dssdev = d->dssdev;
- dssdrv = dssdev->driver;
- fbdev = d->fbdev;
-
- if (!dssdrv || !dssdrv->update)
- return;
-
- if (dssdrv->sync)
- dssdrv->sync(dssdev);
-
- dssdrv->get_resolution(dssdev, &w, &h);
- dssdrv->update(dssdev, 0, 0, w, h);
-
- freq = auto_update_freq;
- if (freq == 0)
- freq = 20;
- queue_delayed_work(fbdev->auto_update_wq,
- &d->auto_update_work, HZ / freq);
-}
-
-void omapfb_start_auto_update(struct omapfb2_device *fbdev,
- struct omap_dss_device *display)
-{
- struct omapfb_display_data *d;
-
- if (fbdev->auto_update_wq == NULL) {
- struct workqueue_struct *wq;
-
- wq = create_singlethread_workqueue("omapfb_auto_update");
-
- if (wq == NULL) {
- dev_err(fbdev->dev, "Failed to create workqueue for "
- "auto-update\n");
- return;
- }
-
- fbdev->auto_update_wq = wq;
- }
-
- d = get_display_data(fbdev, display);
-
- INIT_DELAYED_WORK(&d->auto_update_work, omapfb_auto_update_work);
-
- d->auto_update_work_enabled = true;
-
- omapfb_auto_update_work(&d->auto_update_work.work);
-}
-
-void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
- struct omap_dss_device *display)
-{
- struct omapfb_display_data *d;
-
- d = get_display_data(fbdev, display);
-
- cancel_delayed_work_sync(&d->auto_update_work);
-
- d->auto_update_work_enabled = false;
-}
-
/* initialize fb_info, var, fix to something sane based on the display */
static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
{
@@ -1945,21 +1858,10 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
}
for (i = 0; i < fbdev->num_displays; i++) {
- struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
-
- if (fbdev->displays[i].auto_update_work_enabled)
- omapfb_stop_auto_update(fbdev, dssdev);
-
- if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
- dssdev->driver->disable(dssdev);
-
- omap_dss_put_device(dssdev);
- }
+ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
+ fbdev->displays[i]->driver->disable(fbdev->displays[i]);
- if (fbdev->auto_update_wq != NULL) {
- flush_workqueue(fbdev->auto_update_wq);
- destroy_workqueue(fbdev->auto_update_wq);
- fbdev->auto_update_wq = NULL;
+ omap_dss_put_device(fbdev->displays[i]);
}
dev_set_drvdata(fbdev->dev, NULL);
@@ -2182,14 +2084,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
int r;
u8 bpp;
struct omap_video_timings timings, temp_timings;
- struct omapfb_display_data *d;
r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
if (r)
return r;
- d = get_display_data(fbdev, display);
- d->bpp_override = bpp;
+ fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
+ fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
+ ++fbdev->num_bpp_overrides;
if (display->driver->check_timings) {
r = display->driver->check_timings(display, &timings);
@@ -2215,14 +2117,14 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
- struct omapfb_display_data *d;
+ int i;
BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
- d = get_display_data(fbdev, dssdev);
-
- if (d->bpp_override != 0)
- return d->bpp_override;
+ for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
+ if (dssdev == fbdev->bpp_overrides[i].dssdev)
+ return fbdev->bpp_overrides[i].bpp;
+ }
return dssdev->driver->get_recommended_bpp(dssdev);
}
@@ -2254,9 +2156,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
display = NULL;
for (i = 0; i < fbdev->num_displays; ++i) {
- if (strcmp(fbdev->displays[i].dssdev->name,
+ if (strcmp(fbdev->displays[i]->name,
display_str) == 0) {
- display = fbdev->displays[i].dssdev;
+ display = fbdev->displays[i];
break;
}
}
@@ -2280,7 +2182,6 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
struct omap_dss_driver *dssdrv = dssdev->driver;
- struct omapfb_display_data *d;
int r;
r = dssdrv->enable(dssdev);
@@ -2290,20 +2191,8 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return r;
}
- d = get_display_data(fbdev, dssdev);
-
- d->fbdev = fbdev;
-
if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
u16 w, h;
-
- if (auto_update) {
- omapfb_start_auto_update(fbdev, dssdev);
- d->update_mode = OMAPFB_AUTO_UPDATE;
- } else {
- d->update_mode = OMAPFB_MANUAL_UPDATE;
- }
-
if (dssdrv->enable_te) {
r = dssdrv->enable_te(dssdev, 1);
if (r) {
@@ -2312,6 +2201,16 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
}
}
+ if (dssdrv->set_update_mode) {
+ r = dssdrv->set_update_mode(dssdev,
+ OMAP_DSS_UPDATE_MANUAL);
+ if (r) {
+ dev_err(fbdev->dev,
+ "Failed to set update mode\n");
+ return r;
+ }
+ }
+
dssdrv->get_resolution(dssdev, &w, &h);
r = dssdrv->update(dssdev, 0, 0, w, h);
if (r) {
@@ -2320,7 +2219,15 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
return r;
}
} else {
- d->update_mode = OMAPFB_AUTO_UPDATE;
+ if (dssdrv->set_update_mode) {
+ r = dssdrv->set_update_mode(dssdev,
+ OMAP_DSS_UPDATE_AUTO);
+ if (r) {
+ dev_err(fbdev->dev,
+ "Failed to set update mode\n");
+ return r;
+ }
+ }
}
return 0;
@@ -2368,8 +2275,6 @@ static int omapfb_probe(struct platform_device *pdev)
fbdev->num_displays = 0;
dssdev = NULL;
for_each_dss_dev(dssdev) {
- struct omapfb_display_data *d;
-
omap_dss_get_device(dssdev);
if (!dssdev->driver) {
@@ -2377,12 +2282,7 @@ static int omapfb_probe(struct platform_device *pdev)
r = -ENODEV;
}
- d = &fbdev->displays[fbdev->num_displays++];
- d->dssdev = dssdev;
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
- d->update_mode = OMAPFB_MANUAL_UPDATE;
- else
- d->update_mode = OMAPFB_AUTO_UPDATE;
+ fbdev->displays[fbdev->num_displays++] = dssdev;
}
if (r)
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 153bf1aceeb..2f5e817b2a9 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -518,39 +518,6 @@ static ssize_t show_virt(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
}
-static ssize_t show_upd_mode(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fb_info *fbi = dev_get_drvdata(dev);
- enum omapfb_update_mode mode;
- int r;
-
- r = omapfb_get_update_mode(fbi, &mode);
-
- if (r)
- return r;
-
- return snprintf(buf, PAGE_SIZE, "%u\n", (unsigned)mode);
-}
-
-static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fb_info *fbi = dev_get_drvdata(dev);
- unsigned mode;
- int r;
-
- r = kstrtouint(buf, 0, &mode);
- if (r)
- return r;
-
- r = omapfb_set_update_mode(fbi, mode);
- if (r)
- return r;
-
- return count;
-}
-
static struct device_attribute omapfb_attrs[] = {
__ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type,
store_rotate_type),
@@ -561,7 +528,6 @@ static struct device_attribute omapfb_attrs[] = {
store_overlays_rotate),
__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
- __ATTR(update_mode, S_IRUGO | S_IWUSR, show_upd_mode, store_upd_mode),
};
int omapfb_create_sysfs(struct omapfb2_device *fbdev)
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index fdf0edeccf4..aa1b1d97427 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -73,15 +73,6 @@ struct omapfb_info {
bool mirror;
};
-struct omapfb_display_data {
- struct omapfb2_device *fbdev;
- struct omap_dss_device *dssdev;
- u8 bpp_override;
- enum omapfb_update_mode update_mode;
- bool auto_update_work_enabled;
- struct delayed_work auto_update_work;
-};
-
struct omapfb2_device {
struct device *dev;
struct mutex mtx;
@@ -95,13 +86,17 @@ struct omapfb2_device {
struct omapfb2_mem_region regions[10];
unsigned num_displays;
- struct omapfb_display_data displays[10];
+ struct omap_dss_device *displays[10];
unsigned num_overlays;
struct omap_overlay *overlays[10];
unsigned num_managers;
struct omap_overlay_manager *managers[10];
- struct workqueue_struct *auto_update_wq;
+ unsigned num_bpp_overrides;
+ struct {
+ struct omap_dss_device *dssdev;
+ u8 bpp;
+ } bpp_overrides[10];
};
struct omapfb_colormode {
@@ -133,13 +128,6 @@ int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
u16 posx, u16 posy, u16 outw, u16 outh);
-void omapfb_start_auto_update(struct omapfb2_device *fbdev,
- struct omap_dss_device *display);
-void omapfb_stop_auto_update(struct omapfb2_device *fbdev,
- struct omap_dss_device *display);
-int omapfb_get_update_mode(struct fb_info *fbi, enum omapfb_update_mode *mode);
-int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
-
/* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{
@@ -155,19 +143,6 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
return NULL;
}
-static inline struct omapfb_display_data *get_display_data(
- struct omapfb2_device *fbdev, struct omap_dss_device *dssdev)
-{
- int i;
-
- for (i = 0; i < fbdev->num_displays; ++i)
- if (fbdev->displays[i].dssdev == dssdev)
- return &fbdev->displays[i];
-
- /* This should never happen */
- BUG();
-}
-
static inline void omapfb_lock(struct omapfb2_device *fbdev)
{
mutex_lock(&fbdev->mtx);