* [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Alexandre Courbot @ 2012-07-27 12:05 UTC (permalink / raw)
To: Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
Rob Herring, Greg Kroah-Hartman, Mark Brown, Arnd Bergmann
Cc: linux-tegra, linux-kernel, linux-fbdev, devicetree-discuss,
Alexandre Courbot
In-Reply-To: <1343390750-3642-1-git-send-email-acourbot@nvidia.com>
Some device drivers (panel backlights especially) need to follow precise
sequences for powering on and off, involving gpios, regulators, PWMs
with a precise powering order and delays to respect between each steps.
These sequences are board-specific, and do not belong to a particular
driver - therefore they have been performed by board-specific hook
functions to far.
With the advent of the device tree and of ARM kernels that are not
board-tied, we cannot rely on these board-specific hooks anymore but
need a way to implement these sequences in a portable manner. This patch
introduces a simple interpreter that can execute such power sequences
encoded either as platform data or within the device tree.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
Documentation/power/power_seq.txt | 120 +++++++++++++++
drivers/base/Kconfig | 4 +
drivers/base/Makefile | 1 +
drivers/base/power_seq.c | 300 ++++++++++++++++++++++++++++++++++++++
include/linux/power_seq.h | 139 ++++++++++++++++++
5 files changed, 564 insertions(+)
create mode 100644 Documentation/power/power_seq.txt
create mode 100644 drivers/base/power_seq.c
create mode 100644 include/linux/power_seq.h
diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
new file mode 100644
index 0000000..aa2ceb5
--- /dev/null
+++ b/Documentation/power/power_seq.txt
@@ -0,0 +1,120 @@
+Runtime Interpreted Power Sequences
+-----------------------------------
+
+Problem
+-------
+One very common board-dependent code is the out-of-driver code that is used to
+turn a device on or off. For instance, SoC boards very commonly use a GPIO
+(abstracted to a regulator or not) to control the power supply of a backlight,
+disabling it when the backlight is not used in order to save power. The GPIO
+that should be used, however, as well as the exact power sequence that may
+involve different resources, is board-dependent and thus unknown of the driver.
+
+This has been addressed so far by using hooks in the device's platform data that
+are called whenever the state of the device might reflect a power change. This
+approach, however, introduces board-dependant code into the kernel and is not
+compatible with the device tree.
+
+The Runtime Interpreted Power Sequences (or power sequences for short) aim at
+turning this code into platform data or device tree nodes. Power sequences are
+described using a simple format and run by a simple interpreter whenever needed.
+This allows to remove the callback mechanism and makes the kernel less
+board-dependant.
+
+Sequences Format
+----------------
+Power sequences are a series of sequential steps during which an action is
+performed on a resource. The supported resources so far are:
+- GPIOs
+- Regulators
+- PWMs
+
+Each step designates a resource and the following parameters:
+- Whether the step should enable or disable the resource,
+- Delay to wait before performing the action,
+- Delay to wait after performing the action.
+
+Both new resources and parameters can be introduced, but the goal is of course
+to keep things as simple and compact as possible.
+
+The platform data is a simple array of platform_power_seq_step instances, each
+instance describing a step. The type as well as one of id or gpio members
+(depending on the type) must be specified. The last step must be of type
+POWER_SEQ_STOP. Regulator and PWM resources are identified by name. GPIO are
+identified by number. For example, the following sequence will turn on the
+"power" regulator of the device, wait 10ms, and set GPIO number 110 to 1:
+
+struct platform_power_seq_step power_on_seq[] = {
+ {
+ .type = POWER_SEQ_REGULATOR,
+ .id = "power",
+ .params = {
+ .enable = 1,
+ .post_delay = 10,
+ },
+ },
+ {
+ .type = POWER_SEQ_GPIO,
+ .gpio = 110,
+ .params = {
+ .enable = 1,
+ },
+ },
+ {
+ .type = POWER_SEQ_STOP,
+ },
+};
+
+Usage by Drivers and Resources Management
+-----------------------------------------
+Power sequences make use of resources that must be properly allocated and
+managed. The power_seq_build() function takes care of resolving the resources as
+they are met in the sequence and to allocate them if needed:
+
+power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
+ platform_power_seq *pseq);
+
+You will need an instance of power_seq_resources to keep track of the resources
+that are already allocated. On success, the function returns a devm allocated
+resolved sequence that is ready to be passed to power_seq_run(). In case of
+failure, and error code is returned.
+
+A resolved power sequence returned by power_seq_build can be run by
+power_run_run():
+
+int power_seq_run(struct device *dev, power_seq *seq);
+
+It returns 0 if the sequence has successfully been run, or an error code if a
+problem occured.
+
+Finally, some resources that cannot be allocated through devm need to be freed
+manually. Therefore, be sure to call power_seq_free_resources() in your device
+remove function:
+
+void power_seq_free_resources(power_seq_resources *ress);
+
+Device tree
+-----------
+All the same, power sequences can be encoded as device tree nodes. The following
+properties and nodes are equivalent to the platform data defined previously:
+
+ power-supply = <&mydevice_reg>;
+ enable-gpio = <&gpio 6 0>;
+
+ power-on-sequence {
+ regulator@0 {
+ id = "power";
+ enable;
+ post-delay = <10>;
+ };
+ gpio@1 {
+ id = "enable-gpio";
+ enable;
+ };
+ };
+
+Note that first, the phandles of the regulator and gpio used in the sequences
+are defined as properties. Then the sequence references them through the id
+property of every step. The name of sub-properties defines the type of the step.
+Valid names are "regulator", "gpio" and "pwm". Steps must be numbered
+sequentially.
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 08b4c52..65bebfe 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -282,4 +282,8 @@ config CMA_AREAS
endif
+config POWER_SEQ
+ bool
+ default n
+
endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 5aa2d70..4c498c1 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
ifeq ($(CONFIG_SYSFS),y)
obj-$(CONFIG_MODULES) += module.o
endif
+obj-$(CONFIG_POWER_SEQ) += power_seq.o
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
obj-$(CONFIG_REGMAP) += regmap/
obj-$(CONFIG_SOC_BUS) += soc.o
diff --git a/drivers/base/power_seq.c b/drivers/base/power_seq.c
new file mode 100644
index 0000000..6ccefa1
--- /dev/null
+++ b/drivers/base/power_seq.c
@@ -0,0 +1,300 @@
+/*
+ * power_seq.c - A simple power sequence interpreter for platform devices
+ * and device tree.
+ *
+ * Author: Alexandre Courbot <acourbot@nvidia.com>
+ *
+ * Copyright (c) 2012 NVIDIA Corporation.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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/power_seq.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#endif
+
+static int power_seq_step_run(struct power_seq_step *step)
+{
+ int err = 0;
+
+ if (step->params.pre_delay)
+ mdelay(step->params.pre_delay);
+
+ switch (step->resource->type) {
+#ifdef CONFIG_REGULATOR
+ case POWER_SEQ_REGULATOR:
+ if (step->params.enable)
+ err = regulator_enable(step->resource->regulator);
+ else
+ err = regulator_disable(step->resource->regulator);
+ break;
+#endif
+#ifdef CONFIG_PWM
+ case POWER_SEQ_PWM:
+ if (step->params.enable)
+ err = pwm_enable(step->resource->pwm);
+ else
+ pwm_disable(step->resource->pwm);
+ break;
+#endif
+#ifdef CONFIG_GPIOLIB
+ case POWER_SEQ_GPIO:
+ gpio_set_value_cansleep(step->resource->gpio,
+ step->params.enable);
+ break;
+#endif
+ /*
+ * should never happen unless the sequence includes a step which
+ * type does not have support compiled in
+ */
+ default:
+ return -EINVAL;
+ }
+
+ if (err < 0)
+ return err;
+
+ if (step->params.post_delay)
+ mdelay(step->params.post_delay);
+
+ return 0;
+}
+
+int power_seq_run(struct device *dev, power_seq *seq)
+{
+ int err;
+
+ if (!seq) return 0;
+
+ while (seq->resource) {
+ if ((err = power_seq_step_run(seq++))) {
+ dev_err(dev, "error %d while running power sequence!\n",
+ err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(power_seq_run);
+
+#ifdef CONFIG_OF
+static int of_parse_power_seq_step(struct device *dev, struct device_node *node,
+ struct platform_power_seq_step *step)
+{
+ if (of_property_read_string(node, "id", &step->id)) {
+ dev_err(dev, "missing id property!\n");
+ return -EINVAL;
+ }
+
+ if (!strcmp(node->name, "regulator")) {
+ step->type = POWER_SEQ_REGULATOR;
+#ifdef CONFIG_OF_GPIO
+ } else if (!strcmp(node->name, "gpio")) {
+ int gpio;
+
+ step->type = POWER_SEQ_GPIO;
+ gpio = of_get_named_gpio(dev->of_node, step->id, 0);
+ if (gpio < 0) {
+ dev_err(dev, "cannot resolve gpio \"%s\"\n", step->id);
+ return gpio;
+ }
+ step->gpio = gpio;
+#endif /* CONFIG_OF_GPIO */
+ } else if (!strcmp(node->name, "pwm")) {
+ step->type = POWER_SEQ_PWM;
+ } else {
+ dev_err(dev, "invalid power seq step type!\n");
+ return -EINVAL;
+ }
+
+ if (of_find_property(node, "enable", NULL)) {
+ step->params.enable = 1;
+ } else if (!of_find_property(node, "disable", NULL)) {
+ dev_err(dev, "missing enable or disable property!\n");
+ return -EINVAL;
+ }
+
+ of_property_read_u32(node, "pre-delay", &step->params.pre_delay);
+ of_property_read_u32(node, "post-delay", &step->params.post_delay);
+
+ return 0;
+}
+
+platform_power_seq *of_parse_power_seq(struct device *dev,
+ struct device_node *node)
+{
+ struct device_node *child = NULL;
+ platform_power_seq *ret;
+ int cpt = 0;
+ int err;
+
+ if (!node) return NULL;
+
+ while ((child = of_get_next_child(node, child)))
+ cpt++;
+
+ /* allocate one more step to signal end of sequence */
+ ret = devm_kzalloc(dev, sizeof(*ret) * (cpt + 1), GFP_KERNEL);
+ if (!ret)
+ return ERR_PTR(-ENOMEM);
+
+ cpt = 0;
+ while ((child = of_get_next_child(node, child))) {
+ if ((err = of_parse_power_seq_step(dev, child, &ret[cpt++])))
+ return ERR_PTR(err);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_parse_power_seq);
+#endif /* CONFIG_OF */
+
+static
+struct power_seq_resource * power_seq_find_resource(power_seq_resources *ress,
+ struct platform_power_seq_step *res)
+{
+ struct power_seq_resource *step;
+
+ list_for_each_entry(step, ress, list) {
+ if (step->type != res->type) continue;
+ switch (res->type) {
+ case POWER_SEQ_GPIO:
+ if (step->gpio = res->gpio)
+ return step;
+ break;
+ default:
+ if (!strcmp(step->id, res->id))
+ return step;
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static int power_seq_allocate_resource(struct device *dev,
+ struct power_seq_resource *res)
+{
+ int err;
+
+ switch (res->type) {
+#ifdef CONFIG_REGULATOR
+ case POWER_SEQ_REGULATOR:
+ res->regulator = devm_regulator_get(dev, res->id);
+ if (IS_ERR(res->regulator)) {
+ dev_err(dev, "cannot get regulator \"%s\"\n", res->id);
+ return PTR_ERR(res->regulator);
+ }
+ break;
+#endif
+#ifdef CONFIG_PWM
+ case POWER_SEQ_PWM:
+ res->pwm = pwm_get(dev, res->id);
+ if (IS_ERR(res->pwm)) {
+ dev_err(dev, "cannot get pwm \"%s\"\n", res->id);
+ return PTR_ERR(res->pwm);
+ }
+ break;
+#endif
+#ifdef CONFIG_GPIOLIB
+ case POWER_SEQ_GPIO:
+ err = devm_gpio_request_one(dev, res->gpio, GPIOF_OUT_INIT_HIGH,
+ "backlight_gpio");
+ if (err) {
+ dev_err(dev, "cannot get gpio %d\n", res->gpio);
+ return err;
+ }
+ break;
+#endif
+ default:
+ dev_err(dev, "invalid resource type %d\n", res->type);
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
+ platform_power_seq *pseq)
+{
+ struct power_seq_step *seq = NULL, *ret;
+ struct power_seq_resource *res;
+ int cpt, err;
+
+ /* first pass to count the number of steps to allocate */
+ for (cpt = 0; pseq[cpt].type != POWER_SEQ_STOP; cpt++);
+
+ if (!cpt)
+ return seq;
+
+ /* 1 more for the STOP step */
+ ret = seq = devm_kzalloc(dev, sizeof(*seq) * (cpt + 1), GFP_KERNEL);
+ if (!seq)
+ return ERR_PTR(-ENOMEM);
+
+ for (; pseq->type != POWER_SEQ_STOP; pseq++, seq++) {
+ /* create resource node if not referenced already */
+ if (!(res = power_seq_find_resource(ress, pseq))) {
+ res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+ if (!res)
+ return ERR_PTR(-ENOMEM);
+ res->type = pseq->type;
+
+ if (res->type = POWER_SEQ_GPIO)
+ res->gpio = pseq->gpio;
+ else
+ res->id = pseq->id;
+
+ if ((err = power_seq_allocate_resource(dev, res)) < 0)
+ return ERR_PTR(err);
+
+ list_add(&res->list, ress);
+ }
+ seq->resource = res;
+ memcpy(&seq->params, &pseq->params, sizeof(seq->params));
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(power_seq_build);
+
+void power_seq_free_resources(power_seq_resources *ress) {
+ struct power_seq_resource *res;
+
+#ifdef CONFIG_PWM
+ list_for_each_entry(res, ress, list) {
+ if (res->type = POWER_SEQ_PWM)
+ pwm_put(res->pwm);
+ }
+#endif
+}
+EXPORT_SYMBOL_GPL(power_seq_free_resources);
+
+MODULE_AUTHOR("Alexandre Courbot <acourbot@nvidia.com>");
+MODULE_DESCRIPTION("Runtime Interpreted Power Sequences");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/power_seq.h b/include/linux/power_seq.h
new file mode 100644
index 0000000..da0593a
--- /dev/null
+++ b/include/linux/power_seq.h
@@ -0,0 +1,139 @@
+/*
+ * power_seq.h
+ *
+ * Simple interpreter for defining power sequences as platform data or device
+ * tree properties. Initially designed for use with backlight drivers.
+ *
+ * Power sequences are designed to replace the callbacks typically used in
+ * board-specific files that implement board-specific power sequences of devices
+ * such as backlights. A power sequence is an array of resources (which can a
+ * regulator, a GPIO, a PWM, ...) with an action to perform on it (enable or
+ * disable) and optional pre and post step delays. By having them interpreted
+ * instead of arbitrarily executed, it is possible to describe these in the
+ * device tree and thus remove board-specific code from the kernel.
+ *
+ * Author: Alexandre Courbot <acourbot@nvidia.com>
+ *
+ * Copyright (c) 2012 NVIDIA Corporation.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __LINUX_POWER_SEQ_H
+#define __LINUX_POWER_SEQ_H
+
+#include <linux/types.h>
+
+struct device;
+struct regulator;
+struct pwm_device;
+struct device_node;
+
+/**
+ * The different kinds of resources that can be controlled during the sequences.
+ */
+typedef enum {
+ POWER_SEQ_STOP = 0,
+ POWER_SEQ_REGULATOR,
+ POWER_SEQ_PWM,
+ POWER_SEQ_GPIO,
+ POWER_SEQ_MAX,
+} power_res_type;
+
+struct power_seq_resource {
+ power_res_type type;
+ /* name to resolve for resources with a name (regulator, pwm) */
+ const char *id;
+ /* resolved resource */
+ union {
+ struct regulator *regulator;
+ struct pwm_device *pwm;
+ int gpio;
+ };
+ /* used to maintain the list of resources used by the driver */
+ struct list_head list;
+};
+typedef struct list_head power_seq_resources;
+
+struct power_step_params {
+ /* enable the resource if 1, disable if 0 */
+ bool enable;
+ /* delay (in ms) to wait before executing the step */
+ int pre_delay;
+ /* delay (in ms) to wait after executing the step */
+ int post_delay;
+};
+
+/**
+ * Platform definition of power sequences. A sequence is an array of these,
+ * terminated by a STOP instance.
+ */
+struct platform_power_seq_step {
+ power_res_type type;
+ union {
+ /* Used by REGULATOR and PWM types to name the resource */
+ const char *id;
+ /* Used by GPIO */
+ int gpio;
+ };
+ struct power_step_params params;
+};
+typedef struct platform_power_seq_step platform_power_seq;
+
+/**
+ * Power sequence steps resolved against their resource. Built by
+ * power_seq_build and used to run the sequence.
+ */
+struct power_seq_step {
+ struct power_seq_resource *resource;
+ struct power_step_params params;
+};
+typedef struct power_seq_step power_seq;
+
+#ifdef CONFIG_OF
+/**
+ * Build a platform data sequence from a device tree node. Memory for the
+ * sequence is allocated using devm_kzalloc on dev.
+ */
+platform_power_seq *of_parse_power_seq(struct device *dev,
+ struct device_node *node);
+#else
+platform_power_seq *of_parse_power_seq(struct device *dev,
+ struct device_node *node)
+{
+ return NULL;
+}
+#endif
+
+/**
+ * Build a runnable power sequence from platform data, and add the resources
+ * it uses into ress. Memory for the sequence is allocated using devm_kzalloc
+ * on dev.
+ */
+power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
+ platform_power_seq *pseq);
+
+/**
+ * Free all the resources previously allocated by power_seq_allocate_resources.
+ */
+void power_seq_free_resources(power_seq_resources *ress);
+
+/**
+ * Run the given power sequence. Returns 0 on success, error code in case of
+ * failure.
+ */
+int power_seq_run(struct device *dev, power_seq *seq);
+
+#endif
--
1.7.11.3
^ permalink raw reply related
* [RFC][PATCH v3 2/3] pwm_backlight: use power sequences
From: Alexandre Courbot @ 2012-07-27 12:05 UTC (permalink / raw)
To: Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
Rob Herring, Greg Kroah-Hartman, Mark Brown, Arnd Bergmann
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Alexandre Courbot
In-Reply-To: <1343390750-3642-1-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Make use of the power sequences specified in the device tree or platform
data, if any.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
.../bindings/video/backlight/pwm-backlight.txt | 55 +++++-
drivers/video/backlight/Kconfig | 1 +
drivers/video/backlight/pwm_bl.c | 213 +++++++++++++++------
include/linux/pwm_backlight.h | 18 +-
4 files changed, 225 insertions(+), 62 deletions(-)
diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
index 1e4fc72..59abeba 100644
--- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
@@ -2,7 +2,6 @@ pwm-backlight bindings
Required properties:
- compatible: "pwm-backlight"
- - pwms: OF device-tree PWM specification (see PWM binding[0])
- brightness-levels: Array of distinct brightness levels. Typically these
are in the range from 0 to 255, but any range starting at 0 will do.
The actual brightness level (PWM duty cycle) will be interpolated
@@ -10,10 +9,22 @@ Required properties:
last value in the array represents a 100% duty cycle (brightest).
- default-brightness-level: the default brightness level (index into the
array defined by the "brightness-levels" property)
+ - pwms: OF device-tree PWM specification (see PWM binding[0]). Exactly one PWM
+ must be specified
+ - pwm-names: a list of names for the PWM devices specified in the
+ "pwms" property (see PWM binding[0])
+ - power-on-sequence: Power sequence that will bring the backlight on. This
+ sequence must reference the PWM specified in the pwms property by its
+ name. It can also reference extra GPIOs or regulators, and introduce
+ delays between sequence steps
+ - power-off-sequence: Power sequence that will bring the backlight off. This
+ sequence must reference the PWM specified in the pwms property by its
+ name. It can also reference extra GPIOs or regulators, and introduce
+ delays between sequence steps
Optional properties:
- - pwm-names: a list of names for the PWM devices specified in the
- "pwms" property (see PWM binding[0])
+ - *-supply: regulators used within a power sequence
+ - *-gpio: GPIOs used within a power sequence
[0]: Documentation/devicetree/bindings/pwm/pwm.txt
@@ -21,8 +32,42 @@ Example:
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 0 5000000>;
-
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <6>;
+
+ pwms = <&pwm 0 5000000>;
+ pwm-names = "backlight";
+ power-supply = <&backlight_reg>;
+ enable-gpio = <&gpio 6 0>;
+
+ power-on-sequence {
+ regulator@0 {
+ id = "power";
+ enable;
+ post-delay = <10>;
+ };
+ pwm@1 {
+ id = "backlight";
+ enable;
+ };
+ gpio@2 {
+ id = "enable-gpio";
+ enable;
+ };
+ };
+ power-off-sequence {
+ gpio@0 {
+ id = "enable-gpio";
+ disable;
+ };
+ pwm@1 {
+ id = "backlight";
+ disable;
+ };
+ regulator@2 {
+ id = "power";
+ disable;
+ pre-delay = <10>;
+ };
+ };
};
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index cf28276..6fb8aa3 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -246,6 +246,7 @@ config BACKLIGHT_CARILLO_RANCH
config BACKLIGHT_PWM
tristate "Generic PWM based Backlight Driver"
depends on PWM
+ select POWER_SEQ
help
If you have a LCD backlight adjustable by PWM, say Y to enable
this driver.
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 995f016..6e3a49e 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -27,6 +27,12 @@ struct pwm_bl_data {
unsigned int period;
unsigned int lth_brightness;
unsigned int *levels;
+ bool enabled;
+ power_seq_resources resources;
+ power_seq *power_on_seq;
+ power_seq *power_off_seq;
+
+ /* Legacy callbacks */
int (*notify)(struct device *,
int brightness);
void (*notify_after)(struct device *,
@@ -35,6 +41,34 @@ struct pwm_bl_data {
void (*exit)(struct device *);
};
+static void pwm_backlight_on(struct backlight_device *bl)
+{
+ struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
+ int ret;
+
+ if (pb->enabled)
+ return;
+
+ if ((ret = power_seq_run(pb->dev, pb->power_on_seq)) < 0)
+ dev_err(&bl->dev, "cannot run power on sequence\n");
+
+ pb->enabled = true;
+}
+
+static void pwm_backlight_off(struct backlight_device *bl)
+{
+ struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
+ int ret;
+
+ if (!pb->enabled)
+ return;
+
+ if ((ret = power_seq_run(pb->dev, pb->power_off_seq)) < 0)
+ dev_err(&bl->dev, "cannot run power off sequence\n");
+
+ pb->enabled = false;
+}
+
static int pwm_backlight_update_status(struct backlight_device *bl)
{
struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
@@ -51,8 +85,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
brightness = pb->notify(pb->dev, brightness);
if (brightness = 0) {
- pwm_config(pb->pwm, 0, pb->period);
- pwm_disable(pb->pwm);
+ pwm_backlight_off(bl);
} else {
int duty_cycle;
@@ -66,7 +99,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
duty_cycle = pb->lth_brightness +
(duty_cycle * (pb->period - pb->lth_brightness) / max);
pwm_config(pb->pwm, duty_cycle, pb->period);
- pwm_enable(pb->pwm);
+ pwm_backlight_on(bl);
}
if (pb->notify_after)
@@ -145,12 +178,16 @@ static int pwm_backlight_parse_dt(struct device *dev,
data->max_brightness--;
}
- /*
- * TODO: Most users of this driver use a number of GPIOs to control
- * backlight power. Support for specifying these needs to be
- * added.
- */
+ data->power_on_seq = of_parse_power_seq(dev, of_find_node_by_name(node,
+ "power-on-sequence"));
+ if (IS_ERR(data->power_on_seq))
+ return PTR_ERR(data->power_on_seq);
+ data->power_off_seq = of_parse_power_seq(dev, of_find_node_by_name(node,
+ "power-off-sequence"));
+ if (IS_ERR(data->power_off_seq))
+ return PTR_ERR(data->power_off_seq);
+ data->use_power_sequences = true;
return 0;
}
@@ -168,73 +205,141 @@ static int pwm_backlight_parse_dt(struct device *dev,
}
#endif
+/**
+ * Construct the power sequences corresponding to the legacy platform data.
+ */
+static int pwm_backlight_legacy_probe(struct platform_device *pdev,
+ struct pwm_bl_data *pb)
+{
+ struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct power_seq_resource *res;
+ struct power_seq_step *step;
+
+ pb->pwm = pwm_get(dev, NULL);
+ if (IS_ERR(pb->pwm)) {
+ dev_warn(dev, "unable to request PWM, trying legacy API\n");
+
+ pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
+ if (IS_ERR(pb->pwm)) {
+ dev_err(dev, "unable to request legacy PWM\n");
+ return PTR_ERR(pb->pwm);
+ }
+ pwm_set_period(pb->pwm, data->pwm_period_ns);
+ }
+
+ pb->notify = data->notify;
+ pb->notify_after = data->notify_after;
+ pb->check_fb = data->check_fb;
+ pb->exit = data->exit;
+ pb->dev = dev;
+
+ /* Now build the resources and sequences corresponding to this PWM */
+ res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+ if (!res) return -ENOMEM;
+ res->type = POWER_SEQ_PWM;
+ res->id = "pwm-backlight";
+ res->pwm = pb->pwm;
+ list_add(&res->list, &pb->resources);
+
+ /* allocate both power on and off sequences at the same time */
+ step = devm_kzalloc(dev, sizeof(*step) * 4, GFP_KERNEL);
+ if (!step) return -ENOMEM;
+ step->resource = res;
+ memcpy(&step[2], &step[0], sizeof(*step));
+ step[0].params.enable = 1;
+ pb->power_on_seq = &step[0];
+ pb->power_off_seq = &step[2];
+
+ return 0;
+}
+
static int pwm_backlight_probe(struct platform_device *pdev)
{
struct platform_pwm_backlight_data *data = pdev->dev.platform_data;
struct platform_pwm_backlight_data defdata;
+ struct power_seq_resource *res;
struct backlight_properties props;
struct backlight_device *bl;
struct pwm_bl_data *pb;
unsigned int max;
int ret;
+ pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
+ if (!pb) {
+ dev_err(&pdev->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&pb->resources);
+
+ /* using new interface or device tree */
if (!data) {
+ /* build platform data from device tree */
ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
- if (ret < 0) {
+ if (ret = -EPROBE_DEFER) {
+ return ret;
+ } else if (ret < 0) {
dev_err(&pdev->dev, "failed to find platform data\n");
return ret;
}
-
data = &defdata;
}
- if (data->init) {
- ret = data->init(&pdev->dev);
+ if (!data->use_power_sequences) {
+ /* using legacy interface */
+ ret = pwm_backlight_legacy_probe(pdev, pb);
if (ret < 0)
return ret;
+ } else {
+ /* build sequences and allocate resources from platform data */
+ if (data->power_on_seq) {
+ pb->power_on_seq = power_seq_build(&pdev->dev,
+ &pb->resources,
+ data->power_on_seq);
+ if (IS_ERR(pb->power_on_seq))
+ return PTR_ERR(pb->power_on_seq);
+ }
+ if (data->power_off_seq) {
+ pb->power_off_seq = power_seq_build(&pdev->dev,
+ &pb->resources,
+ data->power_off_seq);
+ if (IS_ERR(pb->power_off_seq))
+ return PTR_ERR(pb->power_off_seq);
+ }
+
+ /* we must have exactly one PWM for this driver */
+ list_for_each_entry(res, &pb->resources, list) {
+ if (res->type != POWER_SEQ_PWM)
+ continue;
+ if (pb->pwm) {
+ dev_err(&pdev->dev, "more than one PWM used\n");
+ return -EINVAL;
+ }
+ /* keep the pwm at hand */
+ pb->pwm = res->pwm;
+ }
}
- pb = devm_kzalloc(&pdev->dev, sizeof(*pb), GFP_KERNEL);
- if (!pb) {
- dev_err(&pdev->dev, "no memory for state\n");
- ret = -ENOMEM;
- goto err_alloc;
+ /* from here we should have a PWM */
+ if (!pb->pwm) {
+ dev_err(&pdev->dev, "no PWM defined!\n");
+ return -EINVAL;
+ }
+
+ if (data->init) {
+ ret = data->init(&pdev->dev);
+ if (ret < 0)
+ goto err;
}
if (data->levels) {
max = data->levels[data->max_brightness];
pb->levels = data->levels;
- } else
+ } else {
max = data->max_brightness;
-
- pb->notify = data->notify;
- pb->notify_after = data->notify_after;
- pb->check_fb = data->check_fb;
- pb->exit = data->exit;
- pb->dev = &pdev->dev;
-
- pb->pwm = pwm_get(&pdev->dev, NULL);
- if (IS_ERR(pb->pwm)) {
- dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
-
- pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
- if (IS_ERR(pb->pwm)) {
- dev_err(&pdev->dev, "unable to request legacy PWM\n");
- ret = PTR_ERR(pb->pwm);
- goto err_alloc;
- }
}
- dev_dbg(&pdev->dev, "got pwm for backlight\n");
-
- /*
- * The DT case will set the pwm_period_ns field to 0 and store the
- * period, parsed from the DT, in the PWM device. For the non-DT case,
- * set the period from platform data.
- */
- if (data->pwm_period_ns > 0)
- pwm_set_period(pb->pwm, data->pwm_period_ns);
-
pb->period = pwm_get_period(pb->pwm);
pb->lth_brightness = data->lth_brightness * (pb->period / max);
@@ -246,20 +351,20 @@ static int pwm_backlight_probe(struct platform_device *pdev)
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
ret = PTR_ERR(bl);
- goto err_bl;
+ goto err;
}
bl->props.brightness = data->dft_brightness;
backlight_update_status(bl);
platform_set_drvdata(pdev, bl);
+
return 0;
-err_bl:
- pwm_put(pb->pwm);
-err_alloc:
+err:
if (data->exit)
data->exit(&pdev->dev);
+ power_seq_free_resources(&pb->resources);
return ret;
}
@@ -269,9 +374,9 @@ static int pwm_backlight_remove(struct platform_device *pdev)
struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
backlight_device_unregister(bl);
- pwm_config(pb->pwm, 0, pb->period);
- pwm_disable(pb->pwm);
- pwm_put(pb->pwm);
+ pwm_backlight_off(bl);
+ power_seq_free_resources(&pb->resources);
+
if (pb->exit)
pb->exit(&pdev->dev);
return 0;
@@ -285,8 +390,7 @@ static int pwm_backlight_suspend(struct device *dev)
if (pb->notify)
pb->notify(pb->dev, 0);
- pwm_config(pb->pwm, 0, pb->period);
- pwm_disable(pb->pwm);
+ pwm_backlight_off(bl);
if (pb->notify_after)
pb->notify_after(pb->dev, 0);
return 0;
@@ -323,4 +427,3 @@ module_platform_driver(pwm_backlight_driver);
MODULE_DESCRIPTION("PWM based Backlight Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pwm-backlight");
-
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index 56f4a86..3e8bd2c 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -5,14 +5,28 @@
#define __LINUX_PWM_BACKLIGHT_H
#include <linux/backlight.h>
+#include <linux/power_seq.h>
struct platform_pwm_backlight_data {
- int pwm_id;
unsigned int max_brightness;
unsigned int dft_brightness;
unsigned int lth_brightness;
- unsigned int pwm_period_ns;
unsigned int *levels;
+ /* Set this to true otherwise the legacy interface will be used */
+ bool use_power_sequences;
+ /*
+ * New interface - arrays of steps terminated by a STOP instance, or
+ * NULL if unused.
+ */
+ struct platform_power_seq_step *power_on_seq;
+ struct platform_power_seq_step *power_off_seq;
+ /*
+ * Legacy interface - single PWM and callback methods to control
+ * the power sequence. pwm_id and pwm_period_ns need only be specified
+ * if get_pwm(dev, NULL) will return NULL.
+ */
+ int pwm_id;
+ unsigned int pwm_period_ns;
int (*init)(struct device *dev);
int (*notify)(struct device *dev, int brightness);
void (*notify_after)(struct device *dev, int brightness);
--
1.7.11.3
^ permalink raw reply related
* [RFC][PATCH v3 3/3] tegra: add pwm backlight device tree nodes
From: Alexandre Courbot @ 2012-07-27 12:05 UTC (permalink / raw)
To: Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
Rob Herring, Greg Kroah-Hartman, Mark Brown, Arnd Bergmann
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Alexandre Courbot
In-Reply-To: <1343390750-3642-1-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
arch/arm/boot/dts/tegra20-ventana.dts | 53 +++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/tegra20.dtsi | 2 +-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index be90544..6acdb6d 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -317,6 +317,59 @@
bus-width = <8>;
};
+ backlight {
+ compatible = "pwm-backlight";
+ brightness-levels = <0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 255>;
+ default-brightness-level = <12>;
+
+ pwms = <&pwm 2 5000000>;
+ pwm-names = "backlight";
+ power-supply = <&backlight_reg>;
+ enable-gpio = <&gpio 28 0>;
+
+ power-on-sequence {
+ regulator@0 {
+ id = "power";
+ enable;
+ post-delay = <10>;
+ };
+ pwm@1 {
+ id = "backlight";
+ enable;
+ };
+ gpio@2 {
+ id = "enable-gpio";
+ enable;
+ };
+ };
+ power-off-sequence {
+ gpio@0 {
+ id = "enable-gpio";
+ disable;
+ };
+ pwm@1 {
+ id = "backlight";
+ disable;
+ };
+ regulator@2 {
+ id = "power";
+ disable;
+ pre-delay = <10>;
+ };
+ };
+ };
+
+ backlight_reg: fixedregulator@176 {
+ compatible = "regulator-fixed";
+ regulator-name = "backlight_regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio 176 0>;
+ startup-delay-us = <0>;
+ enable-active-high;
+ regulator-boot-off;
+ };
+
sound {
compatible = "nvidia,tegra-audio-wm8903-ventana",
"nvidia,tegra-audio-wm8903";
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 405d167..67a6cd9 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -123,7 +123,7 @@
status = "disabled";
};
- pwm {
+ pwm: pwm {
compatible = "nvidia,tegra20-pwm";
reg = <0x7000a000 0x100>;
#pwm-cells = <2>;
--
1.7.11.3
^ permalink raw reply related
* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Greg Kroah-Hartman @ 2012-07-27 18:19 UTC (permalink / raw)
To: Alexandre Courbot
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Mark Brown, Stephen Warren,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1343390750-3642-2-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
>
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
> Documentation/power/power_seq.txt | 120 +++++++++++++++
> drivers/base/Kconfig | 4 +
> drivers/base/Makefile | 1 +
> drivers/base/power_seq.c | 300 ++++++++++++++++++++++++++++++++++++++
> include/linux/power_seq.h | 139 ++++++++++++++++++
What's wrong with drivers/power/? I sure don't want to maintain this
code, and it seems to not be part of the "driver core" infrastructure.
thanks,
greg k-h
^ permalink raw reply
* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Greg Kroah-Hartman @ 2012-07-27 18:20 UTC (permalink / raw)
To: Alexandre Courbot
Cc: Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
Rob Herring, Mark Brown, Arnd Bergmann,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <1343390750-3642-2-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
> +++ b/include/linux/power_seq.h
> @@ -0,0 +1,139 @@
> +/*
> + * power_seq.h
> + *
> + * Simple interpreter for defining power sequences as platform data or device
> + * tree properties. Initially designed for use with backlight drivers.
> + *
> + * Power sequences are designed to replace the callbacks typically used in
> + * board-specific files that implement board-specific power sequences of devices
> + * such as backlights. A power sequence is an array of resources (which can a
> + * regulator, a GPIO, a PWM, ...) with an action to perform on it (enable or
> + * disable) and optional pre and post step delays. By having them interpreted
> + * instead of arbitrarily executed, it is possible to describe these in the
> + * device tree and thus remove board-specific code from the kernel.
> + *
> + * Author: Alexandre Courbot <acourbot@nvidia.com>
> + *
> + * Copyright (c) 2012 NVIDIA Corporation.
> + *
> + * 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; version 2 of the License.
> + *
> + * 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.
As I always say:
Unless you want to track the office movements of the FSF for the
next 40 years, and keep this file up to date, drop that last
paragraph, it's pointless.
^ permalink raw reply
* Re: [PATCH v2] da8xx-fb: add missing FB_BLANK operations
From: Florian Tobias Schandinat @ 2012-07-29 21:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1341583288-30281-1-git-send-email-yegorslists@googlemail.com>
On 07/06/2012 02:01 PM, yegorslists@googlemail.com wrote:
> From: Yegor Yefremov <yegorslists@googlemail.com>
>
> add FB_BLANK_NORMAL, FB_BLANK_VSYNC_SUSPEND and FB_BLANK_HSYNC_SUSPEND
> modes (copy drivers/video/omap2/omapfb/omapfb-main.c implementation).
> Otherwise X-server will complain about invalid parameter.
>
> Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> v2: add linux-fbdev as recipient
>
> drivers/video/da8xx-fb.c | 3 +++
> 1 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 47118c7..8d745bf 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -1026,6 +1026,9 @@ static int cfb_blank(int blank, struct fb_info *info)
>
> lcd_enable_raster();
> break;
> + case FB_BLANK_NORMAL:
> + case FB_BLANK_VSYNC_SUSPEND:
> + case FB_BLANK_HSYNC_SUSPEND:
> case FB_BLANK_POWERDOWN:
> if (par->panel_power_ctrl)
> par->panel_power_ctrl(0);
^ permalink raw reply
* Re: [PATCH RESEND] video: da8xx-fb rev2: fix disabling of palette completion interrupt
From: Florian Tobias Schandinat @ 2012-07-29 21:05 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1342624871-5947-1-git-send-email-prakash.pm@ti.com>
On 07/18/2012 03:21 PM, Manjunathappa, Prakash wrote:
> Writing '1' to particular bit of IRQENABLE_CLEAR register disables the
> corresponding interrupt on revision 2 LCDC. This register was wrongly
> configured to disable all previous enabled interrupts instead of
> disabling only palette completion interrupt. Patch fixes it by clearing
> only palette completion interrupt bit.
>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> Resending as my earlier patch seems like not reached fbdev mailing list.
>
> drivers/video/da8xx-fb.c | 7 ++-----
> 1 files changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 47118c7..88e98ea 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -715,7 +715,6 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
> {
> struct da8xx_fb_par *par = arg;
> u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
> - u32 reg_int;
>
> if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
> lcd_disable_raster();
> @@ -732,10 +731,8 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
>
> lcdc_write(stat, LCD_MASKED_STAT_REG);
>
> - /* Disable PL completion inerrupt */
> - reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
> - (LCD_V2_PL_INT_ENA);
> - lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);
> + /* Disable PL completion interrupt */
> + lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG);
>
> /* Setup and start data loading mode */
> lcd_blit(LOAD_DATA, par);
^ permalink raw reply
* Re: [PATCH RESEND] video: da8xx-fb: fix flicker due to 1 frame delay in updated frame
From: Florian Tobias Schandinat @ 2012-07-29 21:06 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1342625516-7185-1-git-send-email-prakash.pm@ti.com>
On 07/18/2012 03:31 PM, Manjunathappa, Prakash wrote:
> Flicker/tearing effect is observed with current FB driver.
> Issue is because of 2 active DMA channels ping ponging among them
> along with usage of 2 DDR ping pong buffers in driver. Application
> unaware of active DMA channel keeps updating frame being displayed,
> this leads to tearing effect.
> Below steps describes the issue:
> 1)Initially assume both buffers FB0 and FB1 are programmed for buffer-0.
> 2)On EOF0: Program FB0 for buffer-1, indicate(wake up) application
> to fill up buffer-0. As FB1 is active and continues to DMA buffer-0
> (which is being filled), leading to tearing/flickering issue.
> 3)On EOF1: Program FB1 for buffer-0, indicate(wake up) application to
> fill up buffer-1. As FB0 is active and continues to DMA buffer-1(which
> is being filled), leading to tearing/flickering issue.
> 4)On EOF0: Program FB0 for buffer-1, indicate(wake up) application to
> fill up buffer-0. As FB1 is active and continues to DMA buffer-0(which is
> being filled), leading to tearing/flickering issue.
> ...
> Above steps depict that issue is because of 1 frame delay in frame
> panned by application.
>
> Patch fixes the issue by keeping track free DMA channel and configures
> it in drivers PAN callback so that panned frame from application gets
> displayed in next frame period.
>
> Wiki below describes the issue in detail and it also has link to
> application with which issue can be reproduced.
> http://processors.wiki.ti.com/index.php/DA8xx_LCDC_Linux_FB_FAQs
>
> Signed-off-by: Nellutla, Aditya <aditya.n@ti.com>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> Resending as my earlier patch seems like not reached fbdev mailing list.
>
> drivers/video/da8xx-fb.c | 30 ++++++++++++++++++++++++++++++
> 1 files changed, 30 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index e9d2f6e..183366d 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -30,6 +30,7 @@
> #include <linux/clk.h>
> #include <linux/cpufreq.h>
> #include <linux/console.h>
> +#include <linux/spinlock.h>
> #include <linux/slab.h>
> #include <video/da8xx-fb.h>
> #include <asm/div64.h>
> @@ -161,6 +162,13 @@ struct da8xx_fb_par {
> wait_queue_head_t vsync_wait;
> int vsync_flag;
> int vsync_timeout;
> + spinlock_t lock_for_chan_update;
> +
> + /*
> + * LCDC has 2 ping pong DMA channels, channel 0
> + * and channel 1.
> + */
> + unsigned int which_dma_channel_done;
> #ifdef CONFIG_CPU_FREQ
> struct notifier_block freq_transition;
> unsigned int lcd_fck_rate;
> @@ -741,6 +749,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
> lcdc_write(stat, LCD_MASKED_STAT_REG);
>
> if (stat & LCD_END_OF_FRAME0) {
> + par->which_dma_channel_done = 0;
> lcdc_write(par->dma_start,
> LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
> lcdc_write(par->dma_end,
> @@ -750,6 +759,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
> }
>
> if (stat & LCD_END_OF_FRAME1) {
> + par->which_dma_channel_done = 1;
> lcdc_write(par->dma_start,
> LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
> lcdc_write(par->dma_end,
> @@ -796,6 +806,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
> lcdc_write(stat, LCD_STAT_REG);
>
> if (stat & LCD_END_OF_FRAME0) {
> + par->which_dma_channel_done = 0;
> lcdc_write(par->dma_start,
> LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
> lcdc_write(par->dma_end,
> @@ -805,6 +816,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
> }
>
> if (stat & LCD_END_OF_FRAME1) {
> + par->which_dma_channel_done = 1;
> lcdc_write(par->dma_start,
> LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
> lcdc_write(par->dma_end,
> @@ -1050,6 +1062,7 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
> struct fb_fix_screeninfo *fix = &fbi->fix;
> unsigned int end;
> unsigned int start;
> + unsigned long irq_flags;
>
> if (var->xoffset != fbi->var.xoffset ||
> var->yoffset != fbi->var.yoffset) {
> @@ -1067,6 +1080,21 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
> end = start + fbi->var.yres * fix->line_length - 1;
> par->dma_start = start;
> par->dma_end = end;
> + spin_lock_irqsave(&par->lock_for_chan_update,
> + irq_flags);
> + if (par->which_dma_channel_done = 0) {
> + lcdc_write(par->dma_start,
> + LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
> + lcdc_write(par->dma_end,
> + LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
> + } else if (par->which_dma_channel_done = 1) {
> + lcdc_write(par->dma_start,
> + LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
> + lcdc_write(par->dma_end,
> + LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
> + }
> + spin_unlock_irqrestore(&par->lock_for_chan_update,
> + irq_flags);
> }
> }
>
> @@ -1294,6 +1322,8 @@ static int __devinit fb_probe(struct platform_device *device)
> /* initialize the vsync wait queue */
> init_waitqueue_head(&par->vsync_wait);
> par->vsync_timeout = HZ / 5;
> + par->which_dma_channel_done = -1;
> + spin_lock_init(&par->lock_for_chan_update);
>
> /* Register the Frame Buffer */
> if (register_framebuffer(da8xx_fb_info) < 0) {
^ permalink raw reply
* Re: [PATCH v2 1/2] video: da8xx-fb: configure FIFO threshold to reduce underflow errors
From: Florian Tobias Schandinat @ 2012-07-29 21:07 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1342625616-7393-1-git-send-email-prakash.pm@ti.com>
On 07/18/2012 03:33 PM, Manjunathappa, Prakash wrote:
> Patch works around the below silicon errata:
> During LCDC initialization, there is the potential for a FIFO
> underflow condition to occur. A FIFO underflow condition
> occurs when the input FIFO is completely empty and the LCDC
> raster controller logic that drives data to the output pins
> attempts to fetch data from the FIFO. When a FIFO underflow
> condition occurs, incorrect data will be driven out on the
> LCDC data pins.
>
> Software should poll the FUF bit field in the LCD_STAT register
> to check if an error condition has occurred or service the
> interrupt if FUF_EN is enabled when FUF occurs. If the FUF bit
> field has been set to 1, this will indicate an underflow
> condition has occurred and then the software should execute a
> reset of the LCDC via the LPSC.
>
> This problem may occur if the LCDC FIFO threshold size
> (LCDDMA_CTRL[TH_FIFO_READY]) is left at its default value after
> reset. Increasing the FIFO threshold size will reduce or
> eliminate underflows. Setting the threshold size to 256 double
> words or larger is recommended.
>
> Above issue is described in section 2.1.3 of silicon errata
> http://www.ti.com/lit/er/sprz313e/sprz313e.pdf
>
> Signed-off-by: Rajashekhara, Sudhakar <sudhakar.raj@ti.com>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Applied both patches of this series.
Thanks,
Florian Tobias Schandinat
> ---
> Seems like version 1 of this patch did not reach fbdev mailing list.
> Since v1:
> Removed clk_disable/clk_enable from error interrupt handling code.
>
> drivers/video/da8xx-fb.c | 11 +++++++----
> include/video/da8xx-fb.h | 3 +++
> 2 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 183366d..186ab5a 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -353,8 +353,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
> lcd_enable_raster();
> }
>
> -/* Configure the Burst Size of DMA */
> -static int lcd_cfg_dma(int burst_size)
> +/* Configure the Burst Size and fifo threhold of DMA */
> +static int lcd_cfg_dma(int burst_size, int fifo_th)
> {
> u32 reg;
>
> @@ -378,6 +378,9 @@ static int lcd_cfg_dma(int burst_size)
> default:
> return -EINVAL;
> }
> +
> + reg |= (fifo_th << 8);
> +
> lcdc_write(reg, LCD_DMA_CTRL_REG);
>
> return 0;
> @@ -679,8 +682,8 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
> lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
> ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
>
> - /* Configure the DMA burst size. */
> - ret = lcd_cfg_dma(cfg->dma_burst_sz);
> + /* Configure the DMA burst size and fifo threshold. */
> + ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th);
> if (ret < 0)
> return ret;
>
> diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
> index 89d43b3..5a0e4f9 100644
> --- a/include/video/da8xx-fb.h
> +++ b/include/video/da8xx-fb.h
> @@ -82,6 +82,9 @@ struct lcd_ctrl_config {
>
> /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
> unsigned char raster_order;
> +
> + /* DMA FIFO threshold */
> + int fifo_th;
> };
>
> struct lcd_sync_arg {
^ permalink raw reply
* Re: [PATCH] video: da8xx-fb: do clock reset of revision 2 LCDC before enabling
From: Florian Tobias Schandinat @ 2012-07-29 21:14 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1342799471-10729-1-git-send-email-prakash.pm@ti.com>
On 07/20/2012 03:51 PM, Manjunathappa, Prakash wrote:
> As in specification software reset should be applied for several
> cycles before bringing it out of reset. Without this patch
> particularly during suspend and resume clock reset is not guaranteed
> to happen.
>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Applied. But it would be better if you made the patch dependencies
clear, as I didn't consider some of your patches mature enough for this
merge window. Now I had to figure out why my final build failed and
applied the patch below.
Best regards,
Florian Tobias Schandinat
---
commit a0239073fd75489d25575cf3aaf71ab55b416020
Author: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Date: Sun Jul 29 16:47:40 2012 +0000
da8xx-fb: fix compile issue due to missing include
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index ca9943a..7ae9d53 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -32,6 +32,7 @@
#include <linux/console.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/lcm.h>
#include <video/da8xx-fb.h>
#include <asm/div64.h>
> ---
> drivers/video/da8xx-fb.c | 12 ++++++++----
> 1 files changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 3d2d0d1..4440292 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -262,10 +262,18 @@ static inline void lcd_enable_raster(void)
> {
> u32 reg;
>
> + /* Put LCDC in reset for several cycles */
> + if (lcd_revision = LCD_VERSION_2)
> + /* Write 1 to reset LCDC */
> + lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
> + mdelay(1);
> +
> /* Bring LCDC out of reset */
> if (lcd_revision = LCD_VERSION_2)
> lcdc_write(0, LCD_CLK_RESET_REG);
> + mdelay(1);
>
> + /* Above reset sequence doesnot reset register context */
> reg = lcdc_read(LCD_RASTER_CTRL_REG);
> if (!(reg & LCD_RASTER_ENABLE))
> lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
> @@ -279,10 +287,6 @@ static inline void lcd_disable_raster(void)
> reg = lcdc_read(LCD_RASTER_CTRL_REG);
> if (reg & LCD_RASTER_ENABLE)
> lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
> -
> - if (lcd_revision = LCD_VERSION_2)
> - /* Write 1 to reset LCDC */
> - lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
> }
>
> static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
^ permalink raw reply related
* Re: [PATCH] video: exynos mipi dsi: Fix mipi dsi regulators handling issue
From: Florian Tobias Schandinat @ 2012-07-29 21:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <500CB61A.6000106@samsung.com>
On 07/23/2012 02:25 AM, Donghwa Lee wrote:
> When FB_BLANK_UNLANK event occured, exynos mipi dsi regulators have to turn on.
>
> Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
> Signed-off-by: Inki Dae <inki.dae@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/exynos/exynos_mipi_dsi.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
> index 6c1f5c3..9390640 100644
> --- a/drivers/video/exynos/exynos_mipi_dsi.c
> +++ b/drivers/video/exynos/exynos_mipi_dsi.c
> @@ -154,7 +154,7 @@ static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
> if (client_drv && client_drv->power_on)
> client_drv->power_on(client_dev, 1);
>
> - exynos_mipi_regulator_disable(dsim);
> + exynos_mipi_regulator_enable(dsim);
>
> /* enable MIPI-DSI PHY. */
> if (dsim->pd->phy_enable)
^ permalink raw reply
* Re: [PATCH] da8xx-fb: do not turn ON LCD backlight unless LCDC is enabled
From: Florian Tobias Schandinat @ 2012-07-29 21:16 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1343103325-7313-1-git-send-email-prakash.pm@ti.com>
On 07/24/2012 04:15 AM, Manjunathappa, Prakash wrote:
> LCD blink is observed during suspend/resume and blank/unblank
> operations as backlight is ON during LCDC disable and enable.
> So make sure to turn OFF backlight before disabling and turn
> it ON after enabling.
>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
> drivers/video/da8xx-fb.c | 9 +++++----
> 1 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 0fb4d7d..1a569ae 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -1056,10 +1056,10 @@ static int cfb_blank(int blank, struct fb_info *info)
> par->blank = blank;
> switch (blank) {
> case FB_BLANK_UNBLANK:
> + lcd_enable_raster();
> +
> if (par->panel_power_ctrl)
> par->panel_power_ctrl(1);
> -
> - lcd_enable_raster();
> break;
> case FB_BLANK_POWERDOWN:
> if (par->panel_power_ctrl)
> @@ -1417,11 +1417,12 @@ static int fb_resume(struct platform_device *dev)
> struct da8xx_fb_par *par = info->par;
>
> console_lock();
> + clk_enable(par->lcdc_clk);
> + lcd_enable_raster();
> +
> if (par->panel_power_ctrl)
> par->panel_power_ctrl(1);
>
> - clk_enable(par->lcdc_clk);
> - lcd_enable_raster();
> fb_set_suspend(info, 0);
> console_unlock();
>
^ permalink raw reply
* Re: [PATCH] fbdev: Make pixel_to_pat() failure mode more friendly
From: Florian Tobias Schandinat @ 2012-07-29 21:16 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1343117953.3715.23.camel@pasglop>
On 07/24/2012 08:19 AM, Benjamin Herrenschmidt wrote:
> If we accidentally pass an incorrect bpp value to pixel_to_pat(),
> it panics. This is pretty useless, as we generally have the various
> console locks held at that point, so nothing will be displayed,
> and there is no reason to make this a fatal event.
>
> Let's WARN instead.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Applied.
Thanks,
Florian Tobias Schandinat
> ---
>
> diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
> index 04c01fa..624ee11 100644
> --- a/drivers/video/fb_draw.h
> +++ b/drivers/video/fb_draw.h
> @@ -3,6 +3,7 @@
>
> #include <asm/types.h>
> #include <linux/fb.h>
> +#include <linux/bug.h>
>
> /*
> * Compose two values, using a bitmask as decision value
> @@ -41,7 +42,8 @@ pixel_to_pat( u32 bpp, u32 pixel)
> case 32:
> return 0x0000000100000001ul*pixel;
> default:
> - panic("pixel_to_pat(): unsupported pixelformat\n");
> + WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp);
> + return 0;
> }
> }
> #else
> @@ -66,7 +68,8 @@ pixel_to_pat( u32 bpp, u32 pixel)
> case 32:
> return 0x00000001ul*pixel;
> default:
> - panic("pixel_to_pat(): unsupported pixelformat\n");
> + WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp);
> + return 0;
> }
> }
> #endif
>
>
>
^ permalink raw reply
* Re: [GIT PULL] SH Mobile LCDC and MERAM patches
From: Florian Tobias Schandinat @ 2012-07-29 21:16 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <2980452.38e8VA4mF5@avalon>
On 07/26/2012 05:26 PM, Laurent Pinchart wrote:
> Hi Florian,
>
> On Thursday 26 July 2012 17:14:33 Florian Tobias Schandinat wrote:
>> On 07/24/2012 09:16 AM, Laurent Pinchart wrote:
>>> Hi Florian,
>>>
>>> The following changes since commit
> 6fcdbc0c3a683003a00f383fceac80da1b7852ff:
>>> s3fb: Add Virge/MX (86C260) (2012-07-08 14:03:50 +0000)
>>>
>>> are available in the git repository at:
>>> git://linuxtv.org/pinchartl/fbdev.git for-next
>>
>> Merged. Should I also apply your followup patch
>> "[PATCH] fbdev: sh_mobile_lcdc: Fix vertical panning step"
>> ?
>
> I was planning to send a pull request for that one, but yes, please merge it
> :-)
Applied.
Thanks,
Florian Tobias Schandinat
^ permalink raw reply
* Re: [PATCH v3] video: da8xx-fb: add 24bpp LCD configuration support
From: Florian Tobias Schandinat @ 2012-07-29 21:37 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1342712266-4381-1-git-send-email-prakash.pm@ti.com>
Hi,
On 07/23/2012 08:26 AM, Manjunathappa, Prakash wrote:
> Hi,
>
> On Thu, Jul 19, 2012 at 21:07:46, Manjunathappa, Prakash wrote:
>> LCD controller on am335x supports 24bpp raster configuration in addition
>> to ones on da850. LCDC also supports 24bpp in unpacked format having
>> ARGB:8888 32bpp format data in DDR, but it doesn't interpret alpha
>> component of the data.
>>
>> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
>> Cc: Anatolij Gustschin <agust@denx.de>
>> ---
>> Since v2:
>> Fixed additional configurations for 24bpp support.
>> Since v1:
>> Simplified calculation of pseudopalette for FB_VISUAL_TRUECOLOR type.
>>
>> drivers/video/da8xx-fb.c | 127 ++++++++++++++++++++++++++++++++++------------
>> 1 files changed, 94 insertions(+), 33 deletions(-)
>>
>> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
>> index 47118c7..3d2d0d1 100644
>> --- a/drivers/video/da8xx-fb.c
>> +++ b/drivers/video/da8xx-fb.c
>> @@ -83,6 +83,8 @@
>> #define LCD_V2_LIDD_CLK_EN BIT(1)
>> #define LCD_V2_CORE_CLK_EN BIT(0)
>> #define LCD_V2_LPP_B10 26
>> +#define LCD_V2_TFT_24BPP_MODE BIT(25)
>> +#define LCD_V2_TFT_24BPP_UNPACK BIT(26)
>>
>> /* LCD Raster Timing 2 Register */
>> #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
>> @@ -153,7 +155,7 @@ struct da8xx_fb_par {
>> unsigned int dma_end;
>> struct clk *lcdc_clk;
>> int irq;
>> - unsigned short pseudo_palette[16];
>> + unsigned long pseudo_palette[16];
>
> I am still not convinced as sizes of "unsigned long" and "unsigned int" are not
> guaranteed to be 32bit across platforms and compilers, so planning to retain u32.
Yes, if you want something that is always 32 bit you probably should use
u32, that is at least more obvious.
There are a few guarantees in C like
sizeof(short)<=sizeof(int)<=sizeof(long) and short at least being 16
bits and long at least 32 bits that any standard compliant compiler
should honor. And if you limit it to a specific platform/CPU even more
may be assured. But if you want to highlight that you always want to use
32bit u32 is the best choice.
>
> Florian Tobias Schandinat,
> Can you please comment?
Best regards,
Florian Tobias Schandinat
>
> Here is the history:
> http://marc.info/?l=linux-fbdev&m\x134259216714719&w=2
>
>> unsigned int palette_sz;
>> unsigned int pxl_clk;
>> int blank;
>> @@ -482,6 +484,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>> {
>> u32 reg;
>>
>> + if ((bpp > 16) && (lcd_revision = LCD_VERSION_1))
>> + return -EINVAL;
>> +
>> /* Set the Panel Width */
>> /* Pixels per line = (PPL + 1)*16 */
>> if (lcd_revision = LCD_VERSION_1) {
>> @@ -525,6 +530,12 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>> reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
>> if (raster_order)
>> reg |= LCD_RASTER_ORDER;
>> +
>> + if (bpp = 24)
>> + reg |= LCD_V2_TFT_24BPP_MODE;
>> + else if (bpp = 32)
>> + reg |= (LCD_V2_TFT_24BPP_MODE | LCD_V2_TFT_24BPP_UNPACK);
>> +
>> lcdc_write(reg, LCD_RASTER_CTRL_REG);
>>
>> switch (bpp) {
>> @@ -532,6 +543,8 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>> case 2:
>> case 4:
>> case 16:
>> + case 24:
>> + case 32:
>> par->palette_sz = 16 * 2;
>> break;
>>
>> @@ -546,6 +559,8 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
>> return 0;
>> }
>>
>> +
>> +#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
>
> since multiple FB drivers have re-defined this macro, I will move this to common place(linux/fb.h) and
> convert it as inline function.
>
> Thanks,
> Prakash
>
>> static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
> [...]
>
^ permalink raw reply
* Re: [PATCH] fbdev: sh_mobile_lcdc: Fix vertical panning step
From: Kuninori Morimoto @ 2012-07-30 1:25 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1343306215-20868-1-git-send-email-laurent.pinchart@ideasonboard.com>
Hi Laurent
> diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
> index 8cb653b..699487c 100644
> --- a/drivers/video/sh_mobile_lcdcfb.c
> +++ b/drivers/video/sh_mobile_lcdcfb.c
> @@ -1716,11 +1716,11 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
> info->fix.visual = FB_VISUAL_TRUECOLOR;
>
> switch (ovl->format->fourcc) {
> - case V4L2_PIX_FMT_NV16:
> - case V4L2_PIX_FMT_NV61:
> - info->fix.ypanstep = 2;
> case V4L2_PIX_FMT_NV12:
> case V4L2_PIX_FMT_NV21:
> + info->fix.ypanstep = 2;
> + case V4L2_PIX_FMT_NV16:
> + case V4L2_PIX_FMT_NV61:
> info->fix.xpanstep = 2;
> }
>
> @@ -2215,11 +2215,11 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
> info->fix.visual = FB_VISUAL_TRUECOLOR;
>
> switch (ch->format->fourcc) {
> - case V4L2_PIX_FMT_NV16:
> - case V4L2_PIX_FMT_NV61:
> - info->fix.ypanstep = 2;
> case V4L2_PIX_FMT_NV12:
> case V4L2_PIX_FMT_NV21:
> + info->fix.ypanstep = 2;
> + case V4L2_PIX_FMT_NV16:
> + case V4L2_PIX_FMT_NV61:
> info->fix.xpanstep = 2;
> }
If possible, could you please add comment /* fall through */ ?
current code is a little bit confusing
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Alex Courbot @ 2012-07-30 1:51 UTC (permalink / raw)
To: Greg Kroah-Hartman, Anton Vorontsov, David Woodhouse
Cc: Stephen Warren, Thierry Reding, Simon Glass, Grant Likely,
Rob Herring, Mark Brown, Arnd Bergmann,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
In-Reply-To: <20120727181923.GB23564-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
On 07/28/2012 03:19 AM, Greg Kroah-Hartman wrote:
> On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
>> Some device drivers (panel backlights especially) need to follow precise
>> sequences for powering on and off, involving gpios, regulators, PWMs
>> with a precise powering order and delays to respect between each steps.
>> These sequences are board-specific, and do not belong to a particular
>> driver - therefore they have been performed by board-specific hook
>> functions to far.
>>
>> With the advent of the device tree and of ARM kernels that are not
>> board-tied, we cannot rely on these board-specific hooks anymore but
>> need a way to implement these sequences in a portable manner. This patch
>> introduces a simple interpreter that can execute such power sequences
>> encoded either as platform data or within the device tree.
>>
>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>> ---
>> Documentation/power/power_seq.txt | 120 +++++++++++++++
>> drivers/base/Kconfig | 4 +
>> drivers/base/Makefile | 1 +
>> drivers/base/power_seq.c | 300 ++++++++++++++++++++++++++++++++++++++
>> include/linux/power_seq.h | 139 ++++++++++++++++++
>
> What's wrong with drivers/power/? I sure don't want to maintain this
> code, and it seems to not be part of the "driver core" infrastructure.
I thought about drivers/power/ initially, but quickly realized it was
only about the power supply class and its drivers - so I felt like it
would be out of place there, as the power sequences have nothing to do
with power supply but instead control gpios, regulators and pwms.
On the other hand I have just noticed that the apparently unrelated
Adaptive Voltage Scaling driver just appeared in drivers/power/avs. So
if Anton and David are ok with this, maybe I could put the power
sequences code in its own subdirectory within drivers/power.
Thanks,
Alex.
^ permalink raw reply
* Gethering power management/policy hw drivers under drivers/power/? (Re: [RFC][PATCH v3 1/3] runtime
From: Anton Vorontsov @ 2012-07-30 2:40 UTC (permalink / raw)
To: Alex Courbot, Jean Pihet
Cc: Greg Kroah-Hartman, David Woodhouse, Stephen Warren,
Thierry Reding, Simon Glass, Grant Likely, Rob Herring,
Mark Brown, Arnd Bergmann, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org,
devicetree-discuss@lists.ozlabs.org, Liam Girdwood, MyungJoo Ham,
Rafael J. Wysocki, linux-pm
In-Reply-To: <5015E8AE.8060404@nvidia.com>
On Mon, Jul 30, 2012 at 10:51:42AM +0900, Alex Courbot wrote:
[...]
> On the other hand I have just noticed that the apparently unrelated
> Adaptive Voltage Scaling driver just appeared in drivers/power/avs.
> So if Anton and David are ok with this, maybe I could put the power
> sequences code in its own subdirectory within drivers/power.
Well, currently drivers/power/ is indeed just for power supply class
subsystem and drivers. But if the trend is to gather power management
("policy") stuff under one directory, i.e.
drivers/
power/
supplies/ <- former "power supply class and drivers"
regulators/
idle/
cpuidle/
cpufreq/
devfreq/
avs/
...
That would probably make sense, we could easily see the big picture.
But if we're not going to do this long-term, I would suggest to stick
to just a new directory under drivers (and move drivers/power/avs/ to
drivers/avs).
Cc'ing some more people...
Thanks,
p.s. Jean, why am I the last person who discovers drivers/power/avs/?
Would be nice to Cc me on such patches; by moving AVS under
drivers/power/ you effectively nominated me as its maintainer. :-)
--
Anton Vorontsov
Email: cbouatmailru@gmail.com
^ permalink raw reply
* Re: Gethering power management/policy hw drivers under drivers/power/? (Re: [RFC][PATCH v3 1/3] runt
From: 함명주 @ 2012-07-30 3:04 UTC (permalink / raw)
To: Anton Vorontsov, Alex Courbot, Jean Pihet
Cc: Greg Kroah-Hartman, David Woodhouse, Stephen Warren,
Thierry Reding, Simon Glass, Grant Likely, Rob Herring,
Mark Brown, Arnd Bergmann,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
Liam Girdwood, Rafael J. Wysocki,
linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <20120730024049.GA10442@lizard>
PiBPbiBNb24sIEp1bCAzMCwgMjAxMiBhdCAxMDo1MTo0MkFNICswOTAwLCBBbGV4IENvdXJib3Qg
d3JvdGU6DQo+IFsuLi5dDQo+ID4gT24gdGhlIG90aGVyIGhhbmQgSSBoYXZlIGp1c3Qgbm90aWNl
ZCB0aGF0IHRoZSBhcHBhcmVudGx5IHVucmVsYXRlZA0KPiA+IEFkYXB0aXZlIFZvbHRhZ2UgU2Nh
bGluZyBkcml2ZXIganVzdCBhcHBlYXJlZCBpbiBkcml2ZXJzL3Bvd2VyL2F2cy4NCj4gPiBTbyBp
ZiBBbnRvbiBhbmQgRGF2aWQgYXJlIG9rIHdpdGggdGhpcywgbWF5YmUgSSBjb3VsZCBwdXQgdGhl
IHBvd2VyDQo+ID4gc2VxdWVuY2VzIGNvZGUgaW4gaXRzIG93biBzdWJkaXJlY3Rvcnkgd2l0aGlu
IGRyaXZlcnMvcG93ZXIuDQo+IA0KPiBXZWxsLCBjdXJyZW50bHkgZHJpdmVycy9wb3dlci8gaXMg
aW5kZWVkIGp1c3QgZm9yIHBvd2VyIHN1cHBseSBjbGFzcw0KPiBzdWJzeXN0ZW0gYW5kIGRyaXZl
cnMuIEJ1dCBpZiB0aGUgdHJlbmQgaXMgdG8gZ2F0aGVyIHBvd2VyIG1hbmFnZW1lbnQNCj4gKCJw
b2xpY3kiKSBzdHVmZiB1bmRlciBvbmUgZGlyZWN0b3J5LCBpLmUuDQo+IA0KPiBkcml2ZXJzLw0K
PiAgIHBvd2VyLw0KPiAgICAgc3VwcGxpZXMvICAgIDwtIGZvcm1lciAicG93ZXIgc3VwcGx5IGNs
YXNzIGFuZCBkcml2ZXJzIg0KPiAgICAgcmVndWxhdG9ycy8NCj4gICAgIGlkbGUvDQo+ICAgICBj
cHVpZGxlLw0KPiAgICAgY3B1ZnJlcS8NCj4gICAgIGRldmZyZXEvDQo+ICAgICBhdnMvDQo+ICAg
ICAuLi4NCj4gDQo+IFRoYXQgd291bGQgcHJvYmFibHkgbWFrZSBzZW5zZSwgd2UgY291bGQgZWFz
aWx5IHNlZSB0aGUgYmlnIHBpY3R1cmUuDQo+IEJ1dCBpZiB3ZSdyZSBub3QgZ29pbmcgdG8gZG8g
dGhpcyBsb25nLXRlcm0sIEkgd291bGQgc3VnZ2VzdCB0byBzdGljaw0KPiB0byBqdXN0IGEgbmV3
IGRpcmVjdG9yeSB1bmRlciBkcml2ZXJzIChhbmQgbW92ZSBkcml2ZXJzL3Bvd2VyL2F2cy8gdG8N
Cj4gZHJpdmVycy9hdnMpLg0KPiANCj4gQ2MnaW5nIHNvbWUgbW9yZSBwZW9wbGUuLi4NCj4gDQo+
IFRoYW5rcywNCj4gDQo+IHAucy4gSmVhbiwgd2h5IGFtIEkgdGhlIGxhc3QgcGVyc29uIHdobyBk
aXNjb3ZlcnMgZHJpdmVycy9wb3dlci9hdnMvPw0KPiBXb3VsZCBiZSBuaWNlIHRvIENjIG1lIG9u
IHN1Y2ggcGF0Y2hlczsgYnkgbW92aW5nIEFWUyB1bmRlcg0KPiBkcml2ZXJzL3Bvd2VyLyB5b3Ug
ZWZmZWN0aXZlbHkgbm9taW5hdGVkIG1lIGFzIGl0cyBtYWludGFpbmVyLiA6LSkNCj4gDQo+IC0t
IA0KPiBBbnRvbiBWb3JvbnRzb3YNCj4gRW1haWw6IGNib3VhdG1haWxydUBnbWFpbC5jb20NCj4g
DQoNCkhhdmluZyBwb3dlci1zdXBwbGllcyBhdCAvZHJpdmVycy9wb3dlci8gYW5kIG90aGVyIHBv
d2VyLXJlbGF0ZWQgZHJpdmVycyBzcHJlYWQgYXQgL2RyaXZlcnMvIGhhdmUgYmVlbiBidWdnaW5n
IG1lIGFzIHdlbGwuIEknZCBsaWtlIHRvIHNlZSB0aGUgY2hhbmdlIHlvdSd2ZSBzdWdnZXN0ZWQg
dGhvdWdoIEknbSBub3Qgc3VyZSBob3cgc2lnbmlmaWNhbnQgdGhlIHNpZGUtZWZmZWN0IHdpbGwg
YmUgYXQgdGhpcyBwb2ludC4NCg0KR2VuZXJhbGx5IHNwZWFraW5nLCB5ZXMsIEkgYWxzbyB0aGlu
ayB0aGUgcHJvcG9zYWwgaXMgbW9yZSByZWFzb25hYmxlIHRoYW4gdGhlIGN1cnJlbnQgc3RydWN0
dXJlLg0KDQoNCg0KQ2hlZXJzIQ0KTXl1bmdKb28NCg0KDQo
^ permalink raw reply
* Re: [PATCH] video: exynos_dp: adjust voltage swing and pre-emphasis during Link Training
From: Jingoo Han @ 2012-07-30 4:08 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <001101cd656a$5ea25c90$1be715b0$%han@samsung.com>
On Thursday, July 19, 2012 1:53 PM, Jingoo Han wrote:
>
> This patch adds adjustement for voltage swing and pre-emphasis during
> Link Training procedure. According to the DP specification, unless all
> the LANEx_CR_DONE bits are set, the transmitter must read
> the ADJUST_REQUEST_LANEx_x, increase the voltage swing according to
> the request, and update the TRAINING_LANEx_SET bytes to match the new
> voltage swing setting.
>
> Refer to the DP specification v1.1a, Section 3.5.1.3 Link Training.
>
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Hi Florian,
Could you accept this patch for 3.6-rc1?
This patch was already verified and tested with different 2 kinds of eDP LCD panels.
Thank you.
Best regards,
Jingoo Han
> ---
> drivers/video/exynos/exynos_dp_core.c | 282 +++++++++++++++++----------------
> drivers/video/exynos/exynos_dp_core.h | 2 +-
> 2 files changed, 144 insertions(+), 140 deletions(-)
>
> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
> index c6c016a..9c0140f 100644
> --- a/drivers/video/exynos/exynos_dp_core.c
> +++ b/drivers/video/exynos/exynos_dp_core.c
> @@ -260,7 +260,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
>
> static void exynos_dp_link_start(struct exynos_dp_device *dp)
> {
> - u8 buf[5];
> + u8 buf[4];
> int lane;
> int lane_count;
>
> @@ -295,10 +295,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
> exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
>
> /* Set RX training pattern */
> - buf[0] = DPCD_SCRAMBLING_DISABLED |
> - DPCD_TRAINING_PATTERN_1;
> exynos_dp_write_byte_to_dpcd(dp,
> - DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
> + DPCD_ADDR_TRAINING_PATTERN_SET,
> + DPCD_SCRAMBLING_DISABLED |
> + DPCD_TRAINING_PATTERN_1);
>
> for (lane = 0; lane < lane_count; lane++)
> buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
> @@ -308,7 +308,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
> lane_count, buf);
> }
>
> -static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
> +static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
> {
> int shift = (lane & 1) * 4;
> u8 link_value = link_status[lane>>1];
> @@ -316,7 +316,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
> return (link_value >> shift) & 0xf;
> }
>
> -static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
> +static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
> {
> int lane;
> u8 lane_status;
> @@ -329,22 +329,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
> return 0;
> }
>
> -static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
> +static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
> {
> int lane;
> u8 lane_align;
> u8 lane_status;
>
> - lane_align = link_status[2];
> + lane_align = link_align[2];
> if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) = 0)
> return -EINVAL;
>
> for (lane = 0; lane < lane_count; lane++) {
> - lane_status = exynos_dp_get_lane_status(link_status, lane);
> + lane_status = exynos_dp_get_lane_status(link_align, lane);
> lane_status &= DPCD_CHANNEL_EQ_BITS;
> if (lane_status != DPCD_CHANNEL_EQ_BITS)
> return -EINVAL;
> }
> +
> return 0;
> }
>
> @@ -417,69 +418,17 @@ static unsigned int exynos_dp_get_lane_link_training(
>
> static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
> {
> - if (dp->link_train.link_rate = LINK_RATE_2_70GBPS) {
> - /* set to reduced bit rate */
> - dp->link_train.link_rate = LINK_RATE_1_62GBPS;
> - dev_err(dp->dev, "set to bandwidth %.2x\n",
> - dp->link_train.link_rate);
> - dp->link_train.lt_state = START;
> - } else {
> - exynos_dp_training_pattern_dis(dp);
> - /* set enhanced mode if available */
> - exynos_dp_set_enhanced_mode(dp);
> - dp->link_train.lt_state = FAILED;
> - }
> -}
> -
> -static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
> - u8 adjust_request[2])
> -{
> - int lane;
> - int lane_count;
> - u8 voltage_swing;
> - u8 pre_emphasis;
> - u8 training_lane;
> + exynos_dp_training_pattern_dis(dp);
> + exynos_dp_set_enhanced_mode(dp);
>
> - lane_count = dp->link_train.lane_count;
> - for (lane = 0; lane < lane_count; lane++) {
> - voltage_swing = exynos_dp_get_adjust_request_voltage(
> - adjust_request, lane);
> - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> - adjust_request, lane);
> - training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> - DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> -
> - if (voltage_swing = VOLTAGE_LEVEL_3 ||
> - pre_emphasis = PRE_EMPHASIS_LEVEL_3) {
> - training_lane |= DPCD_MAX_SWING_REACHED;
> - training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> - }
> - dp->link_train.training_lane[lane] = training_lane;
> - }
> -}
> -
> -static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
> - u8 voltage_swing)
> -{
> - int lane;
> - int lane_count;
> -
> - lane_count = dp->link_train.lane_count;
> - for (lane = 0; lane < lane_count; lane++) {
> - if (voltage_swing = VOLTAGE_LEVEL_3 ||
> - dp->link_train.cr_loop[lane] = MAX_CR_LOOP)
> - return -EINVAL;
> - }
> - return 0;
> + dp->link_train.lt_state = FAILED;
> }
>
> static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
> {
> - u8 data;
> - u8 link_status[6];
> + u8 link_status[2];
> int lane;
> int lane_count;
> - u8 buf[5];
>
> u8 adjust_request[2];
> u8 voltage_swing;
> @@ -488,98 +437,152 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>
> usleep_range(100, 101);
>
> - exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> - 6, link_status);
> lane_count = dp->link_train.lane_count;
>
> + exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> + 2, link_status);
> +
> if (exynos_dp_clock_recovery_ok(link_status, lane_count) = 0) {
> /* set training pattern 2 for EQ */
> exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
>
> - adjust_request[0] = link_status[4];
> - adjust_request[1] = link_status[5];
> + for (lane = 0; lane < lane_count; lane++) {
> + exynos_dp_read_bytes_from_dpcd(dp,
> + DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> + 2, adjust_request);
> + voltage_swing = exynos_dp_get_adjust_request_voltage(
> + adjust_request, lane);
> + pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> + adjust_request, lane);
> + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> + DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>
> - exynos_dp_get_adjust_train(dp, adjust_request);
> + if (voltage_swing = VOLTAGE_LEVEL_3)
> + training_lane |= DPCD_MAX_SWING_REACHED;
> + if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
> + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>
> - buf[0] = DPCD_SCRAMBLING_DISABLED |
> - DPCD_TRAINING_PATTERN_2;
> - exynos_dp_write_byte_to_dpcd(dp,
> - DPCD_ADDR_TRAINING_PATTERN_SET,
> - buf[0]);
> + dp->link_train.training_lane[lane] = training_lane;
>
> - for (lane = 0; lane < lane_count; lane++) {
> exynos_dp_set_lane_link_training(dp,
> dp->link_train.training_lane[lane],
> lane);
> - buf[lane] = dp->link_train.training_lane[lane];
> - exynos_dp_write_byte_to_dpcd(dp,
> - DPCD_ADDR_TRAINING_LANE0_SET + lane,
> - buf[lane]);
> }
> - dp->link_train.lt_state = EQUALIZER_TRAINING;
> - } else {
> - exynos_dp_read_byte_from_dpcd(dp,
> - DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> - &data);
> - adjust_request[0] = data;
>
> - exynos_dp_read_byte_from_dpcd(dp,
> - DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
> - &data);
> - adjust_request[1] = data;
> + exynos_dp_write_byte_to_dpcd(dp,
> + DPCD_ADDR_TRAINING_PATTERN_SET,
> + DPCD_SCRAMBLING_DISABLED |
> + DPCD_TRAINING_PATTERN_2);
> +
> + exynos_dp_write_bytes_to_dpcd(dp,
> + DPCD_ADDR_TRAINING_LANE0_SET,
> + lane_count,
> + dp->link_train.training_lane);
>
> + dev_info(dp->dev, "Link Training Clock Recovery success\n");
> + dp->link_train.lt_state = EQUALIZER_TRAINING;
> + } else {
> for (lane = 0; lane < lane_count; lane++) {
> training_lane = exynos_dp_get_lane_link_training(
> dp, lane);
> + exynos_dp_read_bytes_from_dpcd(dp,
> + DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> + 2, adjust_request);
> voltage_swing = exynos_dp_get_adjust_request_voltage(
> adjust_request, lane);
> pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> adjust_request, lane);
> - if ((DPCD_VOLTAGE_SWING_GET(training_lane) = voltage_swing) &&
> - (DPCD_PRE_EMPHASIS_GET(training_lane) = pre_emphasis))
> - dp->link_train.cr_loop[lane]++;
> - dp->link_train.training_lane[lane] = training_lane;
> - }
>
> - if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
> - exynos_dp_reduce_link_rate(dp);
> - } else {
> - exynos_dp_get_adjust_train(dp, adjust_request);
> + if (voltage_swing = VOLTAGE_LEVEL_3 ||
> + pre_emphasis = PRE_EMPHASIS_LEVEL_3) {
> + dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
> + goto reduce_link_rate;
> + }
>
> - for (lane = 0; lane < lane_count; lane++) {
> - exynos_dp_set_lane_link_training(dp,
> - dp->link_train.training_lane[lane],
> - lane);
> - buf[lane] = dp->link_train.training_lane[lane];
> - exynos_dp_write_byte_to_dpcd(dp,
> - DPCD_ADDR_TRAINING_LANE0_SET + lane,
> - buf[lane]);
> + if ((DPCD_VOLTAGE_SWING_GET(training_lane) =
> + voltage_swing) &&
> + (DPCD_PRE_EMPHASIS_GET(training_lane) =
> + pre_emphasis)) {
> + dp->link_train.cr_loop[lane]++;
> + if (dp->link_train.cr_loop[lane] = MAX_CR_LOOP) {
> + dev_err(dp->dev, "CR Max loop\n");
> + goto reduce_link_rate;
> + }
> }
> +
> + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> + DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> +
> + if (voltage_swing = VOLTAGE_LEVEL_3)
> + training_lane |= DPCD_MAX_SWING_REACHED;
> + if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
> + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> +
> + dp->link_train.training_lane[lane] = training_lane;
> +
> + exynos_dp_set_lane_link_training(dp,
> + dp->link_train.training_lane[lane], lane);
> }
> +
> + exynos_dp_write_bytes_to_dpcd(dp,
> + DPCD_ADDR_TRAINING_LANE0_SET,
> + lane_count,
> + dp->link_train.training_lane);
> }
>
> return 0;
> +
> +reduce_link_rate:
> + exynos_dp_reduce_link_rate(dp);
> + return -EIO;
> }
>
> static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
> {
> - u8 link_status[6];
> + u8 link_status[2];
> + u8 link_align[3];
> int lane;
> int lane_count;
> - u8 buf[5];
> u32 reg;
>
> u8 adjust_request[2];
> + u8 voltage_swing;
> + u8 pre_emphasis;
> + u8 training_lane;
>
> usleep_range(400, 401);
>
> - exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> - 6, link_status);
> lane_count = dp->link_train.lane_count;
>
> + exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> + 2, link_status);
> +
> if (exynos_dp_clock_recovery_ok(link_status, lane_count) = 0) {
> - adjust_request[0] = link_status[4];
> - adjust_request[1] = link_status[5];
> + link_align[0] = link_status[0];
> + link_align[1] = link_status[1];
> +
> + exynos_dp_read_byte_from_dpcd(dp,
> + DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
> + &link_align[2]);
> +
> + for (lane = 0; lane < lane_count; lane++) {
> + exynos_dp_read_bytes_from_dpcd(dp,
> + DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> + 2, adjust_request);
> + voltage_swing = exynos_dp_get_adjust_request_voltage(
> + adjust_request, lane);
> + pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> + adjust_request, lane);
> + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> + DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> +
> + if (voltage_swing = VOLTAGE_LEVEL_3)
> + training_lane |= DPCD_MAX_SWING_REACHED;
> + if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
> + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> +
> + dp->link_train.training_lane[lane] = training_lane;
> + }
>
> if (exynos_dp_channel_eq_ok(link_status, lane_count) = 0) {
> /* traing pattern Set to Normal */
> @@ -596,39 +599,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
> dp->link_train.lane_count = reg;
> dev_dbg(dp->dev, "final lane count = %.2x\n",
> dp->link_train.lane_count);
> +
> /* set enhanced mode if available */
> exynos_dp_set_enhanced_mode(dp);
> -
> dp->link_train.lt_state = FINISHED;
> } else {
> /* not all locked */
> dp->link_train.eq_loop++;
>
> if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
> - exynos_dp_reduce_link_rate(dp);
> - } else {
> - exynos_dp_get_adjust_train(dp, adjust_request);
> -
> - for (lane = 0; lane < lane_count; lane++) {
> - exynos_dp_set_lane_link_training(dp,
> - dp->link_train.training_lane[lane],
> - lane);
> - buf[lane] = dp->link_train.training_lane[lane];
> - exynos_dp_write_byte_to_dpcd(dp,
> - DPCD_ADDR_TRAINING_LANE0_SET + lane,
> - buf[lane]);
> - }
> + dev_err(dp->dev, "EQ Max loop\n");
> + goto reduce_link_rate;
> }
> +
> + for (lane = 0; lane < lane_count; lane++)
> + exynos_dp_set_lane_link_training(dp,
> + dp->link_train.training_lane[lane],
> + lane);
> +
> + exynos_dp_write_bytes_to_dpcd(dp,
> + DPCD_ADDR_TRAINING_LANE0_SET,
> + lane_count,
> + dp->link_train.training_lane);
> }
> } else {
> - exynos_dp_reduce_link_rate(dp);
> + goto reduce_link_rate;
> }
>
> return 0;
> +
> +reduce_link_rate:
> + exynos_dp_reduce_link_rate(dp);
> + return -EIO;
> }
>
> static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
> - u8 *bandwidth)
> + u8 *bandwidth)
> {
> u8 data;
>
> @@ -641,7 +647,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
> }
>
> static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
> - u8 *lane_count)
> + u8 *lane_count)
> {
> u8 data;
>
> @@ -693,13 +699,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
> static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
> {
> int retval = 0;
> - int training_finished;
> -
> - /* Turn off unnecessary lane */
> - if (dp->link_train.lane_count = 1)
> - exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
> -
> - training_finished = 0;
> + int training_finished = 0;
>
> dp->link_train.lt_state = START;
>
> @@ -710,10 +710,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
> exynos_dp_link_start(dp);
> break;
> case CLOCK_RECOVERY:
> - exynos_dp_process_clock_recovery(dp);
> + retval = exynos_dp_process_clock_recovery(dp);
> + if (retval)
> + dev_err(dp->dev, "LT CR failed!\n");
> break;
> case EQUALIZER_TRAINING:
> - exynos_dp_process_equalizer_training(dp);
> + retval = exynos_dp_process_equalizer_training(dp);
> + if (retval)
> + dev_err(dp->dev, "LT EQ failed!\n");
> break;
> case FINISHED:
> training_finished = 1;
> diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
> index 8526e54..44c11e1 100644
> --- a/drivers/video/exynos/exynos_dp_core.h
> +++ b/drivers/video/exynos/exynos_dp_core.h
> @@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
> #define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
> #define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
> #define DPCD_ADDR_LANE0_1_STATUS 0x0202
> -#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
> +#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED 0x0204
> #define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
> #define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
> #define DPCD_ADDR_TEST_REQUEST 0x0218
> --
> 1.7.1
^ permalink raw reply
* Re: [PATCH] video: exynos_dp: adjust voltage swing and pre-emphasis during Link Training
From: Florian Tobias Schandinat @ 2012-07-30 6:33 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <001101cd656a$5ea25c90$1be715b0$%han@samsung.com>
Hi,
On 07/30/2012 04:08 AM, Jingoo Han wrote:
> On Thursday, July 19, 2012 1:53 PM, Jingoo Han wrote:
>>
>> This patch adds adjustement for voltage swing and pre-emphasis during
>> Link Training procedure. According to the DP specification, unless all
>> the LANEx_CR_DONE bits are set, the transmitter must read
>> the ADJUST_REQUEST_LANEx_x, increase the voltage swing according to
>> the request, and update the TRAINING_LANEx_SET bytes to match the new
>> voltage swing setting.
>>
>> Refer to the DP specification v1.1a, Section 3.5.1.3 Link Training.
>>
>> Signed-off-by: Jingoo Han <jg1.han@samsung.com>
>
>
> Hi Florian,
>
> Could you accept this patch for 3.6-rc1?
I rather consider it for -rc2 or -rc3. You could have made my life easier by
(1) sending it earlier, not just half a week before the merge window
opened. For some reason a lot of patches ended up hitting my Inbox in
that timeframe which is bad timing for things that should go in this
merge window as I usually wait a week before applying to give others the
chance to comment on it and I should have my final tree ready the day
the merge window opens.
(2) reducing it to the bare minimum changes required or splitting it up
and not doing a bunch of unrelated changes
> This patch was already verified and tested with different 2 kinds of eDP LCD panels.
I'm not saying that your patch is wrong. I think it is important, but
given its size I don't feel comfortable with just looking at the code
but feel that it should be longer in -next than 2 days.
Best regards,
Florian Tobias Schandinat
> Thank you.
>
> Best regards,
> Jingoo Han
>
>
>> ---
>> drivers/video/exynos/exynos_dp_core.c | 282 +++++++++++++++++----------------
>> drivers/video/exynos/exynos_dp_core.h | 2 +-
>> 2 files changed, 144 insertions(+), 140 deletions(-)
>>
>> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
>> index c6c016a..9c0140f 100644
>> --- a/drivers/video/exynos/exynos_dp_core.c
>> +++ b/drivers/video/exynos/exynos_dp_core.c
>> @@ -260,7 +260,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
>>
>> static void exynos_dp_link_start(struct exynos_dp_device *dp)
>> {
>> - u8 buf[5];
>> + u8 buf[4];
>> int lane;
>> int lane_count;
>>
>> @@ -295,10 +295,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
>> exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
>>
>> /* Set RX training pattern */
>> - buf[0] = DPCD_SCRAMBLING_DISABLED |
>> - DPCD_TRAINING_PATTERN_1;
>> exynos_dp_write_byte_to_dpcd(dp,
>> - DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
>> + DPCD_ADDR_TRAINING_PATTERN_SET,
>> + DPCD_SCRAMBLING_DISABLED |
>> + DPCD_TRAINING_PATTERN_1);
>>
>> for (lane = 0; lane < lane_count; lane++)
>> buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
>> @@ -308,7 +308,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
>> lane_count, buf);
>> }
>>
>> -static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
>> +static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
>> {
>> int shift = (lane & 1) * 4;
>> u8 link_value = link_status[lane>>1];
>> @@ -316,7 +316,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
>> return (link_value >> shift) & 0xf;
>> }
>>
>> -static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
>> +static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
>> {
>> int lane;
>> u8 lane_status;
>> @@ -329,22 +329,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
>> return 0;
>> }
>>
>> -static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
>> +static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
>> {
>> int lane;
>> u8 lane_align;
>> u8 lane_status;
>>
>> - lane_align = link_status[2];
>> + lane_align = link_align[2];
>> if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) = 0)
>> return -EINVAL;
>>
>> for (lane = 0; lane < lane_count; lane++) {
>> - lane_status = exynos_dp_get_lane_status(link_status, lane);
>> + lane_status = exynos_dp_get_lane_status(link_align, lane);
>> lane_status &= DPCD_CHANNEL_EQ_BITS;
>> if (lane_status != DPCD_CHANNEL_EQ_BITS)
>> return -EINVAL;
>> }
>> +
>> return 0;
>> }
>>
>> @@ -417,69 +418,17 @@ static unsigned int exynos_dp_get_lane_link_training(
>>
>> static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
>> {
>> - if (dp->link_train.link_rate = LINK_RATE_2_70GBPS) {
>> - /* set to reduced bit rate */
>> - dp->link_train.link_rate = LINK_RATE_1_62GBPS;
>> - dev_err(dp->dev, "set to bandwidth %.2x\n",
>> - dp->link_train.link_rate);
>> - dp->link_train.lt_state = START;
>> - } else {
>> - exynos_dp_training_pattern_dis(dp);
>> - /* set enhanced mode if available */
>> - exynos_dp_set_enhanced_mode(dp);
>> - dp->link_train.lt_state = FAILED;
>> - }
>> -}
>> -
>> -static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
>> - u8 adjust_request[2])
>> -{
>> - int lane;
>> - int lane_count;
>> - u8 voltage_swing;
>> - u8 pre_emphasis;
>> - u8 training_lane;
>> + exynos_dp_training_pattern_dis(dp);
>> + exynos_dp_set_enhanced_mode(dp);
>>
>> - lane_count = dp->link_train.lane_count;
>> - for (lane = 0; lane < lane_count; lane++) {
>> - voltage_swing = exynos_dp_get_adjust_request_voltage(
>> - adjust_request, lane);
>> - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>> - adjust_request, lane);
>> - training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
>> - DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>> -
>> - if (voltage_swing = VOLTAGE_LEVEL_3 ||
>> - pre_emphasis = PRE_EMPHASIS_LEVEL_3) {
>> - training_lane |= DPCD_MAX_SWING_REACHED;
>> - training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>> - }
>> - dp->link_train.training_lane[lane] = training_lane;
>> - }
>> -}
>> -
>> -static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
>> - u8 voltage_swing)
>> -{
>> - int lane;
>> - int lane_count;
>> -
>> - lane_count = dp->link_train.lane_count;
>> - for (lane = 0; lane < lane_count; lane++) {
>> - if (voltage_swing = VOLTAGE_LEVEL_3 ||
>> - dp->link_train.cr_loop[lane] = MAX_CR_LOOP)
>> - return -EINVAL;
>> - }
>> - return 0;
>> + dp->link_train.lt_state = FAILED;
>> }
>>
>> static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>> {
>> - u8 data;
>> - u8 link_status[6];
>> + u8 link_status[2];
>> int lane;
>> int lane_count;
>> - u8 buf[5];
>>
>> u8 adjust_request[2];
>> u8 voltage_swing;
>> @@ -488,98 +437,152 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>>
>> usleep_range(100, 101);
>>
>> - exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
>> - 6, link_status);
>> lane_count = dp->link_train.lane_count;
>>
>> + exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
>> + 2, link_status);
>> +
>> if (exynos_dp_clock_recovery_ok(link_status, lane_count) = 0) {
>> /* set training pattern 2 for EQ */
>> exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
>>
>> - adjust_request[0] = link_status[4];
>> - adjust_request[1] = link_status[5];
>> + for (lane = 0; lane < lane_count; lane++) {
>> + exynos_dp_read_bytes_from_dpcd(dp,
>> + DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
>> + 2, adjust_request);
>> + voltage_swing = exynos_dp_get_adjust_request_voltage(
>> + adjust_request, lane);
>> + pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>> + adjust_request, lane);
>> + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
>> + DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>>
>> - exynos_dp_get_adjust_train(dp, adjust_request);
>> + if (voltage_swing = VOLTAGE_LEVEL_3)
>> + training_lane |= DPCD_MAX_SWING_REACHED;
>> + if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
>> + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>>
>> - buf[0] = DPCD_SCRAMBLING_DISABLED |
>> - DPCD_TRAINING_PATTERN_2;
>> - exynos_dp_write_byte_to_dpcd(dp,
>> - DPCD_ADDR_TRAINING_PATTERN_SET,
>> - buf[0]);
>> + dp->link_train.training_lane[lane] = training_lane;
>>
>> - for (lane = 0; lane < lane_count; lane++) {
>> exynos_dp_set_lane_link_training(dp,
>> dp->link_train.training_lane[lane],
>> lane);
>> - buf[lane] = dp->link_train.training_lane[lane];
>> - exynos_dp_write_byte_to_dpcd(dp,
>> - DPCD_ADDR_TRAINING_LANE0_SET + lane,
>> - buf[lane]);
>> }
>> - dp->link_train.lt_state = EQUALIZER_TRAINING;
>> - } else {
>> - exynos_dp_read_byte_from_dpcd(dp,
>> - DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
>> - &data);
>> - adjust_request[0] = data;
>>
>> - exynos_dp_read_byte_from_dpcd(dp,
>> - DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
>> - &data);
>> - adjust_request[1] = data;
>> + exynos_dp_write_byte_to_dpcd(dp,
>> + DPCD_ADDR_TRAINING_PATTERN_SET,
>> + DPCD_SCRAMBLING_DISABLED |
>> + DPCD_TRAINING_PATTERN_2);
>> +
>> + exynos_dp_write_bytes_to_dpcd(dp,
>> + DPCD_ADDR_TRAINING_LANE0_SET,
>> + lane_count,
>> + dp->link_train.training_lane);
>>
>> + dev_info(dp->dev, "Link Training Clock Recovery success\n");
>> + dp->link_train.lt_state = EQUALIZER_TRAINING;
>> + } else {
>> for (lane = 0; lane < lane_count; lane++) {
>> training_lane = exynos_dp_get_lane_link_training(
>> dp, lane);
>> + exynos_dp_read_bytes_from_dpcd(dp,
>> + DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
>> + 2, adjust_request);
>> voltage_swing = exynos_dp_get_adjust_request_voltage(
>> adjust_request, lane);
>> pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>> adjust_request, lane);
>> - if ((DPCD_VOLTAGE_SWING_GET(training_lane) = voltage_swing) &&
>> - (DPCD_PRE_EMPHASIS_GET(training_lane) = pre_emphasis))
>> - dp->link_train.cr_loop[lane]++;
>> - dp->link_train.training_lane[lane] = training_lane;
>> - }
>>
>> - if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
>> - exynos_dp_reduce_link_rate(dp);
>> - } else {
>> - exynos_dp_get_adjust_train(dp, adjust_request);
>> + if (voltage_swing = VOLTAGE_LEVEL_3 ||
>> + pre_emphasis = PRE_EMPHASIS_LEVEL_3) {
>> + dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
>> + goto reduce_link_rate;
>> + }
>>
>> - for (lane = 0; lane < lane_count; lane++) {
>> - exynos_dp_set_lane_link_training(dp,
>> - dp->link_train.training_lane[lane],
>> - lane);
>> - buf[lane] = dp->link_train.training_lane[lane];
>> - exynos_dp_write_byte_to_dpcd(dp,
>> - DPCD_ADDR_TRAINING_LANE0_SET + lane,
>> - buf[lane]);
>> + if ((DPCD_VOLTAGE_SWING_GET(training_lane) =
>> + voltage_swing) &&
>> + (DPCD_PRE_EMPHASIS_GET(training_lane) =
>> + pre_emphasis)) {
>> + dp->link_train.cr_loop[lane]++;
>> + if (dp->link_train.cr_loop[lane] = MAX_CR_LOOP) {
>> + dev_err(dp->dev, "CR Max loop\n");
>> + goto reduce_link_rate;
>> + }
>> }
>> +
>> + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
>> + DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>> +
>> + if (voltage_swing = VOLTAGE_LEVEL_3)
>> + training_lane |= DPCD_MAX_SWING_REACHED;
>> + if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
>> + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>> +
>> + dp->link_train.training_lane[lane] = training_lane;
>> +
>> + exynos_dp_set_lane_link_training(dp,
>> + dp->link_train.training_lane[lane], lane);
>> }
>> +
>> + exynos_dp_write_bytes_to_dpcd(dp,
>> + DPCD_ADDR_TRAINING_LANE0_SET,
>> + lane_count,
>> + dp->link_train.training_lane);
>> }
>>
>> return 0;
>> +
>> +reduce_link_rate:
>> + exynos_dp_reduce_link_rate(dp);
>> + return -EIO;
>> }
>>
>> static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
>> {
>> - u8 link_status[6];
>> + u8 link_status[2];
>> + u8 link_align[3];
>> int lane;
>> int lane_count;
>> - u8 buf[5];
>> u32 reg;
>>
>> u8 adjust_request[2];
>> + u8 voltage_swing;
>> + u8 pre_emphasis;
>> + u8 training_lane;
>>
>> usleep_range(400, 401);
>>
>> - exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
>> - 6, link_status);
>> lane_count = dp->link_train.lane_count;
>>
>> + exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
>> + 2, link_status);
>> +
>> if (exynos_dp_clock_recovery_ok(link_status, lane_count) = 0) {
>> - adjust_request[0] = link_status[4];
>> - adjust_request[1] = link_status[5];
>> + link_align[0] = link_status[0];
>> + link_align[1] = link_status[1];
>> +
>> + exynos_dp_read_byte_from_dpcd(dp,
>> + DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
>> + &link_align[2]);
>> +
>> + for (lane = 0; lane < lane_count; lane++) {
>> + exynos_dp_read_bytes_from_dpcd(dp,
>> + DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
>> + 2, adjust_request);
>> + voltage_swing = exynos_dp_get_adjust_request_voltage(
>> + adjust_request, lane);
>> + pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>> + adjust_request, lane);
>> + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
>> + DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>> +
>> + if (voltage_swing = VOLTAGE_LEVEL_3)
>> + training_lane |= DPCD_MAX_SWING_REACHED;
>> + if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
>> + training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>> +
>> + dp->link_train.training_lane[lane] = training_lane;
>> + }
>>
>> if (exynos_dp_channel_eq_ok(link_status, lane_count) = 0) {
>> /* traing pattern Set to Normal */
>> @@ -596,39 +599,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
>> dp->link_train.lane_count = reg;
>> dev_dbg(dp->dev, "final lane count = %.2x\n",
>> dp->link_train.lane_count);
>> +
>> /* set enhanced mode if available */
>> exynos_dp_set_enhanced_mode(dp);
>> -
>> dp->link_train.lt_state = FINISHED;
>> } else {
>> /* not all locked */
>> dp->link_train.eq_loop++;
>>
>> if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
>> - exynos_dp_reduce_link_rate(dp);
>> - } else {
>> - exynos_dp_get_adjust_train(dp, adjust_request);
>> -
>> - for (lane = 0; lane < lane_count; lane++) {
>> - exynos_dp_set_lane_link_training(dp,
>> - dp->link_train.training_lane[lane],
>> - lane);
>> - buf[lane] = dp->link_train.training_lane[lane];
>> - exynos_dp_write_byte_to_dpcd(dp,
>> - DPCD_ADDR_TRAINING_LANE0_SET + lane,
>> - buf[lane]);
>> - }
>> + dev_err(dp->dev, "EQ Max loop\n");
>> + goto reduce_link_rate;
>> }
>> +
>> + for (lane = 0; lane < lane_count; lane++)
>> + exynos_dp_set_lane_link_training(dp,
>> + dp->link_train.training_lane[lane],
>> + lane);
>> +
>> + exynos_dp_write_bytes_to_dpcd(dp,
>> + DPCD_ADDR_TRAINING_LANE0_SET,
>> + lane_count,
>> + dp->link_train.training_lane);
>> }
>> } else {
>> - exynos_dp_reduce_link_rate(dp);
>> + goto reduce_link_rate;
>> }
>>
>> return 0;
>> +
>> +reduce_link_rate:
>> + exynos_dp_reduce_link_rate(dp);
>> + return -EIO;
>> }
>>
>> static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
>> - u8 *bandwidth)
>> + u8 *bandwidth)
>> {
>> u8 data;
>>
>> @@ -641,7 +647,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
>> }
>>
>> static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
>> - u8 *lane_count)
>> + u8 *lane_count)
>> {
>> u8 data;
>>
>> @@ -693,13 +699,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
>> static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
>> {
>> int retval = 0;
>> - int training_finished;
>> -
>> - /* Turn off unnecessary lane */
>> - if (dp->link_train.lane_count = 1)
>> - exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
>> -
>> - training_finished = 0;
>> + int training_finished = 0;
>>
>> dp->link_train.lt_state = START;
>>
>> @@ -710,10 +710,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
>> exynos_dp_link_start(dp);
>> break;
>> case CLOCK_RECOVERY:
>> - exynos_dp_process_clock_recovery(dp);
>> + retval = exynos_dp_process_clock_recovery(dp);
>> + if (retval)
>> + dev_err(dp->dev, "LT CR failed!\n");
>> break;
>> case EQUALIZER_TRAINING:
>> - exynos_dp_process_equalizer_training(dp);
>> + retval = exynos_dp_process_equalizer_training(dp);
>> + if (retval)
>> + dev_err(dp->dev, "LT EQ failed!\n");
>> break;
>> case FINISHED:
>> training_finished = 1;
>> diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
>> index 8526e54..44c11e1 100644
>> --- a/drivers/video/exynos/exynos_dp_core.h
>> +++ b/drivers/video/exynos/exynos_dp_core.h
>> @@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
>> #define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
>> #define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
>> #define DPCD_ADDR_LANE0_1_STATUS 0x0202
>> -#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
>> +#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED 0x0204
>> #define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
>> #define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
>> #define DPCD_ADDR_TEST_REQUEST 0x0218
>> --
>> 1.7.1
>
>
>
^ permalink raw reply
* RE: [PATCH v2 3/4] media: videobuf2-dma-contig: use dma_mmap_coherent if available
From: Marek Szyprowski @ 2012-07-30 7:43 UTC (permalink / raw)
To: 'Hideki EIRAKU', 'Russell King',
'Pawel Osciak', 'Kyungmin Park',
'Mauro Carvalho Chehab',
'Florian Tobias Schandinat', 'Jaroslav Kysela',
'Takashi Iwai'
Cc: linux-arm-kernel, linux-kernel, linux-media, linux-fbdev,
alsa-devel, 'Katsuya MATSUBARA'
In-Reply-To: <1343301191-26001-4-git-send-email-hdk@igel.co.jp>
Hello,
On Thursday, July 26, 2012 1:13 PM Hideki EIRAKU wrote:
> Previously the vb2_dma_contig_mmap() function was using a dma_addr_t as a
> physical address. The two addressses are not necessarily the same.
> For example, when using the IOMMU funtion on certain platforms, dma_addr_t
> addresses are not directly mappable physical address.
> dma_mmap_coherent() maps the address correctly.
> It is available on ARM platforms.
>
> Signed-off-by: Hideki EIRAKU <hdk@igel.co.jp>
> ---
> drivers/media/video/videobuf2-dma-contig.c | 18 ++++++++++++++++++
> 1 files changed, 18 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/media/video/videobuf2-dma-contig.c b/drivers/media/video/videobuf2-dma-
> contig.c
> index 4b71326..4dc85ab 100644
> --- a/drivers/media/video/videobuf2-dma-contig.c
> +++ b/drivers/media/video/videobuf2-dma-contig.c
> @@ -101,14 +101,32 @@ static unsigned int vb2_dma_contig_num_users(void *buf_priv)
> static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
> {
> struct vb2_dc_buf *buf = buf_priv;
> +#ifdef ARCH_HAS_DMA_MMAP_COHERENT
> + int ret;
> +#endif
>
> if (!buf) {
> printk(KERN_ERR "No buffer to map\n");
> return -EINVAL;
> }
>
> +#ifdef ARCH_HAS_DMA_MMAP_COHERENT
> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
The above line is not needed. It is up to dma_mmap_coherent() / dma_mmap_attrs() to set page
protection bits which match requested type of dma buffer mapping.
> + ret = dma_mmap_coherent(buf->conf->dev, vma, buf->vaddr, buf->dma_addr,
> + buf->size);
> + if (ret) {
> + pr_err("Remapping memory failed, error: %d\n", ret);
> + return ret;
> + }
> + vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
> + vma->vm_private_data = &buf->handler;
> + vma->vm_ops = &vb2_common_vm_ops;
> + vma->vm_ops->open(vma);
> + return 0;
> +#else
> return vb2_mmap_pfn_range(vma, buf->dma_addr, buf->size,
> &vb2_common_vm_ops, &buf->handler);
> +#endif
> }
>
> static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply
* Re: [PATCH 1/3] Move FIMD register headers to include/video/
From: Sylwester Nawrocki @ 2012-07-30 8:49 UTC (permalink / raw)
To: Leela Krishna Amudala
Cc: linux-arm-kernel, linux-samsung-soc, dri-devel, linux-fbdev,
ben-linux, inki.dae, kgene.kim, joshi, jg1.han
In-Reply-To: <1343637905-17764-2-git-send-email-l.krishna@samsung.com>
Hi,
On 07/30/2012 10:45 AM, Leela Krishna Amudala wrote:
> Moved the contents of regs-fb-v4.h and regs-fb.h from arch side
> to include/video/samsung_fimd.h
>
> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
> ---
> arch/arm/plat-samsung/include/plat/regs-fb-v4.h | 159 -------
> arch/arm/plat-samsung/include/plat/regs-fb.h | 403 -----------------
> include/video/samsung_fimd.h | 533 +++++++++++++++++++++++
> 3 files changed, 533 insertions(+), 562 deletions(-)
> delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
> create mode 100644 include/video/samsung_fimd.h
Thanks for taking care if this. However you might need to split this
patch in two, so there is no build and git bisection breakage. In the
first patch a new header file would be added, then the patch updating
users of the FIMD headers would be applied, and finally the regs-fb*.h
files would be removed.
Also it helps to use -M option to git format-patch when creating patches
that mainly move files.
--
Regards,
Sylwester
^ permalink raw reply
* Re: [PATCH 1/3] Move FIMD register headers to include/video/
From: Jingoo Han @ 2012-07-30 8:53 UTC (permalink / raw)
To: 'Leela Krishna Amudala', linux-arm-kernel,
linux-samsung-soc
Cc: dri-devel, linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
'Marek Szyprowski', 'Jingoo Han'
In-Reply-To: <1343637905-17764-2-git-send-email-l.krishna@samsung.com>
On Monday, July 30, 2012 5:45 PM, Leela Krishna Amudala wrote:
>
> Moved the contents of regs-fb-v4.h and regs-fb.h from arch side
> to include/video/samsung_fimd.h
>
> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
> ---
> arch/arm/plat-samsung/include/plat/regs-fb-v4.h | 159 -------
> arch/arm/plat-samsung/include/plat/regs-fb.h | 403 -----------------
> include/video/samsung_fimd.h | 533 +++++++++++++++++++++++
> 3 files changed, 533 insertions(+), 562 deletions(-)
> delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
> create mode 100644 include/video/samsung_fimd.h
>
> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-
> fb-v4.h
> deleted file mode 100644
> index 4c3647f..0000000
> --- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> +++ /dev/null
> @@ -1,159 +0,0 @@
> -/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> - *
> - * Copyright 2008 Openmoko, Inc.
> - * Copyright 2008 Simtec Electronics
> - * http://armlinux.simtec.co.uk/
> - * Ben Dooks <ben@simtec.co.uk>
> - *
> - * S3C64XX - new-style framebuffer register definitions
> - *
> - * This is the register set for the new style framebuffer interface
> - * found from the S3C2443 onwards and specifically the S3C64XX series
> - * S3C6400 and S3C6410.
> - *
> - * The file contains the cpu specific items which change between whichever
> - * architecture is selected. See <plat/regs-fb.h> for the core definitions
> - * that are the same.
> - *
> - * 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 the core definitions here, in case we really do need to
> - * override them at a later date.
> -*/
> -
> -#include <plat/regs-fb.h>
> -
> -#define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */
> -#define VIDCON1_FSTATUS_EVEN (1 << 15)
> -
> -/* Video timing controls */
> -#define VIDTCON0 (0x10)
> -#define VIDTCON1 (0x14)
> -#define VIDTCON2 (0x18)
> -
> -/* Window position controls */
> -
> -#define WINCON(_win) (0x20 + ((_win) * 4))
> -
> -/* OSD1 and OSD4 do not have register D */
> -
> -#define VIDOSD_BASE (0x40)
> -
> -#define VIDINTCON0 (0x130)
> -
> -/* WINCONx */
> -
> -#define WINCONx_CSCWIDTH_MASK (0x3 << 26)
> -#define WINCONx_CSCWIDTH_SHIFT (26)
> -#define WINCONx_CSCWIDTH_WIDE (0x0 << 26)
> -#define WINCONx_CSCWIDTH_NARROW (0x3 << 26)
> -
> -#define WINCONx_ENLOCAL (1 << 22)
> -#define WINCONx_BUFSTATUS (1 << 21)
> -#define WINCONx_BUFSEL (1 << 20)
> -#define WINCONx_BUFAUTOEN (1 << 19)
> -#define WINCONx_YCbCr (1 << 13)
> -
> -#define WINCON1_LOCALSEL_CAMIF (1 << 23)
> -
> -#define WINCON2_LOCALSEL_CAMIF (1 << 23)
> -#define WINCON2_BLD_PIX (1 << 6)
> -
> -#define WINCON2_ALPHA_SEL (1 << 1)
> -#define WINCON2_BPPMODE_MASK (0xf << 2)
> -#define WINCON2_BPPMODE_SHIFT (2)
> -#define WINCON2_BPPMODE_1BPP (0x0 << 2)
> -#define WINCON2_BPPMODE_2BPP (0x1 << 2)
> -#define WINCON2_BPPMODE_4BPP (0x2 << 2)
> -#define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2)
> -#define WINCON2_BPPMODE_16BPP_565 (0x5 << 2)
> -#define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2)
> -#define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2)
> -#define WINCON2_BPPMODE_18BPP_666 (0x8 << 2)
> -#define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2)
> -#define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2)
> -#define WINCON2_BPPMODE_24BPP_888 (0xb << 2)
> -#define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2)
> -#define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2)
> -#define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2)
> -
> -#define WINCON3_BLD_PIX (1 << 6)
> -
> -#define WINCON3_ALPHA_SEL (1 << 1)
> -#define WINCON3_BPPMODE_MASK (0xf << 2)
> -#define WINCON3_BPPMODE_SHIFT (2)
> -#define WINCON3_BPPMODE_1BPP (0x0 << 2)
> -#define WINCON3_BPPMODE_2BPP (0x1 << 2)
> -#define WINCON3_BPPMODE_4BPP (0x2 << 2)
> -#define WINCON3_BPPMODE_16BPP_565 (0x5 << 2)
> -#define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2)
> -#define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2)
> -#define WINCON3_BPPMODE_18BPP_666 (0x8 << 2)
> -#define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2)
> -#define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2)
> -#define WINCON3_BPPMODE_24BPP_888 (0xb << 2)
> -#define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2)
> -#define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2)
> -#define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2)
> -
> -#define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5)
> -#define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5)
> -#define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5)
> -
> -#define DITHMODE (0x170)
> -#define WINxMAP(_win) (0x180 + ((_win) * 4))
> -
> -
> -#define DITHMODE_R_POS_MASK (0x3 << 5)
> -#define DITHMODE_R_POS_SHIFT (5)
> -#define DITHMODE_R_POS_8BIT (0x0 << 5)
> -#define DITHMODE_R_POS_6BIT (0x1 << 5)
> -#define DITHMODE_R_POS_5BIT (0x2 << 5)
> -
> -#define DITHMODE_G_POS_MASK (0x3 << 3)
> -#define DITHMODE_G_POS_SHIFT (3)
> -#define DITHMODE_G_POS_8BIT (0x0 << 3)
> -#define DITHMODE_G_POS_6BIT (0x1 << 3)
> -#define DITHMODE_G_POS_5BIT (0x2 << 3)
> -
> -#define DITHMODE_B_POS_MASK (0x3 << 1)
> -#define DITHMODE_B_POS_SHIFT (1)
> -#define DITHMODE_B_POS_8BIT (0x0 << 1)
> -#define DITHMODE_B_POS_6BIT (0x1 << 1)
> -#define DITHMODE_B_POS_5BIT (0x2 << 1)
> -
> -#define DITHMODE_DITH_EN (1 << 0)
> -
> -#define WPALCON (0x1A0)
> -
> -/* Palette control */
> -/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
> - * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
> -#define WPALCON_W4PAL_16BPP_A555 (1 << 8)
> -#define WPALCON_W3PAL_16BPP_A555 (1 << 7)
> -#define WPALCON_W2PAL_16BPP_A555 (1 << 6)
> -
> -
> -/* Notes on per-window bpp settings
> - *
> - * Value Win0 Win1 Win2 Win3 Win 4
> - * 0000 1(P) 1(P) 1(P) 1(P) 1(P)
> - * 0001 2(P) 2(P) 2(P) 2(P) 2(P)
> - * 0010 4(P) 4(P) 4(P) 4(P) -none-
> - * 0011 8(P) 8(P) -none- -none- -none-
> - * 0100 -none- 8(A232) 8(A232) -none- -none-
> - * 0101 16(565) 16(565) 16(565) 16(565) 16(565)
> - * 0110 -none- 16(A555) 16(A555) 16(A555) 16(A555)
> - * 0111 16(I555) 16(I565) 16(I555) 16(I555) 16(I555)
> - * 1000 18(666) 18(666) 18(666) 18(666) 18(666)
> - * 1001 -none- 18(A665) 18(A665) 18(A665) 16(A665)
> - * 1010 -none- 19(A666) 19(A666) 19(A666) 19(A666)
> - * 1011 24(888) 24(888) 24(888) 24(888) 24(888)
> - * 1100 -none- 24(A887) 24(A887) 24(A887) 24(A887)
> - * 1101 -none- 25(A888) 25(A888) 25(A888) 25(A888)
> - * 1110 -none- -none- -none- -none- -none-
> - * 1111 -none- -none- -none- -none- -none-
> -*/
> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
> deleted file mode 100644
> index 9a78012..0000000
> --- a/arch/arm/plat-samsung/include/plat/regs-fb.h
> +++ /dev/null
> @@ -1,403 +0,0 @@
> -/* arch/arm/plat-samsung/include/plat/regs-fb.h
> - *
> - * Copyright 2008 Openmoko, Inc.
> - * Copyright 2008 Simtec Electronics
> - * http://armlinux.simtec.co.uk/
> - * Ben Dooks <ben@simtec.co.uk>
> - *
> - * S3C Platform - new-style framebuffer register definitions
> - *
> - * This is the register set for the new style framebuffer interface
> - * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
> - * S3C64XX series such as the S3C6400 and S3C6410.
> - *
> - * The file does not contain the cpu specific items which are based on
> - * whichever architecture is selected, it only contains the core of the
> - * register set. See <mach/regs-fb.h> to get the specifics.
> - *
> - * Note, we changed to using regs-fb.h as it avoids any clashes with
> - * the original regs-lcd.h so out of the way of regs-lcd.h as well as
> - * indicating the newer block is much more than just an LCD interface.
> - *
> - * 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.
> -*/
> -
> -/* Please do not include this file directly, use <mach/regs-fb.h> to
> - * ensure all the localised SoC support is included as necessary.
> -*/
> -
> -/* VIDCON0 */
> -
> -#define VIDCON0 (0x00)
> -#define VIDCON0_INTERLACE (1 << 29)
> -#define VIDCON0_VIDOUT_MASK (0x3 << 26)
> -#define VIDCON0_VIDOUT_SHIFT (26)
> -#define VIDCON0_VIDOUT_RGB (0x0 << 26)
> -#define VIDCON0_VIDOUT_TV (0x1 << 26)
> -#define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26)
> -#define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26)
> -
> -#define VIDCON0_L1_DATA_MASK (0x7 << 23)
> -#define VIDCON0_L1_DATA_SHIFT (23)
> -#define VIDCON0_L1_DATA_16BPP (0x0 << 23)
> -#define VIDCON0_L1_DATA_18BPP16 (0x1 << 23)
> -#define VIDCON0_L1_DATA_18BPP9 (0x2 << 23)
> -#define VIDCON0_L1_DATA_24BPP (0x3 << 23)
> -#define VIDCON0_L1_DATA_18BPP (0x4 << 23)
> -#define VIDCON0_L1_DATA_16BPP8 (0x5 << 23)
> -
> -#define VIDCON0_L0_DATA_MASK (0x7 << 20)
> -#define VIDCON0_L0_DATA_SHIFT (20)
> -#define VIDCON0_L0_DATA_16BPP (0x0 << 20)
> -#define VIDCON0_L0_DATA_18BPP16 (0x1 << 20)
> -#define VIDCON0_L0_DATA_18BPP9 (0x2 << 20)
> -#define VIDCON0_L0_DATA_24BPP (0x3 << 20)
> -#define VIDCON0_L0_DATA_18BPP (0x4 << 20)
> -#define VIDCON0_L0_DATA_16BPP8 (0x5 << 20)
> -
> -#define VIDCON0_PNRMODE_MASK (0x3 << 17)
> -#define VIDCON0_PNRMODE_SHIFT (17)
> -#define VIDCON0_PNRMODE_RGB (0x0 << 17)
> -#define VIDCON0_PNRMODE_BGR (0x1 << 17)
> -#define VIDCON0_PNRMODE_SERIAL_RGB (0x2 << 17)
> -#define VIDCON0_PNRMODE_SERIAL_BGR (0x3 << 17)
> -
> -#define VIDCON0_CLKVALUP (1 << 16)
> -#define VIDCON0_CLKVAL_F_MASK (0xff << 6)
> -#define VIDCON0_CLKVAL_F_SHIFT (6)
> -#define VIDCON0_CLKVAL_F_LIMIT (0xff)
> -#define VIDCON0_CLKVAL_F(_x) ((_x) << 6)
> -#define VIDCON0_VLCKFREE (1 << 5)
> -#define VIDCON0_CLKDIR (1 << 4)
> -
> -#define VIDCON0_CLKSEL_MASK (0x3 << 2)
> -#define VIDCON0_CLKSEL_SHIFT (2)
> -#define VIDCON0_CLKSEL_HCLK (0x0 << 2)
> -#define VIDCON0_CLKSEL_LCD (0x1 << 2)
> -#define VIDCON0_CLKSEL_27M (0x3 << 2)
> -
> -#define VIDCON0_ENVID (1 << 1)
> -#define VIDCON0_ENVID_F (1 << 0)
> -
> -#define VIDCON1 (0x04)
> -#define VIDCON1_LINECNT_MASK (0x7ff << 16)
> -#define VIDCON1_LINECNT_SHIFT (16)
> -#define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff)
> -#define VIDCON1_VSTATUS_MASK (0x3 << 13)
> -#define VIDCON1_VSTATUS_SHIFT (13)
> -#define VIDCON1_VSTATUS_VSYNC (0x0 << 13)
> -#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13)
> -#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13)
> -#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13)
> -#define VIDCON1_VCLK_MASK (0x3 << 9)
> -#define VIDCON1_VCLK_HOLD (0x0 << 9)
> -#define VIDCON1_VCLK_RUN (0x1 << 9)
> -
> -#define VIDCON1_INV_VCLK (1 << 7)
> -#define VIDCON1_INV_HSYNC (1 << 6)
> -#define VIDCON1_INV_VSYNC (1 << 5)
> -#define VIDCON1_INV_VDEN (1 << 4)
> -
> -/* VIDCON2 */
> -
> -#define VIDCON2 (0x08)
> -#define VIDCON2_EN601 (1 << 23)
> -#define VIDCON2_TVFMTSEL_SW (1 << 14)
> -
> -#define VIDCON2_TVFMTSEL1_MASK (0x3 << 12)
> -#define VIDCON2_TVFMTSEL1_SHIFT (12)
> -#define VIDCON2_TVFMTSEL1_RGB (0x0 << 12)
> -#define VIDCON2_TVFMTSEL1_YUV422 (0x1 << 12)
> -#define VIDCON2_TVFMTSEL1_YUV444 (0x2 << 12)
> -
> -#define VIDCON2_ORGYCbCr (1 << 8)
> -#define VIDCON2_YUVORDCrCb (1 << 7)
> -
> -/* PRTCON (S3C6410, S5PC100)
> - * Might not be present in the S3C6410 documentation,
> - * but tests prove it's there almost for sure; shouldn't hurt in any case.
> - */
> -#define PRTCON (0x0c)
> -#define PRTCON_PROTECT (1 << 11)
> -
> -/* VIDTCON0 */
> -
> -#define VIDTCON0_VBPDE_MASK (0xff << 24)
> -#define VIDTCON0_VBPDE_SHIFT (24)
> -#define VIDTCON0_VBPDE_LIMIT (0xff)
> -#define VIDTCON0_VBPDE(_x) ((_x) << 24)
> -
> -#define VIDTCON0_VBPD_MASK (0xff << 16)
> -#define VIDTCON0_VBPD_SHIFT (16)
> -#define VIDTCON0_VBPD_LIMIT (0xff)
> -#define VIDTCON0_VBPD(_x) ((_x) << 16)
> -
> -#define VIDTCON0_VFPD_MASK (0xff << 8)
> -#define VIDTCON0_VFPD_SHIFT (8)
> -#define VIDTCON0_VFPD_LIMIT (0xff)
> -#define VIDTCON0_VFPD(_x) ((_x) << 8)
> -
> -#define VIDTCON0_VSPW_MASK (0xff << 0)
> -#define VIDTCON0_VSPW_SHIFT (0)
> -#define VIDTCON0_VSPW_LIMIT (0xff)
> -#define VIDTCON0_VSPW(_x) ((_x) << 0)
> -
> -/* VIDTCON1 */
> -
> -#define VIDTCON1_VFPDE_MASK (0xff << 24)
> -#define VIDTCON1_VFPDE_SHIFT (24)
> -#define VIDTCON1_VFPDE_LIMIT (0xff)
> -#define VIDTCON1_VFPDE(_x) ((_x) << 24)
> -
> -#define VIDTCON1_HBPD_MASK (0xff << 16)
> -#define VIDTCON1_HBPD_SHIFT (16)
> -#define VIDTCON1_HBPD_LIMIT (0xff)
> -#define VIDTCON1_HBPD(_x) ((_x) << 16)
> -
> -#define VIDTCON1_HFPD_MASK (0xff << 8)
> -#define VIDTCON1_HFPD_SHIFT (8)
> -#define VIDTCON1_HFPD_LIMIT (0xff)
> -#define VIDTCON1_HFPD(_x) ((_x) << 8)
> -
> -#define VIDTCON1_HSPW_MASK (0xff << 0)
> -#define VIDTCON1_HSPW_SHIFT (0)
> -#define VIDTCON1_HSPW_LIMIT (0xff)
> -#define VIDTCON1_HSPW(_x) ((_x) << 0)
> -
> -#define VIDTCON2 (0x18)
> -#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23)
> -#define VIDTCON2_LINEVAL_MASK (0x7ff << 11)
> -#define VIDTCON2_LINEVAL_SHIFT (11)
> -#define VIDTCON2_LINEVAL_LIMIT (0x7ff)
> -#define VIDTCON2_LINEVAL(_x) (((_x) & 0x7ff) << 11)
> -
> -#define VIDTCON2_HOZVAL_E(_x) ((((_x) & 0x800) >> 11) << 22)
> -#define VIDTCON2_HOZVAL_MASK (0x7ff << 0)
> -#define VIDTCON2_HOZVAL_SHIFT (0)
> -#define VIDTCON2_HOZVAL_LIMIT (0x7ff)
> -#define VIDTCON2_HOZVAL(_x) (((_x) & 0x7ff) << 0)
> -
> -/* WINCONx */
> -
> -
> -#define WINCONx_BITSWP (1 << 18)
> -#define WINCONx_BYTSWP (1 << 17)
> -#define WINCONx_HAWSWP (1 << 16)
> -#define WINCONx_WSWP (1 << 15)
> -#define WINCONx_BURSTLEN_MASK (0x3 << 9)
> -#define WINCONx_BURSTLEN_SHIFT (9)
> -#define WINCONx_BURSTLEN_16WORD (0x0 << 9)
> -#define WINCONx_BURSTLEN_8WORD (0x1 << 9)
> -#define WINCONx_BURSTLEN_4WORD (0x2 << 9)
> -
> -#define WINCONx_ENWIN (1 << 0)
> -#define WINCON0_BPPMODE_MASK (0xf << 2)
> -#define WINCON0_BPPMODE_SHIFT (2)
> -#define WINCON0_BPPMODE_1BPP (0x0 << 2)
> -#define WINCON0_BPPMODE_2BPP (0x1 << 2)
> -#define WINCON0_BPPMODE_4BPP (0x2 << 2)
> -#define WINCON0_BPPMODE_8BPP_PALETTE (0x3 << 2)
> -#define WINCON0_BPPMODE_16BPP_565 (0x5 << 2)
> -#define WINCON0_BPPMODE_16BPP_1555 (0x7 << 2)
> -#define WINCON0_BPPMODE_18BPP_666 (0x8 << 2)
> -#define WINCON0_BPPMODE_24BPP_888 (0xb << 2)
> -
> -#define WINCON1_BLD_PIX (1 << 6)
> -
> -#define WINCON1_ALPHA_SEL (1 << 1)
> -#define WINCON1_BPPMODE_MASK (0xf << 2)
> -#define WINCON1_BPPMODE_SHIFT (2)
> -#define WINCON1_BPPMODE_1BPP (0x0 << 2)
> -#define WINCON1_BPPMODE_2BPP (0x1 << 2)
> -#define WINCON1_BPPMODE_4BPP (0x2 << 2)
> -#define WINCON1_BPPMODE_8BPP_PALETTE (0x3 << 2)
> -#define WINCON1_BPPMODE_8BPP_1232 (0x4 << 2)
> -#define WINCON1_BPPMODE_16BPP_565 (0x5 << 2)
> -#define WINCON1_BPPMODE_16BPP_A1555 (0x6 << 2)
> -#define WINCON1_BPPMODE_16BPP_I1555 (0x7 << 2)
> -#define WINCON1_BPPMODE_18BPP_666 (0x8 << 2)
> -#define WINCON1_BPPMODE_18BPP_A1665 (0x9 << 2)
> -#define WINCON1_BPPMODE_19BPP_A1666 (0xa << 2)
> -#define WINCON1_BPPMODE_24BPP_888 (0xb << 2)
> -#define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2)
> -#define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2)
> -#define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2)
> -
> -/* S5PV210 */
> -#define SHADOWCON (0x34)
> -#define SHADOWCON_WINx_PROTECT(_win) (1 << (10 + (_win)))
> -/* DMA channels (all windows) */
> -#define SHADOWCON_CHx_ENABLE(_win) (1 << (_win))
> -/* Local input channels (windows 0-2) */
> -#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win)))
> -
> -#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
> -#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11)
> -#define VIDOSDxA_TOPLEFT_X_SHIFT (11)
> -#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff)
> -#define VIDOSDxA_TOPLEFT_X(_x) (((_x) & 0x7ff) << 11)
> -
> -#define VIDOSDxA_TOPLEFT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
> -#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0)
> -#define VIDOSDxA_TOPLEFT_Y_SHIFT (0)
> -#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff)
> -#define VIDOSDxA_TOPLEFT_Y(_x) (((_x) & 0x7ff) << 0)
> -
> -#define VIDOSDxB_BOTRIGHT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
> -#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11)
> -#define VIDOSDxB_BOTRIGHT_X_SHIFT (11)
> -#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff)
> -#define VIDOSDxB_BOTRIGHT_X(_x) (((_x) & 0x7ff) << 11)
> -
> -#define VIDOSDxB_BOTRIGHT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
> -#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0)
> -#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0)
> -#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff)
> -#define VIDOSDxB_BOTRIGHT_Y(_x) (((_x) & 0x7ff) << 0)
> -
> -/* For VIDOSD[1..4]C */
> -#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20)
> -#define VIDISD14C_ALPHA0_G_MASK (0xf << 16)
> -#define VIDISD14C_ALPHA0_G_SHIFT (16)
> -#define VIDISD14C_ALPHA0_G_LIMIT (0xf)
> -#define VIDISD14C_ALPHA0_G(_x) ((_x) << 16)
> -#define VIDISD14C_ALPHA0_B_MASK (0xf << 12)
> -#define VIDISD14C_ALPHA0_B_SHIFT (12)
> -#define VIDISD14C_ALPHA0_B_LIMIT (0xf)
> -#define VIDISD14C_ALPHA0_B(_x) ((_x) << 12)
> -#define VIDISD14C_ALPHA1_R_MASK (0xf << 8)
> -#define VIDISD14C_ALPHA1_R_SHIFT (8)
> -#define VIDISD14C_ALPHA1_R_LIMIT (0xf)
> -#define VIDISD14C_ALPHA1_R(_x) ((_x) << 8)
> -#define VIDISD14C_ALPHA1_G_MASK (0xf << 4)
> -#define VIDISD14C_ALPHA1_G_SHIFT (4)
> -#define VIDISD14C_ALPHA1_G_LIMIT (0xf)
> -#define VIDISD14C_ALPHA1_G(_x) ((_x) << 4)
> -#define VIDISD14C_ALPHA1_B_MASK (0xf << 0)
> -#define VIDISD14C_ALPHA1_B_SHIFT (0)
> -#define VIDISD14C_ALPHA1_B_LIMIT (0xf)
> -#define VIDISD14C_ALPHA1_B(_x) ((_x) << 0)
> -
> -/* Video buffer addresses */
> -#define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8))
> -#define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8))
> -#define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8))
> -#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8))
> -#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4))
> -
> -#define VIDW_BUF_SIZE_OFFSET_E(_x) ((((_x) & 0x2000) >> 13) << 27)
> -#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13)
> -#define VIDW_BUF_SIZE_OFFSET_SHIFT (13)
> -#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff)
> -#define VIDW_BUF_SIZE_OFFSET(_x) (((_x) & 0x1fff) << 13)
> -
> -#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x) ((((_x) & 0x2000) >> 13) << 26)
> -#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0)
> -#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0)
> -#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff)
> -#define VIDW_BUF_SIZE_PAGEWIDTH(_x) (((_x) & 0x1fff) << 0)
> -
> -/* Interrupt controls and status */
> -
> -#define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20)
> -#define VIDINTCON0_FIFOINTERVAL_SHIFT (20)
> -#define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f)
> -#define VIDINTCON0_FIFOINTERVAL(_x) ((_x) << 20)
> -
> -#define VIDINTCON0_INT_SYSMAINCON (1 << 19)
> -#define VIDINTCON0_INT_SYSSUBCON (1 << 18)
> -#define VIDINTCON0_INT_I80IFDONE (1 << 17)
> -
> -#define VIDINTCON0_FRAMESEL0_MASK (0x3 << 15)
> -#define VIDINTCON0_FRAMESEL0_SHIFT (15)
> -#define VIDINTCON0_FRAMESEL0_BACKPORCH (0x0 << 15)
> -#define VIDINTCON0_FRAMESEL0_VSYNC (0x1 << 15)
> -#define VIDINTCON0_FRAMESEL0_ACTIVE (0x2 << 15)
> -#define VIDINTCON0_FRAMESEL0_FRONTPORCH (0x3 << 15)
> -
> -#define VIDINTCON0_FRAMESEL1 (1 << 13)
> -#define VIDINTCON0_FRAMESEL1_MASK (0x3 << 13)
> -#define VIDINTCON0_FRAMESEL1_NONE (0x0 << 13)
> -#define VIDINTCON0_FRAMESEL1_BACKPORCH (0x1 << 13)
> -#define VIDINTCON0_FRAMESEL1_VSYNC (0x2 << 13)
> -#define VIDINTCON0_FRAMESEL1_FRONTPORCH (0x3 << 13)
> -
> -#define VIDINTCON0_INT_FRAME (1 << 12)
> -#define VIDINTCON0_FIFIOSEL_MASK (0x7f << 5)
> -#define VIDINTCON0_FIFIOSEL_SHIFT (5)
> -#define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5)
> -#define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5)
> -
> -#define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2)
> -#define VIDINTCON0_FIFOLEVEL_SHIFT (2)
> -#define VIDINTCON0_FIFOLEVEL_TO25PC (0x0 << 2)
> -#define VIDINTCON0_FIFOLEVEL_TO50PC (0x1 << 2)
> -#define VIDINTCON0_FIFOLEVEL_TO75PC (0x2 << 2)
> -#define VIDINTCON0_FIFOLEVEL_EMPTY (0x3 << 2)
> -#define VIDINTCON0_FIFOLEVEL_FULL (0x4 << 2)
> -
> -#define VIDINTCON0_INT_FIFO_MASK (0x3 << 0)
> -#define VIDINTCON0_INT_FIFO_SHIFT (0)
> -#define VIDINTCON0_INT_ENABLE (1 << 0)
> -
> -#define VIDINTCON1 (0x134)
> -#define VIDINTCON1_INT_I180 (1 << 2)
> -#define VIDINTCON1_INT_FRAME (1 << 1)
> -#define VIDINTCON1_INT_FIFO (1 << 0)
> -
> -/* Window colour-key control registers */
> -#define WKEYCON (0x140) /* 6410,V210 */
> -
> -#define WKEYCON0 (0x00)
> -#define WKEYCON1 (0x04)
> -
> -#define WxKEYCON0_KEYBL_EN (1 << 26)
> -#define WxKEYCON0_KEYEN_F (1 << 25)
> -#define WxKEYCON0_DIRCON (1 << 24)
> -#define WxKEYCON0_COMPKEY_MASK (0xffffff << 0)
> -#define WxKEYCON0_COMPKEY_SHIFT (0)
> -#define WxKEYCON0_COMPKEY_LIMIT (0xffffff)
> -#define WxKEYCON0_COMPKEY(_x) ((_x) << 0)
> -#define WxKEYCON1_COLVAL_MASK (0xffffff << 0)
> -#define WxKEYCON1_COLVAL_SHIFT (0)
> -#define WxKEYCON1_COLVAL_LIMIT (0xffffff)
> -#define WxKEYCON1_COLVAL(_x) ((_x) << 0)
> -
> -
> -/* Window blanking (MAP) */
> -
> -#define WINxMAP_MAP (1 << 24)
> -#define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0)
> -#define WINxMAP_MAP_COLOUR_SHIFT (0)
> -#define WINxMAP_MAP_COLOUR_LIMIT (0xffffff)
> -#define WINxMAP_MAP_COLOUR(_x) ((_x) << 0)
> -
> -#define WPALCON_PAL_UPDATE (1 << 9)
> -#define WPALCON_W1PAL_MASK (0x7 << 3)
> -#define WPALCON_W1PAL_SHIFT (3)
> -#define WPALCON_W1PAL_25BPP_A888 (0x0 << 3)
> -#define WPALCON_W1PAL_24BPP (0x1 << 3)
> -#define WPALCON_W1PAL_19BPP_A666 (0x2 << 3)
> -#define WPALCON_W1PAL_18BPP_A665 (0x3 << 3)
> -#define WPALCON_W1PAL_18BPP (0x4 << 3)
> -#define WPALCON_W1PAL_16BPP_A555 (0x5 << 3)
> -#define WPALCON_W1PAL_16BPP_565 (0x6 << 3)
> -
> -#define WPALCON_W0PAL_MASK (0x7 << 0)
> -#define WPALCON_W0PAL_SHIFT (0)
> -#define WPALCON_W0PAL_25BPP_A888 (0x0 << 0)
> -#define WPALCON_W0PAL_24BPP (0x1 << 0)
> -#define WPALCON_W0PAL_19BPP_A666 (0x2 << 0)
> -#define WPALCON_W0PAL_18BPP_A665 (0x3 << 0)
> -#define WPALCON_W0PAL_18BPP (0x4 << 0)
> -#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0)
> -#define WPALCON_W0PAL_16BPP_565 (0x6 << 0)
> -
> -/* Blending equation control */
> -#define BLENDCON (0x260)
> -#define BLENDCON_NEW_MASK (1 << 0)
> -#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
> -#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
> -
> diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
> new file mode 100644
> index 0000000..1b5ff4c
> --- /dev/null
> +++ b/include/video/samsung_fimd.h
> @@ -0,0 +1,533 @@
> +/* include/video/samsung_fimd.h
> + *
> + * Copyright 2008 Openmoko, Inc.
> + * Copyright 2008 Simtec Electronics
> + * http://armlinux.simtec.co.uk/
> + * Ben Dooks <ben@simtec.co.uk>
> + *
> + * S3C Platform - new-style fimd and framebuffer register definitions
> + *
> + * This is the register set for the fimd and new style framebuffer interface
> + * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
> + * S3C64XX series such as the S3C6400 and S3C6410.
> + *
> + * The file does not contain the cpu specific items which are based on
> + * whichever architecture is selected, it only contains the core of the
> + * register set. See <mach/regs-fb.h> to get the specifics.
> + *
> + * 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.
> +*/
> +
> +/* VIDCON0 */
> +
> +#define VIDCON0 (0x00)
> +#define VIDCON0_INTERLACE (1 << 29)
> +#define VIDCON0_VIDOUT_MASK (0x3 << 26)
> +#define VIDCON0_VIDOUT_SHIFT (26)
> +#define VIDCON0_VIDOUT_RGB (0x0 << 26)
> +#define VIDCON0_VIDOUT_TV (0x1 << 26)
> +#define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26)
> +#define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26)
> +
> +#define VIDCON0_L1_DATA_MASK (0x7 << 23)
> +#define VIDCON0_L1_DATA_SHIFT (23)
> +#define VIDCON0_L1_DATA_16BPP (0x0 << 23)
> +#define VIDCON0_L1_DATA_18BPP16 (0x1 << 23)
> +#define VIDCON0_L1_DATA_18BPP9 (0x2 << 23)
> +#define VIDCON0_L1_DATA_24BPP (0x3 << 23)
> +#define VIDCON0_L1_DATA_18BPP (0x4 << 23)
> +#define VIDCON0_L1_DATA_16BPP8 (0x5 << 23)
> +
> +#define VIDCON0_L0_DATA_MASK (0x7 << 20)
> +#define VIDCON0_L0_DATA_SHIFT (20)
> +#define VIDCON0_L0_DATA_16BPP (0x0 << 20)
> +#define VIDCON0_L0_DATA_18BPP16 (0x1 << 20)
> +#define VIDCON0_L0_DATA_18BPP9 (0x2 << 20)
> +#define VIDCON0_L0_DATA_24BPP (0x3 << 20)
> +#define VIDCON0_L0_DATA_18BPP (0x4 << 20)
> +#define VIDCON0_L0_DATA_16BPP8 (0x5 << 20)
> +
> +#define VIDCON0_PNRMODE_MASK (0x3 << 17)
> +#define VIDCON0_PNRMODE_SHIFT (17)
> +#define VIDCON0_PNRMODE_RGB (0x0 << 17)
> +#define VIDCON0_PNRMODE_BGR (0x1 << 17)
> +#define VIDCON0_PNRMODE_SERIAL_RGB (0x2 << 17)
> +#define VIDCON0_PNRMODE_SERIAL_BGR (0x3 << 17)
> +
> +#define VIDCON0_CLKVALUP (1 << 16)
> +#define VIDCON0_CLKVAL_F_MASK (0xff << 6)
> +#define VIDCON0_CLKVAL_F_SHIFT (6)
> +#define VIDCON0_CLKVAL_F_LIMIT (0xff)
> +#define VIDCON0_CLKVAL_F(_x) ((_x) << 6)
> +#define VIDCON0_VLCKFREE (1 << 5)
> +#define VIDCON0_CLKDIR (1 << 4)
> +
> +#define VIDCON0_CLKSEL_MASK (0x3 << 2)
> +#define VIDCON0_CLKSEL_SHIFT (2)
> +#define VIDCON0_CLKSEL_HCLK (0x0 << 2)
> +#define VIDCON0_CLKSEL_LCD (0x1 << 2)
> +#define VIDCON0_CLKSEL_27M (0x3 << 2)
> +
> +#define VIDCON0_ENVID (1 << 1)
> +#define VIDCON0_ENVID_F (1 << 0)
> +
> +#define VIDCON1 (0x04)
> +#define VIDCON1_LINECNT_MASK (0x7ff << 16)
> +#define VIDCON1_LINECNT_SHIFT (16)
> +#define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff)
> +#define VIDCON1_VSTATUS_MASK (0x3 << 13)
> +#define VIDCON1_VSTATUS_SHIFT (13)
> +#define VIDCON1_VSTATUS_VSYNC (0x0 << 13)
> +#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13)
> +#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13)
> +#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13)
> +#define VIDCON1_VCLK_MASK (0x3 << 9)
> +#define VIDCON1_VCLK_HOLD (0x0 << 9)
> +#define VIDCON1_VCLK_RUN (0x1 << 9)
> +
> +#define VIDCON1_INV_VCLK (1 << 7)
> +#define VIDCON1_INV_HSYNC (1 << 6)
> +#define VIDCON1_INV_VSYNC (1 << 5)
> +#define VIDCON1_INV_VDEN (1 << 4)
> +
> +/* VIDCON2 */
> +
> +#define VIDCON2 (0x08)
> +#define VIDCON2_EN601 (1 << 23)
> +#define VIDCON2_TVFMTSEL_SW (1 << 14)
> +
> +#define VIDCON2_TVFMTSEL1_MASK (0x3 << 12)
> +#define VIDCON2_TVFMTSEL1_SHIFT (12)
> +#define VIDCON2_TVFMTSEL1_RGB (0x0 << 12)
> +#define VIDCON2_TVFMTSEL1_YUV422 (0x1 << 12)
> +#define VIDCON2_TVFMTSEL1_YUV444 (0x2 << 12)
> +
> +#define VIDCON2_ORGYCbCr (1 << 8)
> +#define VIDCON2_YUVORDCrCb (1 << 7)
> +
> +/* PRTCON (S3C6410, S5PC100)
> + * Might not be present in the S3C6410 documentation,
> + * but tests prove it's there almost for sure; shouldn't hurt in any case.
> + */
> +#define PRTCON (0x0c)
> +#define PRTCON_PROTECT (1 << 11)
> +
> +/* VIDTCON0 */
> +
> +#define VIDTCON0_VBPDE_MASK (0xff << 24)
> +#define VIDTCON0_VBPDE_SHIFT (24)
> +#define VIDTCON0_VBPDE_LIMIT (0xff)
> +#define VIDTCON0_VBPDE(_x) ((_x) << 24)
> +
> +#define VIDTCON0_VBPD_MASK (0xff << 16)
> +#define VIDTCON0_VBPD_SHIFT (16)
> +#define VIDTCON0_VBPD_LIMIT (0xff)
> +#define VIDTCON0_VBPD(_x) ((_x) << 16)
> +
> +#define VIDTCON0_VFPD_MASK (0xff << 8)
> +#define VIDTCON0_VFPD_SHIFT (8)
> +#define VIDTCON0_VFPD_LIMIT (0xff)
> +#define VIDTCON0_VFPD(_x) ((_x) << 8)
> +
> +#define VIDTCON0_VSPW_MASK (0xff << 0)
> +#define VIDTCON0_VSPW_SHIFT (0)
> +#define VIDTCON0_VSPW_LIMIT (0xff)
> +#define VIDTCON0_VSPW(_x) ((_x) << 0)
> +
> +/* VIDTCON1 */
> +
> +#define VIDTCON1_VFPDE_MASK (0xff << 24)
> +#define VIDTCON1_VFPDE_SHIFT (24)
> +#define VIDTCON1_VFPDE_LIMIT (0xff)
> +#define VIDTCON1_VFPDE(_x) ((_x) << 24)
> +
> +#define VIDTCON1_HBPD_MASK (0xff << 16)
> +#define VIDTCON1_HBPD_SHIFT (16)
> +#define VIDTCON1_HBPD_LIMIT (0xff)
> +#define VIDTCON1_HBPD(_x) ((_x) << 16)
> +
> +#define VIDTCON1_HFPD_MASK (0xff << 8)
> +#define VIDTCON1_HFPD_SHIFT (8)
> +#define VIDTCON1_HFPD_LIMIT (0xff)
> +#define VIDTCON1_HFPD(_x) ((_x) << 8)
> +
> +#define VIDTCON1_HSPW_MASK (0xff << 0)
> +#define VIDTCON1_HSPW_SHIFT (0)
> +#define VIDTCON1_HSPW_LIMIT (0xff)
> +#define VIDTCON1_HSPW(_x) ((_x) << 0)
> +
> +#define VIDTCON2 (0x18)
> +#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23)
> +#define VIDTCON2_LINEVAL_MASK (0x7ff << 11)
> +#define VIDTCON2_LINEVAL_SHIFT (11)
> +#define VIDTCON2_LINEVAL_LIMIT (0x7ff)
> +#define VIDTCON2_LINEVAL(_x) (((_x) & 0x7ff) << 11)
> +
> +#define VIDTCON2_HOZVAL_E(_x) ((((_x) & 0x800) >> 11) << 22)
> +#define VIDTCON2_HOZVAL_MASK (0x7ff << 0)
> +#define VIDTCON2_HOZVAL_SHIFT (0)
> +#define VIDTCON2_HOZVAL_LIMIT (0x7ff)
> +#define VIDTCON2_HOZVAL(_x) (((_x) & 0x7ff) << 0)
> +
> +/* WINCONx */
> +
> +
> +#define WINCONx_BITSWP (1 << 18)
> +#define WINCONx_BYTSWP (1 << 17)
> +#define WINCONx_HAWSWP (1 << 16)
> +#define WINCONx_WSWP (1 << 15)
> +#define WINCONx_BURSTLEN_MASK (0x3 << 9)
> +#define WINCONx_BURSTLEN_SHIFT (9)
> +#define WINCONx_BURSTLEN_16WORD (0x0 << 9)
> +#define WINCONx_BURSTLEN_8WORD (0x1 << 9)
> +#define WINCONx_BURSTLEN_4WORD (0x2 << 9)
> +
> +#define WINCONx_ENWIN (1 << 0)
> +#define WINCON0_BPPMODE_MASK (0xf << 2)
> +#define WINCON0_BPPMODE_SHIFT (2)
> +#define WINCON0_BPPMODE_1BPP (0x0 << 2)
> +#define WINCON0_BPPMODE_2BPP (0x1 << 2)
> +#define WINCON0_BPPMODE_4BPP (0x2 << 2)
> +#define WINCON0_BPPMODE_8BPP_PALETTE (0x3 << 2)
> +#define WINCON0_BPPMODE_16BPP_565 (0x5 << 2)
> +#define WINCON0_BPPMODE_16BPP_1555 (0x7 << 2)
> +#define WINCON0_BPPMODE_18BPP_666 (0x8 << 2)
> +#define WINCON0_BPPMODE_24BPP_888 (0xb << 2)
> +
> +#define WINCON1_BLD_PIX (1 << 6)
> +
> +#define WINCON1_ALPHA_SEL (1 << 1)
> +#define WINCON1_BPPMODE_MASK (0xf << 2)
> +#define WINCON1_BPPMODE_SHIFT (2)
> +#define WINCON1_BPPMODE_1BPP (0x0 << 2)
> +#define WINCON1_BPPMODE_2BPP (0x1 << 2)
> +#define WINCON1_BPPMODE_4BPP (0x2 << 2)
> +#define WINCON1_BPPMODE_8BPP_PALETTE (0x3 << 2)
> +#define WINCON1_BPPMODE_8BPP_1232 (0x4 << 2)
> +#define WINCON1_BPPMODE_16BPP_565 (0x5 << 2)
> +#define WINCON1_BPPMODE_16BPP_A1555 (0x6 << 2)
> +#define WINCON1_BPPMODE_16BPP_I1555 (0x7 << 2)
> +#define WINCON1_BPPMODE_18BPP_666 (0x8 << 2)
> +#define WINCON1_BPPMODE_18BPP_A1665 (0x9 << 2)
> +#define WINCON1_BPPMODE_19BPP_A1666 (0xa << 2)
> +#define WINCON1_BPPMODE_24BPP_888 (0xb << 2)
> +#define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2)
> +#define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2)
> +#define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2)
> +
> +/* S5PV210 */
> +#define SHADOWCON (0x34)
> +#define SHADOWCON_WINx_PROTECT(_win) (1 << (10 + (_win)))
> +/* DMA channels (all windows) */
> +#define SHADOWCON_CHx_ENABLE(_win) (1 << (_win))
> +/* Local input channels (windows 0-2) */
> +#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win)))
> +
> +#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
> +#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11)
> +#define VIDOSDxA_TOPLEFT_X_SHIFT (11)
> +#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff)
> +#define VIDOSDxA_TOPLEFT_X(_x) (((_x) & 0x7ff) << 11)
> +
> +#define VIDOSDxA_TOPLEFT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
> +#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0)
> +#define VIDOSDxA_TOPLEFT_Y_SHIFT (0)
> +#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff)
> +#define VIDOSDxA_TOPLEFT_Y(_x) (((_x) & 0x7ff) << 0)
> +
> +#define VIDOSDxB_BOTRIGHT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
> +#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11)
> +#define VIDOSDxB_BOTRIGHT_X_SHIFT (11)
> +#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff)
> +#define VIDOSDxB_BOTRIGHT_X(_x) (((_x) & 0x7ff) << 11)
> +
> +#define VIDOSDxB_BOTRIGHT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
> +#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0)
> +#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0)
> +#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff)
> +#define VIDOSDxB_BOTRIGHT_Y(_x) (((_x) & 0x7ff) << 0)
> +
> +/* For VIDOSD[1..4]C */
> +#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20)
> +#define VIDISD14C_ALPHA0_G_MASK (0xf << 16)
> +#define VIDISD14C_ALPHA0_G_SHIFT (16)
> +#define VIDISD14C_ALPHA0_G_LIMIT (0xf)
> +#define VIDISD14C_ALPHA0_G(_x) ((_x) << 16)
> +#define VIDISD14C_ALPHA0_B_MASK (0xf << 12)
> +#define VIDISD14C_ALPHA0_B_SHIFT (12)
> +#define VIDISD14C_ALPHA0_B_LIMIT (0xf)
> +#define VIDISD14C_ALPHA0_B(_x) ((_x) << 12)
> +#define VIDISD14C_ALPHA1_R_MASK (0xf << 8)
> +#define VIDISD14C_ALPHA1_R_SHIFT (8)
> +#define VIDISD14C_ALPHA1_R_LIMIT (0xf)
> +#define VIDISD14C_ALPHA1_R(_x) ((_x) << 8)
> +#define VIDISD14C_ALPHA1_G_MASK (0xf << 4)
> +#define VIDISD14C_ALPHA1_G_SHIFT (4)
> +#define VIDISD14C_ALPHA1_G_LIMIT (0xf)
> +#define VIDISD14C_ALPHA1_G(_x) ((_x) << 4)
> +#define VIDISD14C_ALPHA1_B_MASK (0xf << 0)
> +#define VIDISD14C_ALPHA1_B_SHIFT (0)
> +#define VIDISD14C_ALPHA1_B_LIMIT (0xf)
> +#define VIDISD14C_ALPHA1_B(_x) ((_x) << 0)
> +
> +/* Video buffer addresses */
> +#define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8))
> +#define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8))
> +#define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8))
> +#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8))
> +#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4))
> +
> +#define VIDW_BUF_SIZE_OFFSET_E(_x) ((((_x) & 0x2000) >> 13) << 27)
> +#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13)
> +#define VIDW_BUF_SIZE_OFFSET_SHIFT (13)
> +#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff)
> +#define VIDW_BUF_SIZE_OFFSET(_x) (((_x) & 0x1fff) << 13)
> +
> +#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x) ((((_x) & 0x2000) >> 13) << 26)
> +#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0)
> +#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0)
> +#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff)
> +#define VIDW_BUF_SIZE_PAGEWIDTH(_x) (((_x) & 0x1fff) << 0)
> +
> +/* Interrupt controls and status */
> +
> +#define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20)
> +#define VIDINTCON0_FIFOINTERVAL_SHIFT (20)
> +#define VIDINTCON0_FIFOINTERVAL_LIMIT (0x3f)
> +#define VIDINTCON0_FIFOINTERVAL(_x) ((_x) << 20)
> +
> +#define VIDINTCON0_INT_SYSMAINCON (1 << 19)
> +#define VIDINTCON0_INT_SYSSUBCON (1 << 18)
> +#define VIDINTCON0_INT_I80IFDONE (1 << 17)
> +
> +#define VIDINTCON0_FRAMESEL0_MASK (0x3 << 15)
> +#define VIDINTCON0_FRAMESEL0_SHIFT (15)
> +#define VIDINTCON0_FRAMESEL0_BACKPORCH (0x0 << 15)
> +#define VIDINTCON0_FRAMESEL0_VSYNC (0x1 << 15)
> +#define VIDINTCON0_FRAMESEL0_ACTIVE (0x2 << 15)
> +#define VIDINTCON0_FRAMESEL0_FRONTPORCH (0x3 << 15)
> +
> +#define VIDINTCON0_FRAMESEL1 (1 << 13)
> +#define VIDINTCON0_FRAMESEL1_MASK (0x3 << 13)
> +#define VIDINTCON0_FRAMESEL1_NONE (0x0 << 13)
> +#define VIDINTCON0_FRAMESEL1_BACKPORCH (0x1 << 13)
> +#define VIDINTCON0_FRAMESEL1_VSYNC (0x2 << 13)
> +#define VIDINTCON0_FRAMESEL1_FRONTPORCH (0x3 << 13)
> +
> +#define VIDINTCON0_INT_FRAME (1 << 12)
> +#define VIDINTCON0_FIFIOSEL_MASK (0x7f << 5)
> +#define VIDINTCON0_FIFIOSEL_SHIFT (5)
> +#define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5)
> +#define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5)
> +
> +#define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2)
> +#define VIDINTCON0_FIFOLEVEL_SHIFT (2)
> +#define VIDINTCON0_FIFOLEVEL_TO25PC (0x0 << 2)
> +#define VIDINTCON0_FIFOLEVEL_TO50PC (0x1 << 2)
> +#define VIDINTCON0_FIFOLEVEL_TO75PC (0x2 << 2)
> +#define VIDINTCON0_FIFOLEVEL_EMPTY (0x3 << 2)
> +#define VIDINTCON0_FIFOLEVEL_FULL (0x4 << 2)
> +
> +#define VIDINTCON0_INT_FIFO_MASK (0x3 << 0)
> +#define VIDINTCON0_INT_FIFO_SHIFT (0)
> +#define VIDINTCON0_INT_ENABLE (1 << 0)
> +
> +#define VIDINTCON1 (0x134)
> +#define VIDINTCON1_INT_I180 (1 << 2)
> +#define VIDINTCON1_INT_FRAME (1 << 1)
> +#define VIDINTCON1_INT_FIFO (1 << 0)
> +
> +/* Window colour-key control registers */
> +#define WKEYCON (0x140) /* 6410,V210 */
> +
> +#define WKEYCON0 (0x00)
> +#define WKEYCON1 (0x04)
> +
> +#define WxKEYCON0_KEYBL_EN (1 << 26)
> +#define WxKEYCON0_KEYEN_F (1 << 25)
> +#define WxKEYCON0_DIRCON (1 << 24)
> +#define WxKEYCON0_COMPKEY_MASK (0xffffff << 0)
> +#define WxKEYCON0_COMPKEY_SHIFT (0)
> +#define WxKEYCON0_COMPKEY_LIMIT (0xffffff)
> +#define WxKEYCON0_COMPKEY(_x) ((_x) << 0)
> +#define WxKEYCON1_COLVAL_MASK (0xffffff << 0)
> +#define WxKEYCON1_COLVAL_SHIFT (0)
> +#define WxKEYCON1_COLVAL_LIMIT (0xffffff)
> +#define WxKEYCON1_COLVAL(_x) ((_x) << 0)
> +
> +
> +/* Window blanking (MAP) */
> +
> +#define WINxMAP_MAP (1 << 24)
> +#define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0)
> +#define WINxMAP_MAP_COLOUR_SHIFT (0)
> +#define WINxMAP_MAP_COLOUR_LIMIT (0xffffff)
> +#define WINxMAP_MAP_COLOUR(_x) ((_x) << 0)
> +
> +#define WPALCON_PAL_UPDATE (1 << 9)
> +#define WPALCON_W1PAL_MASK (0x7 << 3)
> +#define WPALCON_W1PAL_SHIFT (3)
> +#define WPALCON_W1PAL_25BPP_A888 (0x0 << 3)
> +#define WPALCON_W1PAL_24BPP (0x1 << 3)
> +#define WPALCON_W1PAL_19BPP_A666 (0x2 << 3)
> +#define WPALCON_W1PAL_18BPP_A665 (0x3 << 3)
> +#define WPALCON_W1PAL_18BPP (0x4 << 3)
> +#define WPALCON_W1PAL_16BPP_A555 (0x5 << 3)
> +#define WPALCON_W1PAL_16BPP_565 (0x6 << 3)
> +
> +#define WPALCON_W0PAL_MASK (0x7 << 0)
> +#define WPALCON_W0PAL_SHIFT (0)
> +#define WPALCON_W0PAL_25BPP_A888 (0x0 << 0)
> +#define WPALCON_W0PAL_24BPP (0x1 << 0)
> +#define WPALCON_W0PAL_19BPP_A666 (0x2 << 0)
> +#define WPALCON_W0PAL_18BPP_A665 (0x3 << 0)
> +#define WPALCON_W0PAL_18BPP (0x4 << 0)
> +#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0)
> +#define WPALCON_W0PAL_16BPP_565 (0x6 << 0)
> +
> +/* Blending equation control */
> +#define BLENDCON (0x260)
> +#define BLENDCON_NEW_MASK (1 << 0)
> +#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
> +#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
> +
> +#define S3C_FB_MAX_WIN (5) /* number of hardware windows available. */
> +#define VIDCON1_FSTATUS_EVEN (1 << 15)
> +
> +/* Video timing controls */
> +#define VIDTCON0 (0x10)
> +#define VIDTCON1 (0x14)
> +#define VIDTCON2 (0x18)
> +
> +/* Window position controls */
> +
> +#define WINCON(_win) (0x20 + ((_win) * 4))
> +
> +/* OSD1 and OSD4 do not have register D */
> +
> +#define VIDOSD_BASE (0x40)
> +
> +#define VIDINTCON0 (0x130)
> +
> +/* WINCONx */
> +
> +#define WINCONx_CSCWIDTH_MASK (0x3 << 26)
> +#define WINCONx_CSCWIDTH_SHIFT (26)
> +#define WINCONx_CSCWIDTH_WIDE (0x0 << 26)
> +#define WINCONx_CSCWIDTH_NARROW (0x3 << 26)
> +
> +#define WINCONx_ENLOCAL (1 << 22)
> +#define WINCONx_BUFSTATUS (1 << 21)
> +#define WINCONx_BUFSEL (1 << 20)
> +#define WINCONx_BUFAUTOEN (1 << 19)
> +#define WINCONx_YCbCr (1 << 13)
> +
> +#define WINCON1_LOCALSEL_CAMIF (1 << 23)
> +
> +#define WINCON2_LOCALSEL_CAMIF (1 << 23)
> +#define WINCON2_BLD_PIX (1 << 6)
> +
> +#define WINCON2_ALPHA_SEL (1 << 1)
> +#define WINCON2_BPPMODE_MASK (0xf << 2)
> +#define WINCON2_BPPMODE_SHIFT (2)
> +#define WINCON2_BPPMODE_1BPP (0x0 << 2)
> +#define WINCON2_BPPMODE_2BPP (0x1 << 2)
> +#define WINCON2_BPPMODE_4BPP (0x2 << 2)
> +#define WINCON2_BPPMODE_8BPP_1232 (0x4 << 2)
> +#define WINCON2_BPPMODE_16BPP_565 (0x5 << 2)
> +#define WINCON2_BPPMODE_16BPP_A1555 (0x6 << 2)
> +#define WINCON2_BPPMODE_16BPP_I1555 (0x7 << 2)
> +#define WINCON2_BPPMODE_18BPP_666 (0x8 << 2)
> +#define WINCON2_BPPMODE_18BPP_A1665 (0x9 << 2)
> +#define WINCON2_BPPMODE_19BPP_A1666 (0xa << 2)
> +#define WINCON2_BPPMODE_24BPP_888 (0xb << 2)
> +#define WINCON2_BPPMODE_24BPP_A1887 (0xc << 2)
> +#define WINCON2_BPPMODE_25BPP_A1888 (0xd << 2)
> +#define WINCON2_BPPMODE_28BPP_A4888 (0xd << 2)
> +
> +#define WINCON3_BLD_PIX (1 << 6)
> +
> +#define WINCON3_ALPHA_SEL (1 << 1)
> +#define WINCON3_BPPMODE_MASK (0xf << 2)
> +#define WINCON3_BPPMODE_SHIFT (2)
> +#define WINCON3_BPPMODE_1BPP (0x0 << 2)
> +#define WINCON3_BPPMODE_2BPP (0x1 << 2)
> +#define WINCON3_BPPMODE_4BPP (0x2 << 2)
> +#define WINCON3_BPPMODE_16BPP_565 (0x5 << 2)
> +#define WINCON3_BPPMODE_16BPP_A1555 (0x6 << 2)
> +#define WINCON3_BPPMODE_16BPP_I1555 (0x7 << 2)
> +#define WINCON3_BPPMODE_18BPP_666 (0x8 << 2)
> +#define WINCON3_BPPMODE_18BPP_A1665 (0x9 << 2)
> +#define WINCON3_BPPMODE_19BPP_A1666 (0xa << 2)
> +#define WINCON3_BPPMODE_24BPP_888 (0xb << 2)
> +#define WINCON3_BPPMODE_24BPP_A1887 (0xc << 2)
> +#define WINCON3_BPPMODE_25BPP_A1888 (0xd << 2)
> +#define WINCON3_BPPMODE_28BPP_A4888 (0xd << 2)
> +
> +#define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5)
> +#define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5)
> +#define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5)
> +
> +#define DITHMODE (0x170)
> +#define WINxMAP(_win) (0x180 + ((_win) * 4))
> +
> +
> +#define DITHMODE_R_POS_MASK (0x3 << 5)
> +#define DITHMODE_R_POS_SHIFT (5)
> +#define DITHMODE_R_POS_8BIT (0x0 << 5)
> +#define DITHMODE_R_POS_6BIT (0x1 << 5)
> +#define DITHMODE_R_POS_5BIT (0x2 << 5)
> +
> +#define DITHMODE_G_POS_MASK (0x3 << 3)
> +#define DITHMODE_G_POS_SHIFT (3)
> +#define DITHMODE_G_POS_8BIT (0x0 << 3)
> +#define DITHMODE_G_POS_6BIT (0x1 << 3)
> +#define DITHMODE_G_POS_5BIT (0x2 << 3)
> +
> +#define DITHMODE_B_POS_MASK (0x3 << 1)
> +#define DITHMODE_B_POS_SHIFT (1)
> +#define DITHMODE_B_POS_8BIT (0x0 << 1)
> +#define DITHMODE_B_POS_6BIT (0x1 << 1)
> +#define DITHMODE_B_POS_5BIT (0x2 << 1)
> +
> +#define DITHMODE_DITH_EN (1 << 0)
> +
> +#define WPALCON (0x1A0)
> +
> +/* Palette control */
> +/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
> + * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
> +#define WPALCON_W4PAL_16BPP_A555 (1 << 8)
> +#define WPALCON_W3PAL_16BPP_A555 (1 << 7)
> +#define WPALCON_W2PAL_16BPP_A555 (1 << 6)
> +
> +
> +/* Notes on per-window bpp settings
> + *
> + * Value Win0 Win1 Win2 Win3 Win 4
> + * 0000 1(P) 1(P) 1(P) 1(P) 1(P)
> + * 0001 2(P) 2(P) 2(P) 2(P) 2(P)
> + * 0010 4(P) 4(P) 4(P) 4(P) -none-
> + * 0011 8(P) 8(P) -none- -none- -none-
> + * 0100 -none- 8(A232) 8(A232) -none- -none-
> + * 0101 16(565) 16(565) 16(565) 16(565) 16(565)
> + * 0110 -none- 16(A555) 16(A555) 16(A555) 16(A555)
> + * 0111 16(I555) 16(I565) 16(I555) 16(I555) 16(I555)
> + * 1000 18(666) 18(666) 18(666) 18(666) 18(666)
> + * 1001 -none- 18(A665) 18(A665) 18(A665) 16(A665)
> + * 1010 -none- 19(A666) 19(A666) 19(A666) 19(A666)
> + * 1011 24(888) 24(888) 24(888) 24(888) 24(888)
> + * 1100 -none- 24(A887) 24(A887) 24(A887) 24(A887)
> + * 1101 -none- 25(A888) 25(A888) 25(A888) 25(A888)
> + * 1110 -none- -none- -none- -none- -none-
> + * 1111 -none- -none- -none- -none- -none-
> +*/
> +
> +/*FIMD V8 REG OFFSET */
> +#define FIMD_V8_VIDTCON0 (0x20010)
> +#define FIMD_V8_VIDTCON1 (0x20014)
> +#define FIMD_V8_VIDTCON2 (0x20018)
> +#define FIMD_V8_VIDTCON3 (0x2001C)
> +#define FIMD_V8_VIDCON1 (0x20004)
CC'ed Marek.
To Leela Krishna Amudala,
Don't add these definitions for FIMD_V8_xxx registers, which are not related to current "regs-fb-v4.h and regs-fb.h".
Just "move" and "merge" regs-fb-v4.h and regs-fb.h to one header file, not "add" new definitions.
If you want to add these definitions, please make new patch for this.
Also, "#define FIMD_V8_xxx" is ugly.
I think that there is better way.
Please, find other way.
> --
> 1.7.0.4
^ permalink raw reply
* [PATCH 0/3] ARM: SAMSUNG: Move FIMD headers to include/video/
From: Leela Krishna Amudala @ 2012-07-30 8:57 UTC (permalink / raw)
To: linux-arm-kernel, linux-samsung-soc
Cc: dri-devel, linux-fbdev, ben-linux, inki.dae, kgene.kim, joshi,
jg1.han
This patchset moves the contents of regs-fb-v4.h and regs-fb.h from arch side
to include/video/samsung_fimd.h
This patchset is created and rebased against master branch of torvalds tree.
Tested on smdk5250 board, build tested for other boards.
Leela Krishna Amudala (3):
Move FIMD register headers to include/video/
arm: samsung: Include the modified FIMD header file
driver: Include the modified FIMD header file
arch/arm/mach-exynos/mach-nuri.c | 2 +-
arch/arm/mach-exynos/mach-origen.c | 2 +-
arch/arm/mach-exynos/mach-smdk4x12.c | 2 +-
arch/arm/mach-exynos/mach-smdkv310.c | 2 +-
arch/arm/mach-exynos/mach-universal_c210.c | 2 +-
arch/arm/mach-exynos/setup-fimd0.c | 2 +-
arch/arm/mach-s3c24xx/mach-smdk2416.c | 2 +-
arch/arm/mach-s3c64xx/mach-anw6410.c | 2 +-
arch/arm/mach-s3c64xx/mach-crag6410.c | 2 +-
arch/arm/mach-s3c64xx/mach-hmt.c | 2 +-
arch/arm/mach-s3c64xx/mach-mini6410.c | 2 +-
arch/arm/mach-s3c64xx/mach-ncp.c | 2 +-
arch/arm/mach-s3c64xx/mach-real6410.c | 2 +-
arch/arm/mach-s3c64xx/mach-smartq5.c | 2 +-
arch/arm/mach-s3c64xx/mach-smartq7.c | 2 +-
arch/arm/mach-s3c64xx/mach-smdk6410.c | 2 +-
arch/arm/mach-s5p64x0/mach-smdk6440.c | 2 +-
arch/arm/mach-s5p64x0/mach-smdk6450.c | 2 +-
arch/arm/mach-s5pc100/mach-smdkc100.c | 2 +-
arch/arm/mach-s5pv210/mach-aquila.c | 2 +-
arch/arm/mach-s5pv210/mach-goni.c | 2 +-
arch/arm/mach-s5pv210/mach-smdkv210.c | 2 +-
arch/arm/plat-samsung/include/plat/regs-fb-v4.h | 159 -------
arch/arm/plat-samsung/include/plat/regs-fb.h | 403 -----------------
drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 +-
drivers/video/s3c-fb.c | 2 +-
include/video/samsung_fimd.h | 533 +++++++++++++++++++++++
27 files changed, 557 insertions(+), 586 deletions(-)
delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
create mode 100644 include/video/samsung_fimd.h
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox