* Re: [PATCHv9][ 3/3] ARM: dts: cpuimx35 Add touchscreen support.
From: Eric Bénard @ 2013-11-21 8:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20131121050922.GF18477@ns203013.ovh.net>
Le Thu, 21 Nov 2013 06:09:22 +0100,
Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> a écrit :
> > + tsc2007: tsc2007@48 {
> > + compatible = "ti,tsc2007";
> > + reg = <0x48>;
> > + interrupt-parent = <&gpio3>;
> > + interrupts = <0x2 0x8>;
> > + gpios = <&gpio3 2 1>;
> as explain on the binding drop this gpios this is an IRQ not a gpio
>
> NACK
>
please read the tsc2007's code, in the patch there is :
+static int tsc2007_get_pendown_state_dt(struct tsc2007 *ts)
+{
+ return !gpio_get_value(ts->gpio);
+}
+
http://www.mail-archive.com/linux-input@vger.kernel.org/msg06765.html
Eric
^ permalink raw reply
* Re: [PATCHv9][ 1/3] Input: tsc2007: Add device tree support.
From: Eric Bénard @ 2013-11-21 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20131121050544.GE18477@ns203013.ovh.net>
Hi Jean Christophe,
Le Thu, 21 Nov 2013 06:05:44 +0100,
Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> a écrit :
> > +Optional properties:
> > +- gpios: the interrupt gpio the chip is connected to (trough the penirq pin).
> nack use interrupt property this a non-sense that we do today to pass irq via
> gpio property the should NEVER known it's a gpio just an irq
read previous email and you will see the GPIO is used to get the signal
level on the pin and not the IRQ.
Eric
^ permalink raw reply
* Re: [PATCHv9][ 3/3] ARM: dts: cpuimx35 Add touchscreen support.
From: Lothar Waßmann @ 2013-11-21 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20131121050922.GF18477@ns203013.ovh.net>
Hi,
Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 14:17 Fri 08 Nov , Denis Carikli wrote:
> > Cc: Rob Herring <rob.herring@calxeda.com>
> > Cc: Pawel Moll <pawel.moll@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Stephen Warren <swarren@wwwdotorg.org>
> > Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> > Cc: Grant Likely <grant.likely@linaro.org>
> > Cc: devicetree@vger.kernel.org
> > Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > Cc: linux-input@vger.kernel.org
> > Cc: Sascha Hauer <kernel@pengutronix.de>
> > Cc: linux-arm-kernel@lists.infradead.org
> > Cc: Lothar Waßmann <LW@KARO-electronics.de>
> > Cc: Shawn Guo <shawn.guo@linaro.org>
> > Cc: Eric Bénard <eric@eukrea.com>
> > Signed-off-by: Denis Carikli <denis@eukrea.com>
> > ---
> > ChangeLog v8->v9:
> > - Added Grant Likely in the cc list.
> > - Adapted to the removal of the pinctrl properties in the tsc2007 documentation.
> > - Fixed the gpios property (before, it was set to active high by error).
> >
> > ChangeLog v7->v8:
> > - Added Shawn Guo in the cc list.
> > ---
> > arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi | 21 +++++++++++++++++++++
> > 1 file changed, 21 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
> > index b9cb5a5..f25a40f 100644
> > --- a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
> > +++ b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
> > @@ -36,6 +36,27 @@
> > compatible = "nxp,pcf8563";
> > reg = <0x51>;
> > };
> > +
> > + tsc2007: tsc2007@48 {
> > + compatible = "ti,tsc2007";
> > + reg = <0x48>;
> > + interrupt-parent = <&gpio3>;
> > + interrupts = <0x2 0x8>;
> > + gpios = <&gpio3 2 1>;
> as explain on the binding drop this gpios this is an IRQ not a gpio
>
> NACK
The driver needs an interrupt to get notified about pendown events and
needs to poll the pendown signal to find out when the pen has been
lifted. Both the interrupt and the pendown signal happen to be
signalled on the same pin. Thus, IMO it is perfectly well to have the
interrupt property as well as the gpios property here.
How would you tell the driver which pin to poll for detecting the pen
up event?
Having a platform callback with hardcoded GPIO numbers is not an option.
Lothar Waßmann
--
___________________________________________________________
Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Geschäftsführer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996
www.karo-electronics.de | info@karo-electronics.de
___________________________________________________________
^ permalink raw reply
* Re: [PATCHv9][ 2/3] ARM: dts: cpuimx51 Add touchscreen support.
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-11-21 5:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1383916659-9988-2-git-send-email-denis@eukrea.com>
On 14:17 Fri 08 Nov , Denis Carikli wrote:
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: devicetree@vger.kernel.org
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: linux-input@vger.kernel.org
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Lothar Waßmann <LW@KARO-electronics.de>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Cc: Eric Bénard <eric@eukrea.com>
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> ChangeLog v8->v9:
> - Added Grant Likely in the Cc list.
> - Adapted to the removal of the pinctrl properties in the tsc2007 documentation.
> - Fixed the gpios property (before, it was set to active high by error).
>
> ChangeLog v7->v8:
> - Added Shawn Guo in the cc list.
> ---
> arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
> index b22841a..b04c65b 100644
> --- a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
> +++ b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
> @@ -42,11 +42,23 @@
> compatible = "nxp,pcf8563";
> reg = <0x51>;
> };
> +
> + tsc2007: tsc2007@49 {
> + compatible = "ti,tsc2007";
> + reg = <0x49>;
> + interrupt-parent = <&gpio4>;
> + interrupts = <0x0 0x8>;
> + gpios = <&gpio4 0 1>;
> + ti,x-plate-ohms = <180>;
as explain on the binding drop this gpios this is an IRQ not a gpio
NACK
Best Regards,
J.
> + };
> };
>
> &iomuxc {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_hog>;
> +
> imx51-eukrea {
> - pinctrl_tsc2007_1: tsc2007grp-1 {
> + pinctrl_hog: hoggrp {
> fsl,pins = <
> MX51_PAD_GPIO_NAND__GPIO_NAND 0x1f5
> MX51_PAD_NANDF_D8__GPIO4_0 0x1f5
> --
> 1.7.9.5
>
^ permalink raw reply
* Re: [PATCHv9][ 3/3] ARM: dts: cpuimx35 Add touchscreen support.
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-11-21 5:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1383916659-9988-3-git-send-email-denis@eukrea.com>
On 14:17 Fri 08 Nov , Denis Carikli wrote:
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: devicetree@vger.kernel.org
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: linux-input@vger.kernel.org
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Lothar Waßmann <LW@KARO-electronics.de>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Cc: Eric Bénard <eric@eukrea.com>
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> ChangeLog v8->v9:
> - Added Grant Likely in the cc list.
> - Adapted to the removal of the pinctrl properties in the tsc2007 documentation.
> - Fixed the gpios property (before, it was set to active high by error).
>
> ChangeLog v7->v8:
> - Added Shawn Guo in the cc list.
> ---
> arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
> index b9cb5a5..f25a40f 100644
> --- a/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
> +++ b/arch/arm/boot/dts/imx35-eukrea-cpuimx35.dtsi
> @@ -36,6 +36,27 @@
> compatible = "nxp,pcf8563";
> reg = <0x51>;
> };
> +
> + tsc2007: tsc2007@48 {
> + compatible = "ti,tsc2007";
> + reg = <0x48>;
> + interrupt-parent = <&gpio3>;
> + interrupts = <0x2 0x8>;
> + gpios = <&gpio3 2 1>;
as explain on the binding drop this gpios this is an IRQ not a gpio
NACK
Best Regards,
J.
> + ti,x-plate-ohms = <180>;
> + };
> +
> +};
> +
> +&iomuxc {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_hog>;
> +
> + imx35-eukrea {
> + pinctrl_hog: hoggrp {
> + fsl,pins = <MX35_PAD_ATA_DA2__GPIO3_2 0x80000000>;
> + };
> + };
> };
>
> &nfc {
> --
> 1.7.9.5
>
^ permalink raw reply
* Re: [PATCHv9][ 1/3] Input: tsc2007: Add device tree support.
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-11-21 5:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1383916659-9988-1-git-send-email-denis@eukrea.com>
On 14:17 Fri 08 Nov , Denis Carikli wrote:
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: devicetree@vger.kernel.org
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: linux-input@vger.kernel.org
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Lothar Waßmann <LW@KARO-electronics.de>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Cc: Eric Bénard <eric@eukrea.com>
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> ChangeLog v8->v9:
> - Added Grant Likely in the Cc list.
> - Removed the mention of the pinctrl properties in the documentation.
>
> ChangeLog v7->v8:
> - Fixed the lack of x and z fuzz properties.
> - The pendown gpio is better documented.
> - Added Shawn Guo in the cc list.
> ---
> .../bindings/input/touchscreen/tsc2007.txt | 41 ++++
> drivers/input/touchscreen/tsc2007.c | 204 ++++++++++++++++----
> 2 files changed, 204 insertions(+), 41 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
> new file mode 100644
> index 0000000..028aba66d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
> @@ -0,0 +1,41 @@
> +* Texas Instruments tsc2007 touchscreen controller
> +
> +Required properties:
> +- compatible: must be "ti,tsc2007".
> +- reg: I2C address of the chip.
> +- ti,x-plate-ohms: X-plate resistance in ohms.
> +
> +Optional properties:
> +- gpios: the interrupt gpio the chip is connected to (trough the penirq pin).
nack use interrupt property this a non-sense that we do today to pass irq via
gpio property the should NEVER known it's a gpio just an irq
> + The penirq pin goes to low when the panel is touched.
> + (see GPIO binding[1] for more details).
> +- interrupt-parent: the phandle for the gpio controller
> + (see interrupt binding[0]).
> +- interrupts: (gpio) interrupt to which the chip is connected
> + (see interrupt binding[0]).
> +- ti,max-rt: maximum pressure.
> +- ti,fuzzx: specifies the absolute input fuzz x value.
> + If set, it will permit noise in the data up to +- the value given to the fuzz
> + parameter, that is used to filter noise from the event stream.
> +- ti,fuzzy: specifies the absolute input fuzz y value.
> +- ti,fuzzz: specifies the absolute input fuzz z value.
fuzz{x,y,z} look a weird name
> +- ti,poll-period: how much time to wait(in millisecond) before reading again the
> + values from the tsc2007.
so put -ms in the binding to de clear and does not requiere to read the doc
Best Regards,
J.
> +
> +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> +[1]: Documentation/devicetree/bindings/gpio/gpio.txt
> +
> +Example:
> + &i2c1 {
> + /* ... */
> + tsc2007@49 {
> + compatible = "ti,tsc2007";
> + reg = <0x49>;
> + interrupt-parent = <&gpio4>;
> + interrupts = <0x0 0x8>;
> + gpios = <&gpio4 0 0>;
> + ti,x-plate-ohms = <180>;
> + };
> +
> + /* ... */
> + };
> diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
> index 0b67ba4..3168a99 100644
> --- a/drivers/input/touchscreen/tsc2007.c
> +++ b/drivers/input/touchscreen/tsc2007.c
> @@ -26,6 +26,9 @@
> #include <linux/interrupt.h>
> #include <linux/i2c.h>
> #include <linux/i2c/tsc2007.h>
> +#include <linux/of_device.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
>
> #define TSC2007_MEASURE_TEMP0 (0x0 << 4)
> #define TSC2007_MEASURE_AUX (0x2 << 4)
> @@ -74,7 +77,12 @@ struct tsc2007 {
> u16 max_rt;
> unsigned long poll_delay;
> unsigned long poll_period;
> + int fuzzx;
> + int fuzzy;
> + int fuzzz;
> + char of;
>
> + unsigned gpio;
> int irq;
>
> wait_queue_head_t wait;
> @@ -84,6 +92,11 @@ struct tsc2007 {
> void (*clear_penirq)(void);
> };
>
> +static int tsc2007_get_pendown_state_dt(struct tsc2007 *ts)
> +{
> + return !gpio_get_value(ts->gpio);
> +}
> +
> static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
> {
> s32 data;
> @@ -142,6 +155,14 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
> return rt;
> }
>
> +static bool tsc2007_is_pen_down_valid(struct tsc2007 *ts)
> +{
> + if (ts->of)
> + return gpio_is_valid(ts->gpio);
> + else
> + return ts->get_pendown_state ? true : false;
> +}
> +
> static bool tsc2007_is_pen_down(struct tsc2007 *ts)
> {
> /*
> @@ -158,10 +179,13 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts)
> * to fall back on the pressure reading.
> */
>
> - if (!ts->get_pendown_state)
> + if (!tsc2007_is_pen_down_valid(ts))
> return true;
>
> - return ts->get_pendown_state();
> + if (ts->of)
> + return tsc2007_get_pendown_state_dt(ts);
> + else
> + return ts->get_pendown_state();
> }
>
> static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
> @@ -178,7 +202,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
>
> rt = tsc2007_calculate_pressure(ts, &tc);
>
> - if (rt = 0 && !ts->get_pendown_state) {
> + if (!rt && !tsc2007_is_pen_down_valid(ts)) {
> /*
> * If pressure reported is 0 and we don't have
> * callback to check pendown state, we have to
> @@ -228,7 +252,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
> {
> struct tsc2007 *ts = handle;
>
> - if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
> + if (tsc2007_is_pen_down(ts))
> return IRQ_WAKE_THREAD;
>
> if (ts->clear_penirq)
> @@ -273,34 +297,71 @@ static void tsc2007_close(struct input_dev *input_dev)
> tsc2007_stop(ts);
> }
>
> -static int tsc2007_probe(struct i2c_client *client,
> - const struct i2c_device_id *id)
> +#ifdef CONFIG_OF
> +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
> + struct device_node *np)
> {
> - struct tsc2007 *ts;
> - struct tsc2007_platform_data *pdata = client->dev.platform_data;
> - struct input_dev *input_dev;
> - int err;
> -
> - if (!pdata) {
> - dev_err(&client->dev, "platform data is required!\n");
> + int err = 0;
> + u32 val32;
> + u64 val64;
> +
> + if (!of_property_read_u32(np, "ti,max-rt", &val32))
> + ts->max_rt = val32;
> + else
> + ts->max_rt = MAX_12BIT;
> +
> + if (!of_property_read_u32(np, "ti,fuzzx", &val32))
> + ts->fuzzx = val32;
> +
> + if (!of_property_read_u32(np, "ti,fuzzy", &val32))
> + ts->fuzzy = val32;
> +
> + if (!of_property_read_u32(np, "ti,fuzzz", &val32))
> + ts->fuzzz = val32;
> +
> + if (!of_property_read_u64(np, "ti,poll-period", &val64))
> + ts->poll_period = val64;
> + else
> + ts->poll_period = 1;
> +
> + if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) {
> + ts->x_plate_ohms = val32;
> + } else {
> + dev_err(&client->dev,
> + "Error: lacking ti,x-plate-ohms devicetree property. (err %d).",
> + err);
> return -EINVAL;
> }
>
> - if (!i2c_check_functionality(client->adapter,
> - I2C_FUNC_SMBUS_READ_WORD_DATA))
> - return -EIO;
> + ts->gpio = of_get_gpio(np, 0);
> + if (!gpio_is_valid(ts->gpio))
> + dev_err(&client->dev,
> + "GPIO not found (of_get_gpio returned %d)\n",
> + ts->gpio);
>
> - ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);
> - input_dev = input_allocate_device();
> - if (!ts || !input_dev) {
> - err = -ENOMEM;
> - goto err_free_mem;
> - }
> + /* Used to detect if it is probed trough the device tree,
> + * in order to be able to use that information in the IRQ handler.
> + */
> + ts->of = 1;
>
> - ts->client = client;
> - ts->irq = client->irq;
> - ts->input = input_dev;
> - init_waitqueue_head(&ts->wait);
> + return 0;
> +}
> +#else
> +static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
> + struct device_node *np)
> +{
> + return -ENODEV;
> +}
> +#endif
> +
> +static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts,
> + struct tsc2007_platform_data *pdata,
> + const struct i2c_device_id *id)
> +{
> + if (!pdata) {
> + dev_err(&client->dev, "platform data is required!\n");
> + return -EINVAL;
> + }
>
> ts->model = pdata->model;
> ts->x_plate_ohms = pdata->x_plate_ohms;
> @@ -309,13 +370,59 @@ static int tsc2007_probe(struct i2c_client *client,
> ts->poll_period = pdata->poll_period ? : 1;
> ts->get_pendown_state = pdata->get_pendown_state;
> ts->clear_penirq = pdata->clear_penirq;
> + ts->fuzzx = pdata->fuzzx;
> + ts->fuzzy = pdata->fuzzy;
> + ts->fuzzz = pdata->fuzzz;
>
> if (pdata->x_plate_ohms = 0) {
> dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
> - err = -EINVAL;
> - goto err_free_mem;
> + return -EINVAL;
> }
>
> + /* Used to detect if it is probed trough the device tree,
> + * in order to be able to use that information in the IRQ handler.
> + */
> + ts->of = 0;
> +
> + return 0;
> +}
> +
> +static int tsc2007_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct device_node *np = client->dev.of_node;
> + struct tsc2007_platform_data *pdata = client->dev.platform_data;
> + struct tsc2007 *ts;
> + struct input_dev *input_dev;
> + int err = 0;
> +
> + ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL);
> + if (!ts)
> + return -ENOMEM;
> +
> + if (np)
> + err = tsc2007_probe_dt(client, ts, np);
> + else
> + err = tsc2007_probe_pdev(client, ts, pdata, id);
> +
> + if (err)
> + return err;
> +
> + if (!i2c_check_functionality(client->adapter,
> + I2C_FUNC_SMBUS_READ_WORD_DATA))
> + return -EIO;
> +
> + input_dev = input_allocate_device();
> + if (!input_dev) {
> + err = -ENOMEM;
> + goto err_free_input;
> + };
> +
> + ts->client = client;
> + ts->irq = client->irq;
> + ts->input = input_dev;
> + init_waitqueue_head(&ts->wait);
> +
> snprintf(ts->phys, sizeof(ts->phys),
> "%s/input0", dev_name(&client->dev));
>
> @@ -331,19 +438,21 @@ static int tsc2007_probe(struct i2c_client *client,
> input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
>
> - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);
> - input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);
> + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
> + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
> input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
> - pdata->fuzzz, 0);
> + ts->fuzzz, 0);
>
> - if (pdata->init_platform_hw)
> - pdata->init_platform_hw();
> + if (!np) {
> + if (pdata->init_platform_hw)
> + pdata->init_platform_hw();
> + }
>
> err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
> IRQF_ONESHOT, client->dev.driver->name, ts);
> if (err < 0) {
> dev_err(&client->dev, "irq %d busy?\n", ts->irq);
> - goto err_free_mem;
> + goto err_free_input;
> }
>
> tsc2007_stop(ts);
> @@ -358,23 +467,27 @@ static int tsc2007_probe(struct i2c_client *client,
>
> err_free_irq:
> free_irq(ts->irq, ts);
> - if (pdata->exit_platform_hw)
> - pdata->exit_platform_hw();
> - err_free_mem:
> + if (!np) {
> + if (pdata->exit_platform_hw)
> + pdata->exit_platform_hw();
> + }
> + err_free_input:
> input_free_device(input_dev);
> - kfree(ts);
> return err;
> }
>
> static int tsc2007_remove(struct i2c_client *client)
> {
> + struct device_node *np = client->dev.of_node;
> struct tsc2007 *ts = i2c_get_clientdata(client);
> struct tsc2007_platform_data *pdata = client->dev.platform_data;
>
> free_irq(ts->irq, ts);
>
> - if (pdata->exit_platform_hw)
> - pdata->exit_platform_hw();
> + if (!np) {
> + if (pdata->exit_platform_hw)
> + pdata->exit_platform_hw();
> + }
>
> input_unregister_device(ts->input);
> kfree(ts);
> @@ -389,10 +502,19 @@ static const struct i2c_device_id tsc2007_idtable[] = {
>
> MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
>
> +#ifdef CONFIG_OF
> +static const struct of_device_id tsc2007_of_match[] = {
> + { .compatible = "ti,tsc2007" },
> + { /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, tsc2007_of_match);
> +#endif
> +
> static struct i2c_driver tsc2007_driver = {
> .driver = {
> .owner = THIS_MODULE,
> - .name = "tsc2007"
> + .name = "tsc2007",
> + .of_match_table = of_match_ptr(tsc2007_of_match),
> },
> .id_table = tsc2007_idtable,
> .probe = tsc2007_probe,
> --
> 1.7.9.5
>
^ permalink raw reply
* Re: [PATCH] video: backlight: Remove backlight sysfs uevent
From: Matthew Garrett @ 2013-11-20 23:40 UTC (permalink / raw)
To: Henrique de Moraes Holschuh
Cc: Jingoo Han, 'Kyungmin Park',
'Henrique de Moraes Holschuh', linux-fbdev, linux-kernel,
kay, 'Richard Purdie', ibm-acpi-devel,
platform-driver-x86
In-Reply-To: <20131112005628.GA2914@khazad-dum.debian.net>
On Mon, 2013-11-11 at 22:56 -0200, Henrique de Moraes Holschuh wrote:
> On Tue, 12 Nov 2013, Jingoo Han wrote:
> > 'thinkpad_acpi.c' uses the 'BACKLIGHT_UPDATE_SYSFS'.
> > Henrique, can we remove it?
>
> Can't you fix this by rate-limiting, or otherwise adding an attribute that
> backlight devices should set when they need to supress change events?
It looks like this is just to force synchronisation to sysfs when using
the /proc interface? In which case we should probably just kill
the /proc interface.
--
Matthew Garrett <matthew.garrett@nebula.com>
^ permalink raw reply
* Re: [PATCH v2] video: add OpenCores VGA/LCD framebuffer driver
From: Stefan Kristiansson @ 2013-11-20 19:13 UTC (permalink / raw)
To: Jingoo Han
Cc: linux-kernel, linux-fbdev, 'Tomi Valkeinen',
'Jean-Christophe PLAGNIOL-VILLARD'
In-Reply-To: <000701cee5b8$9b61e3b0$d225ab10$%han@samsung.com>
On Wed, Nov 20, 2013 at 03:20:28PM +0900, Jingoo Han wrote:
> On Wednesday, November 20, 2013 1:14 PM, Stefan Kristiansson wrote:
>
> > +static int ocfb_probe(struct platform_device *pdev)
> > +{
> > + int ret = 0;
> > + struct ocfb_dev *fbdev;
> > + struct ocfb_par *par = &ocfb_par_priv;
> > + struct resource *res;
> > + struct resource *mmio;
> > + int fbsize;
> > +
> > + fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
>
> Please use devm_kzalloc() instead of kzalloc().
> In this case, kfree() can be removed from ocfb_probe()
> and ocfb_remove(). Thus, it will make the code smaller.
>
Nice, thanks for the hint!
Consider it done.
> [.....]
>
> > +
> > +#ifdef MODULE
>
> I don't think that '#ifdef MODULE' is necessary.
> Is there any reason?
>
You're right, that's not necessary, I'll remove that.
Thanks alot for taking the time to review it!
Stefan
^ permalink raw reply
* Re: [PATCH] RFC: framebuffer: provide generic get_fb_unmapped_area
From: Geert Uytterhoeven @ 2013-11-20 8:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20131118185959.GE19318@pengutronix.de>
On Mon, Nov 18, 2013 at 7:59 PM, Uwe Kleine-König
<u.kleine-koenig@pengutronix.de> wrote:
>> > +unsigned long fb_get_unmapped_area(struct file *filp, unsigned long orig_addr,
>> > + unsigned long len, unsigned long pgoff, unsigned long flags)
>> > +{
>> > + struct fb_info * const info = filp->private_data;
>> > + unsigned long screen_size = info->screen_size ?: info->fix.smem_len;
>>
>> Why restrict this to screen_size? Fbtest will map the whole frame buffer memory.
> For me screen_size is zero. The logic to determine the size is copied
> from fb_read.
fb_read() only allows reading the visible screen, not the full frame
buffer memory.
fb_mmap() does allow mapping the full frame buffer memory (and the optional
MMIO registers, but you can't easily do that the same way on nommu, as it's
a discontiguous mapping).
So please use PAGE_ALIGN(info->fix.smem_len) as the limit.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH v2] video: add OpenCores VGA/LCD framebuffer driver
From: Jingoo Han @ 2013-11-20 6:20 UTC (permalink / raw)
To: 'Stefan Kristiansson'
Cc: linux-kernel, linux-fbdev, 'Tomi Valkeinen',
'Jean-Christophe PLAGNIOL-VILLARD', 'Jingoo Han'
In-Reply-To: <1384920820-18740-1-git-send-email-stefan.kristiansson@saunalahti.fi>
On Wednesday, November 20, 2013 1:14 PM, Stefan Kristiansson wrote:
>
> This adds support for the VGA/LCD core available from OpenCores:
> http://opencores.org/project,vga_lcd
>
> The driver have been tested together with both OpenRISC and
> ARM (socfpga) processors.
>
> Signed-off-by: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
> ---
> Changes in v2:
> - Add Microblaze as an example user and fix a typo in Xilinx Zynq
> ---
> drivers/video/Kconfig | 17 ++
> drivers/video/Makefile | 1 +
> drivers/video/ocfb.c | 479 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 497 insertions(+)
> create mode 100644 drivers/video/ocfb.c
>
Hi Stefan Kristiansson,
I added trivial comments as below.
[.....]
> --- /dev/null
> +++ b/drivers/video/ocfb.c
[.....]
> +static int ocfb_probe(struct platform_device *pdev)
> +{
> + int ret = 0;
> + struct ocfb_dev *fbdev;
> + struct ocfb_par *par = &ocfb_par_priv;
> + struct resource *res;
> + struct resource *mmio;
> + int fbsize;
> +
> + fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
Please use devm_kzalloc() instead of kzalloc().
In this case, kfree() can be removed from ocfb_probe()
and ocfb_remove(). Thus, it will make the code smaller.
[.....]
> +
> +#ifdef MODULE
I don't think that '#ifdef MODULE' is necessary.
Is there any reason?
Best regards,
Jingoo Han
> +MODULE_AUTHOR("Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>");
> +MODULE_DESCRIPTION("OpenCores VGA/LCD 2.0 frame buffer driver");
> +MODULE_LICENSE("GPL v2");
> +module_param(mode_option, charp, 0);
> +MODULE_PARM_DESC(mode_option, "Video mode ('<xres>x<yres>[-<bpp>][@refresh]')");
> +#endif
> --
> 1.8.3.2
^ permalink raw reply
* [PATCH v2] video: add OpenCores VGA/LCD framebuffer driver
From: Stefan Kristiansson @ 2013-11-20 4:13 UTC (permalink / raw)
To: linux-kernel, linux-fbdev; +Cc: tomi.valkeinen, plagnioj, Stefan Kristiansson
This adds support for the VGA/LCD core available from OpenCores:
http://opencores.org/project,vga_lcd
The driver have been tested together with both OpenRISC and
ARM (socfpga) processors.
Signed-off-by: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
---
Changes in v2:
- Add Microblaze as an example user and fix a typo in Xilinx Zynq
---
drivers/video/Kconfig | 17 ++
drivers/video/Makefile | 1 +
drivers/video/ocfb.c | 479 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 497 insertions(+)
create mode 100644 drivers/video/ocfb.c
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 84b685f..3b3f31e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -979,6 +979,23 @@ config FB_PVR2
(<file:drivers/video/pvr2fb.c>). Please see the file
<file:Documentation/fb/pvr2fb.txt>.
+config FB_OPENCORES
+ tristate "OpenCores VGA/LCD core 2.0 framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ default n
+ help
+ This enables support for the OpenCores VGA/LCD core.
+
+ The OpenCores VGA/LCD core is typically used together with
+ softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor
+ systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs.
+
+ The source code and specification for the core is available at
+ <http://opencores.org/project,vga_lcd>
+
config FB_S1D13XXX
tristate "Epson S1D13XXX framebuffer support"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e8bae8d..ae17ddf 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_FB_NUC900) += nuc900fb.o
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
+obj-$(CONFIG_FB_OPENCORES) += ocfb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
diff --git a/drivers/video/ocfb.c b/drivers/video/ocfb.c
new file mode 100644
index 0000000..6b01e65
--- /dev/null
+++ b/drivers/video/ocfb.c
@@ -0,0 +1,479 @@
+/*
+ * OpenCores VGA/LCD 2.0 core frame buffer driver
+ *
+ * Copyright (C) 2013 Stefan Kristiansson, stefan.kristiansson@saunalahti.fi
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+/* OCFB register defines */
+#define OCFB_CTRL 0x000
+#define OCFB_STAT 0x004
+#define OCFB_HTIM 0x008
+#define OCFB_VTIM 0x00c
+#define OCFB_HVLEN 0x010
+#define OCFB_VBARA 0x014
+#define OCFB_PALETTE 0x800
+
+#define OCFB_CTRL_VEN 0x00000001 /* Video Enable */
+#define OCFB_CTRL_HIE 0x00000002 /* HSync Interrupt Enable */
+#define OCFB_CTRL_PC 0x00000800 /* 8-bit Pseudo Color Enable*/
+#define OCFB_CTRL_CD8 0x00000000 /* Color Depth 8 */
+#define OCFB_CTRL_CD16 0x00000200 /* Color Depth 16 */
+#define OCFB_CTRL_CD24 0x00000400 /* Color Depth 24 */
+#define OCFB_CTRL_CD32 0x00000600 /* Color Depth 32 */
+#define OCFB_CTRL_VBL1 0x00000000 /* Burst Length 1 */
+#define OCFB_CTRL_VBL2 0x00000080 /* Burst Length 2 */
+#define OCFB_CTRL_VBL4 0x00000100 /* Burst Length 4 */
+#define OCFB_CTRL_VBL8 0x00000180 /* Burst Length 8 */
+
+#define PALETTE_SIZE 256
+
+#define OCFB_NAME "OC VGA/LCD"
+
+static char *mode_option;
+
+static const struct fb_videomode default_mode = {
+ /* 640x480 @ 60 Hz, 31.5 kHz hsync */
+ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+ 0, FB_VMODE_NONINTERLACED
+};
+
+struct ocfb_dev {
+ struct fb_info info;
+ /* Physical and virtual addresses of control regs */
+ phys_addr_t regs_phys;
+ int regs_phys_size;
+ void __iomem *regs;
+ /* flag indicating whether the regs are little endian accessed */
+ int little_endian;
+ /* Physical and virtual addresses of framebuffer */
+ phys_addr_t fb_phys;
+ void __iomem *fb_virt;
+ u32 pseudo_palette[PALETTE_SIZE];
+};
+
+struct ocfb_par {
+ void __iomem *pal_adr;
+};
+
+static struct ocfb_par ocfb_par_priv;
+
+static struct fb_var_screeninfo ocfb_var;
+static struct fb_fix_screeninfo ocfb_fix;
+
+#ifndef MODULE
+static int __init ocfb_setup(char *options)
+{
+ char *curr_opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((curr_opt = strsep(&options, ",")) != NULL) {
+ if (!*curr_opt)
+ continue;
+ mode_option = curr_opt;
+ }
+
+ return 0;
+}
+#endif
+
+static inline u32 ocfb_readreg(struct ocfb_dev *fbdev, loff_t offset)
+{
+ if (fbdev->little_endian)
+ return ioread32(fbdev->regs + offset);
+ else
+ return ioread32be(fbdev->regs + offset);
+}
+
+static void ocfb_writereg(struct ocfb_dev *fbdev, loff_t offset, u32 data)
+{
+ if (fbdev->little_endian)
+ iowrite32(data, fbdev->regs + offset);
+ else
+ iowrite32be(data, fbdev->regs + offset);
+}
+
+static int ocfb_setupfb(struct ocfb_dev *fbdev)
+{
+ unsigned long bpp_config;
+ struct fb_var_screeninfo *var = &fbdev->info.var;
+ struct device *dev = fbdev->info.device;
+ u32 hlen;
+ u32 vlen;
+
+ /* Disable display */
+ ocfb_writereg(fbdev, OCFB_CTRL, 0);
+
+ /* Register framebuffer address */
+ fbdev->little_endian = 0;
+ ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys);
+
+ /* Detect endianess */
+ if (ocfb_readreg(fbdev, OCFB_VBARA) != fbdev->fb_phys) {
+ fbdev->little_endian = 1;
+ ocfb_writereg(fbdev, OCFB_VBARA, fbdev->fb_phys);
+ }
+
+ /* Horizontal timings */
+ ocfb_writereg(fbdev, OCFB_HTIM, (var->hsync_len - 1) << 24 |
+ (var->right_margin - 1) << 16 | (var->xres - 1));
+
+ /* Vertical timings */
+ ocfb_writereg(fbdev, OCFB_VTIM, (var->vsync_len - 1) << 24 |
+ (var->lower_margin - 1) << 16 | (var->yres - 1));
+
+ /* Total length of frame */
+ hlen = var->left_margin + var->right_margin + var->hsync_len +
+ var->xres;
+
+ vlen = var->upper_margin + var->lower_margin + var->vsync_len +
+ var->yres;
+
+ ocfb_writereg(fbdev, OCFB_HVLEN, (hlen - 1) << 16 | (vlen - 1));
+
+ bpp_config = OCFB_CTRL_CD8;
+ switch (var->bits_per_pixel) {
+ case 8:
+ if (!var->grayscale)
+ bpp_config |= OCFB_CTRL_PC; /* enable palette */
+ break;
+
+ case 16:
+ bpp_config |= OCFB_CTRL_CD16;
+ break;
+
+ case 24:
+ bpp_config |= OCFB_CTRL_CD24;
+ break;
+
+ case 32:
+ bpp_config |= OCFB_CTRL_CD32;
+ break;
+
+ default:
+ dev_err(dev, "no bpp specified\n");
+ break;
+ }
+
+ /* maximum (8) VBL (video memory burst length) */
+ bpp_config |= OCFB_CTRL_VBL8;
+
+ /* Enable output */
+ ocfb_writereg(fbdev, OCFB_CTRL, (OCFB_CTRL_VEN | bpp_config));
+
+ return 0;
+}
+
+static int ocfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct ocfb_par *par = (struct ocfb_par *)info->par;
+ u32 color;
+
+ if (regno >= info->cmap.len) {
+ dev_err(info->device, "regno >= cmap.len\n");
+ return 1;
+ }
+
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ red >>= (16 - info->var.red.length);
+ green >>= (16 - info->var.green.length);
+ blue >>= (16 - info->var.blue.length);
+ transp >>= (16 - info->var.transp.length);
+
+ if (info->var.bits_per_pixel = 8 && !info->var.grayscale) {
+ regno <<= 2;
+ color = (red << 16) | (green << 8) | blue;
+ ocfb_writereg(par->pal_adr, regno, color);
+ } else {
+ ((u32 *)(info->pseudo_palette))[regno] + (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+ }
+
+ return 0;
+}
+
+static int ocfb_init_fix(struct ocfb_dev *fbdev)
+{
+ struct fb_var_screeninfo *var = &fbdev->info.var;
+ struct fb_fix_screeninfo *fix = &fbdev->info.fix;
+
+ strcpy(fix->id, OCFB_NAME);
+
+ fix->line_length = var->xres * var->bits_per_pixel/8;
+ fix->smem_len = fix->line_length * var->yres;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+
+ if (var->bits_per_pixel = 8 && !var->grayscale)
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_TRUECOLOR;
+
+ return 0;
+}
+
+static int ocfb_init_var(struct ocfb_dev *fbdev)
+{
+ struct fb_var_screeninfo *var = &fbdev->info.var;
+
+ var->accel_flags = FB_ACCEL_NONE;
+ var->activate = FB_ACTIVATE_NOW;
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ break;
+
+ case 16:
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ break;
+
+ case 24:
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ break;
+
+ case 32:
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ break;
+ }
+
+ return 0;
+}
+
+static struct fb_ops ocfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = ocfb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int ocfb_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct ocfb_dev *fbdev;
+ struct ocfb_par *par = &ocfb_par_priv;
+ struct resource *res;
+ struct resource *mmio;
+ int fbsize;
+
+ fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+ if (!fbdev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, fbdev);
+
+ fbdev->info.fbops = &ocfb_ops;
+ fbdev->info.var = ocfb_var;
+ fbdev->info.fix = ocfb_fix;
+ fbdev->info.device = &pdev->dev;
+ fbdev->info.par = par;
+
+ /* Video mode setup */
+ if (!fb_find_mode(&fbdev->info.var, &fbdev->info, mode_option,
+ NULL, 0, &default_mode, 16)) {
+ dev_err(&pdev->dev, "No valid video modes found\n");
+ kfree(fbdev);
+ return -EINVAL;
+ }
+ ocfb_init_var(fbdev);
+ ocfb_init_fix(fbdev);
+
+ /* Request I/O resource */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "I/O resource request failed\n");
+ kfree(fbdev);
+ return -ENXIO;
+ }
+ fbdev->regs_phys = res->start;
+ fbdev->regs_phys_size = resource_size(res);
+ mmio = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), res->name);
+ if (!mmio) {
+ dev_err(&pdev->dev, "I/O memory space request failed\n");
+ kfree(fbdev);
+ return -ENXIO;
+ }
+ fbdev->regs = devm_ioremap_nocache(&pdev->dev, mmio->start,
+ resource_size(mmio));
+ if (!fbdev->regs) {
+ dev_err(&pdev->dev, "I/O memory remap request failed\n");
+ kfree(fbdev);
+ return -ENXIO;
+ }
+ par->pal_adr = fbdev->regs + OCFB_PALETTE;
+
+ /* Allocate framebuffer memory */
+ fbsize = fbdev->info.fix.smem_len;
+ fbdev->fb_virt = dma_alloc_coherent(&pdev->dev, PAGE_ALIGN(fbsize),
+ &fbdev->fb_phys, GFP_KERNEL);
+ if (!fbdev->fb_virt) {
+ dev_err(&pdev->dev,
+ "Frame buffer memory allocation failed\n");
+ ret = -ENOMEM;
+ goto err_release;
+ }
+ fbdev->info.fix.smem_start = fbdev->fb_phys;
+ fbdev->info.screen_base = (void __iomem *)fbdev->fb_virt;
+ fbdev->info.pseudo_palette = fbdev->pseudo_palette;
+
+ /* Clear framebuffer */
+ memset_io((void __iomem *)fbdev->fb_virt, 0, fbsize);
+
+ /* Setup and enable the framebuffer */
+ ocfb_setupfb(fbdev);
+
+ if (fbdev->little_endian)
+ fbdev->info.flags |= FBINFO_FOREIGN_ENDIAN;
+
+ /* Allocate color map */
+ ret = fb_alloc_cmap(&fbdev->info.cmap, PALETTE_SIZE, 0);
+ if (ret) {
+ dev_err(&pdev->dev, "Color map allocation failed\n");
+ goto err_dma_free;
+ }
+
+ /* Register framebuffer */
+ ret = register_framebuffer(&fbdev->info);
+ if (ret) {
+ dev_err(&pdev->dev, "Framebuffer registration failed\n");
+ goto err_dealloc_cmap;
+ }
+
+ return 0;
+
+err_dealloc_cmap:
+ fb_dealloc_cmap(&fbdev->info.cmap);
+
+err_dma_free:
+ dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbsize), fbdev->fb_virt,
+ fbdev->fb_phys);
+err_release:
+ release_mem_region(fbdev->regs_phys, fbdev->regs_phys_size);
+ kfree(fbdev);
+
+ return ret;
+}
+
+static int ocfb_remove(struct platform_device *pdev)
+{
+ struct ocfb_dev *fbdev = platform_get_drvdata(pdev);
+
+ unregister_framebuffer(&fbdev->info);
+ fb_dealloc_cmap(&fbdev->info.cmap);
+ dma_free_coherent(&pdev->dev, PAGE_ALIGN(fbdev->info.fix.smem_len),
+ fbdev->fb_virt, fbdev->fb_phys);
+
+ /* Disable display */
+ ocfb_writereg(fbdev, OCFB_CTRL, 0);
+
+ release_mem_region(fbdev->regs_phys, fbdev->regs_phys_size);
+ kfree(fbdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct of_device_id ocfb_match[] = {
+ { .compatible = "opencores,ocfb", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ocfb_match);
+
+static struct platform_driver ocfb_driver = {
+ .probe = ocfb_probe,
+ .remove = ocfb_remove,
+ .driver = {
+ .name = "ocfb_fb",
+ .of_match_table = ocfb_match,
+ }
+};
+
+/*
+ * Init and exit routines
+ */
+static int __init ocfb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("ocfb", &option))
+ return -ENODEV;
+ ocfb_setup(option);
+#endif
+ return platform_driver_register(&ocfb_driver);
+}
+
+static void __exit ocfb_exit(void)
+{
+ platform_driver_unregister(&ocfb_driver);
+}
+
+module_init(ocfb_init);
+module_exit(ocfb_exit);
+
+#ifdef MODULE
+MODULE_AUTHOR("Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>");
+MODULE_DESCRIPTION("OpenCores VGA/LCD 2.0 frame buffer driver");
+MODULE_LICENSE("GPL v2");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Video mode ('<xres>x<yres>[-<bpp>][@refresh]')");
+#endif
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCHv9][ 1/3] Input: tsc2007: Add device tree support.
From: Dmitry Torokhov @ 2013-11-19 21:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1383916659-9988-1-git-send-email-denis@eukrea.com>
Hi Denis,
On Fri, Nov 08, 2013 at 02:17:37PM +0100, Denis Carikli wrote:
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: devicetree@vger.kernel.org
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: linux-input@vger.kernel.org
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Lothar Waßmann <LW@KARO-electronics.de>
> Cc: Shawn Guo <shawn.guo@linaro.org>
> Cc: Eric Bénard <eric@eukrea.com>
> Signed-off-by: Denis Carikli <denis@eukrea.com>
> ---
> ChangeLog v8->v9:
> - Added Grant Likely in the Cc list.
> - Removed the mention of the pinctrl properties in the documentation.
>
> ChangeLog v7->v8:
> - Fixed the lack of x and z fuzz properties.
> - The pendown gpio is better documented.
> - Added Shawn Guo in the cc list.
Does the device still work if you drop the patch below on top of yours?
Thanks!
--
Dmitry
Input: tsc2007 misc fixes
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
arch/arm/mach-imx/mach-cpuimx35.c | 2 -
arch/arm/mach-imx/mach-cpuimx51sd.c | 2 -
arch/sh/boards/mach-ecovec24/setup.c | 2 -
drivers/input/touchscreen/tsc2007.c | 126 +++++++++++++---------------------
include/linux/i2c/tsc2007.h | 6 +-
5 files changed, 55 insertions(+), 83 deletions(-)
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 771362d..65e4c53 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -53,7 +53,7 @@ static const struct imxi2c_platform_data
};
#define TSC2007_IRQGPIO IMX_GPIO_NR(3, 2)
-static int tsc2007_get_pendown_state(void)
+static int tsc2007_get_pendown_state(struct device *dev)
{
return !gpio_get_value(TSC2007_IRQGPIO);
}
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
index 9b5ddf5..1fba2b8 100644
--- a/arch/arm/mach-imx/mach-cpuimx51sd.c
+++ b/arch/arm/mach-imx/mach-cpuimx51sd.c
@@ -121,7 +121,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static int tsc2007_get_pendown_state(void)
+static int tsc2007_get_pendown_state(struct device *dev)
{
if (mx51_revision() < IMX_CHIP_REVISION_3_0)
return !gpio_get_value(TSC2007_IRQGPIO_REV2);
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 1fa8be4..23d7e45 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -501,7 +501,7 @@ static struct platform_device keysc_device = {
/* TouchScreen */
#define IRQ0 evt2irq(0x600)
-static int ts_get_pendown_state(void)
+static int ts_get_pendown_state(struct device *dev)
{
int val = 0;
gpio_free(GPIO_FN_INTC_IRQ0);
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 3168a99..390148c 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -88,15 +88,10 @@ struct tsc2007 {
wait_queue_head_t wait;
bool stopped;
- int (*get_pendown_state)(void);
+ int (*get_pendown_state)(struct device *);
void (*clear_penirq)(void);
};
-static int tsc2007_get_pendown_state_dt(struct tsc2007 *ts)
-{
- return !gpio_get_value(ts->gpio);
-}
-
static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
{
s32 data;
@@ -155,14 +150,6 @@ static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc)
return rt;
}
-static bool tsc2007_is_pen_down_valid(struct tsc2007 *ts)
-{
- if (ts->of)
- return gpio_is_valid(ts->gpio);
- else
- return ts->get_pendown_state ? true : false;
-}
-
static bool tsc2007_is_pen_down(struct tsc2007 *ts)
{
/*
@@ -179,13 +166,10 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts)
* to fall back on the pressure reading.
*/
- if (!tsc2007_is_pen_down_valid(ts))
+ if (!ts->get_pendown_state)
return true;
- if (ts->of)
- return tsc2007_get_pendown_state_dt(ts);
- else
- return ts->get_pendown_state();
+ return ts->get_pendown_state(&ts->client->dev);
}
static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
@@ -202,7 +186,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
rt = tsc2007_calculate_pressure(ts, &tc);
- if (!rt && !tsc2007_is_pen_down_valid(ts)) {
+ if (!rt && !ts->get_pendown_state) {
/*
* If pressure reported is 0 and we don't have
* callback to check pendown state, we have to
@@ -298,13 +282,25 @@ static void tsc2007_close(struct input_dev *input_dev)
}
#ifdef CONFIG_OF
-static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
- struct device_node *np)
+static int tsc2007_get_pendown_state_gpio(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsc2007 *ts = i2c_get_clientdata(client);
+
+ return !gpio_get_value(ts->gpio);
+}
+
+static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
{
- int err = 0;
+ struct device_node *np = client->dev.of_node;
u32 val32;
u64 val64;
+ if (!np) {
+ dev_err(&client->dev, "missing device tree data\n");
+ return -EINVAL;
+ }
+
if (!of_property_read_u32(np, "ti,max-rt", &val32))
ts->max_rt = val32;
else
@@ -327,42 +323,32 @@ static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) {
ts->x_plate_ohms = val32;
} else {
- dev_err(&client->dev,
- "Error: lacking ti,x-plate-ohms devicetree property. (err %d).",
- err);
+ dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property.");
return -EINVAL;
}
ts->gpio = of_get_gpio(np, 0);
- if (!gpio_is_valid(ts->gpio))
- dev_err(&client->dev,
- "GPIO not found (of_get_gpio returned %d)\n",
- ts->gpio);
-
- /* Used to detect if it is probed trough the device tree,
- * in order to be able to use that information in the IRQ handler.
- */
- ts->of = 1;
+ if (gpio_is_valid(ts->gpio))
+ ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
+ else
+ dev_warn(&client->dev,
+ "GPIO not specified in DT (of_get_gpio returned %d)\n",
+ ts->gpio);
return 0;
}
#else
-static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts,
- struct device_node *np)
+static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
{
- return -ENODEV;
+ dev_err(&client->dev, "platform data is required!\n");
+ return -EINVAL;
}
#endif
static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts,
- struct tsc2007_platform_data *pdata,
+ const struct tsc2007_platform_data *pdata,
const struct i2c_device_id *id)
{
- if (!pdata) {
- dev_err(&client->dev, "platform data is required!\n");
- return -EINVAL;
- }
-
ts->model = pdata->model;
ts->x_plate_ohms = pdata->x_plate_ohms;
ts->max_rt = pdata->max_rt ? : MAX_12BIT;
@@ -379,45 +365,40 @@ static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts,
return -EINVAL;
}
- /* Used to detect if it is probed trough the device tree,
- * in order to be able to use that information in the IRQ handler.
- */
- ts->of = 0;
-
return 0;
}
static int tsc2007_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct device_node *np = client->dev.of_node;
- struct tsc2007_platform_data *pdata = client->dev.platform_data;
+ const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev);
struct tsc2007 *ts;
struct input_dev *input_dev;
- int err = 0;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -EIO;
ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL);
if (!ts)
return -ENOMEM;
- if (np)
- err = tsc2007_probe_dt(client, ts, np);
- else
+ if (pdata)
err = tsc2007_probe_pdev(client, ts, pdata, id);
-
+ else
+ err = tsc2007_probe_dt(client, ts);
if (err)
return err;
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_WORD_DATA))
- return -EIO;
-
input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
goto err_free_input;
};
+ i2c_set_clientdata(client, ts);
+
ts->client = client;
ts->irq = client->irq;
ts->input = input_dev;
@@ -443,10 +424,8 @@ static int tsc2007_probe(struct i2c_client *client,
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
ts->fuzzz, 0);
- if (!np) {
- if (pdata->init_platform_hw)
- pdata->init_platform_hw();
- }
+ if (pdata && pdata->init_platform_hw)
+ pdata->init_platform_hw();
err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
IRQF_ONESHOT, client->dev.driver->name, ts);
@@ -461,16 +440,12 @@ static int tsc2007_probe(struct i2c_client *client,
if (err)
goto err_free_irq;
- i2c_set_clientdata(client, ts);
-
return 0;
err_free_irq:
free_irq(ts->irq, ts);
- if (!np) {
- if (pdata->exit_platform_hw)
- pdata->exit_platform_hw();
- }
+ if (pdata && pdata->exit_platform_hw)
+ pdata->exit_platform_hw();
err_free_input:
input_free_device(input_dev);
return err;
@@ -478,16 +453,13 @@ static int tsc2007_probe(struct i2c_client *client,
static int tsc2007_remove(struct i2c_client *client)
{
- struct device_node *np = client->dev.of_node;
- struct tsc2007 *ts = i2c_get_clientdata(client);
- struct tsc2007_platform_data *pdata = client->dev.platform_data;
+ const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev);
+ struct tsc2007 *ts = i2c_get_clientdata(client);
free_irq(ts->irq, ts);
- if (!np) {
- if (pdata->exit_platform_hw)
- pdata->exit_platform_hw();
- }
+ if (pdata && pdata->exit_platform_hw)
+ pdata->exit_platform_hw();
input_unregister_device(ts->input);
kfree(ts);
diff --git a/include/linux/i2c/tsc2007.h b/include/linux/i2c/tsc2007.h
index 506a9f7..041c8e8 100644
--- a/include/linux/i2c/tsc2007.h
+++ b/include/linux/i2c/tsc2007.h
@@ -14,9 +14,9 @@ struct tsc2007_platform_data {
int fuzzy;
int fuzzz;
- int (*get_pendown_state)(void);
- void (*clear_penirq)(void); /* If needed, clear 2nd level
- interrupt source */
+ int (*get_pendown_state)(struct device *);
+ /* If needed, clear 2nd level interrupt source */
+ void (*clear_penirq)(void);
int (*init_platform_hw)(void);
void (*exit_platform_hw)(void);
};
^ permalink raw reply related
* [PATCH] video: kyro: fix incorrect sizes when copying to userspace
From: Sasha Levin @ 2013-11-19 19:25 UTC (permalink / raw)
To: plagnioj, tomi.valkeinen; +Cc: gregkh, linux-fbdev, linux-kernel, Sasha Levin
kyro would copy u32s and specify sizeof(unsigned long) as the size to copy.
This would copy more data than intended and cause memory corruption and might
leak kernel memory.
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
drivers/video/kyro/fbdev.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 50c8574..65041e1 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -624,15 +624,15 @@ static int kyrofb_ioctl(struct fb_info *info,
return -EINVAL;
}
case KYRO_IOCTL_UVSTRIDE:
- if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+ if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
return -EFAULT;
break;
case KYRO_IOCTL_STRIDE:
- if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+ if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
return -EFAULT;
break;
case KYRO_IOCTL_OVERLAY_OFFSET:
- if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+ if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
return -EFAULT;
break;
}
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH] RFC: framebuffer: provide generic get_fb_unmapped_area
From: Uwe Kleine-König @ 2013-11-18 19:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20131118185959.GE19318@pengutronix.de>
Hello again,
On Mon, Nov 18, 2013 at 07:59:59PM +0100, Uwe Kleine-König wrote:
> if (pgoff > screen_size || pgoff + len > screen_size)
This must be:
if (pgoff > screen_size || len > screen_size - pgoff)
to do what I intended.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: [PATCH] RFC: framebuffer: provide generic get_fb_unmapped_area
From: Uwe Kleine-König @ 2013-11-18 18:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMuHMdWtrSnTHNN-7GtMWAG9gZ0HJ3ZgVZt6Cfc=q=e-5Sr-Qw@mail.gmail.com>
Hello Geert,
On Mon, Nov 18, 2013 at 12:59:40PM +0100, Geert Uytterhoeven wrote:
> On Mon, Nov 18, 2013 at 11:57 AM, Uwe Kleine-König
> <u.kleine-koenig@pengutronix.de> wrote:
> > This patch makes mmapping the simple-framebuffer device work on a no-MMU
> > ARM target. The code is mostly taken from
> > arch/blackfin/kernel/sys_bfin.c.
> >
> > Note this is only tested on this no-MMU machine and I don't know enough
> > about framebuffers and mm to decide if this patch is sane. Also I'm
> > unsure about the size check because it triggers if userspace page aligns
> > the len parameter. (I don't know how usual it is to do, I'd say it's
> > wrong, but my test program (fbtest by Geert Uytterhoeven) does it.)
>
> It's quite common: the granularity of mmap() is PAGE_SIZE, i.e. if you
> try to map a partial page, you'll get access to the full page anyway
> (with MMU; without MMU, you can access everything anyway).
> Fbtest always mmap()s the full (page aligned) smem_len.
>
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> > drivers/video/fbmem.c | 22 +++++++++++++++++++---
> > 1 file changed, 19 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> > index dacaf74..70b328c 100644
> > --- a/drivers/video/fbmem.c
> > +++ b/drivers/video/fbmem.c
> > @@ -1483,6 +1483,24 @@ __releases(&info->lock)
> > return 0;
> > }
> >
> > +#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
> > +#define fb_get_unmapped_area get_fb_unmapped_area
> > +#else
> > +unsigned long fb_get_unmapped_area(struct file *filp, unsigned long orig_addr,
> > + unsigned long len, unsigned long pgoff, unsigned long flags)
> > +{
> > + struct fb_info * const info = filp->private_data;
> > + unsigned long screen_size = info->screen_size ?: info->fix.smem_len;
>
> Why restrict this to screen_size? Fbtest will map the whole frame buffer memory.
For me screen_size is zero. The logic to determine the size is copied
from fb_read. In the meantine I'm using
if (len > PAGE_ALIGN(screen_size))
because even if userspace passes an unaligned size it gets aligned
somewhere on the path to fb_get_unmapped_area.
> Typically screen_size is not a multiple of PAGE_SIZE, so this is another
> reason why your size check fails.
>
> > + if (len > screen_size) {
> > + pr_info("%lu > %lu (%lu, %lu)\n", len, screen_size, info->screen_size, info->fix.smem_len);
> > + return -EINVAL;
> > + }
> > +
> > + return (unsigned long)info->screen_base;
>
> Shouldn't you take into account pgoff?
Sounds sensible. Then the same applies to blackfin's
get_fb_unmapped_area.
So is it:
unsigned long screen_size = info->screen_size ?: info->fix.smem_len;
screen_size = PAGE_ALIGN(screen_size);
if (pgoff > screen_size || pgoff + len > screen_size)
return -EINVAL;
return (unsigned long)info->screen_base + pgoff;
? Or should I drop the size check?
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* Re: [PATCH 0/3] omapdss: venc: Add support for bypass and acbias.
From: Dr. H. Nikolaus Schaller @ 2013-11-18 14:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <528A1652.4000806@ti.com>
Hi Tomi,
Am 18.11.2013 um 14:29 schrieb Tomi Valkeinen:
> On 2013-11-11 16:30, Dr. H. Nikolaus Schaller wrote:
>
>> Maybe it looks as if it is an unsolvable problem. The OPA works only if acbias
>> and bypass are enabled, but is not allowed to tell that it is there.
>
> That's why the board file or dts file is there, to have "glue" data to
> make different pieces work together.
Our implementation idea was that this makes the board file developer to specify knowlegde that the
drivers already could have and to reduce the risk of misconfiguration.
So we tried to model the invert property of the connector which is also backpropagated
to VENC.
But of course there are different ways of doing it and different priorities of contradicting
requirements.
>
> The perfect (?) solution would be a CDF like data. The idea would be
> that in the board file, you would describe configuration options for
> VENC and for OPA. In this particular case, you'd tell VENC that it needs
> to enable acbias and bypass when OPA is to be connected to VENC. Then
> there could be more entries for VENC, saying disable acbias and bypass
> when BAR is to be connected to VENC.
>
> However, we don't have such support (yet).
>
> For now, I hope it's enough if we handle VENC in a "single
> configuration" manner, i.e. you'll tell VENC to enable acbias and bypass
> when VENC is enabled. This means you can't have board setups where you'd
> change the VENC->OPA connection to some other analog tv output at
> runtime. I hope that's the case (i.e. OPA is always in use on that board).
I also don't think that there is a need for runtime modifications, so your proposal
looks ok.
> If so, then I think you can just pass the acbias and bypass
> configuration values via omapdss platform data. And VENC driver will use
> them to configure those. OPA doesn't know anything about this at all.
We will change it that way.
Do you see a chance to get it into the merge window of 3.13?
BR,
Nikolaus
^ permalink raw reply
* Re: [PATCH v2] ARM: OMAPFB: panel-sony-acx565akm: fix bad unlock balance
From: Tomi Valkeinen @ 2013-11-18 13:36 UTC (permalink / raw)
To: Aaro Koskinen, linux-omap, linux-fbdev; +Cc: Eduardo Valentin, stable
In-Reply-To: <1384195298-31542-1-git-send-email-aaro.koskinen@iki.fi>
[-- Attachment #1: Type: text/plain, Size: 2088 bytes --]
On 2013-11-11 20:41, Aaro Koskinen wrote:
> When booting Nokia N900 smartphone with v3.12 + omap2plus_defconfig
> (LOCKDEP enabled) and CONFIG_DISPLAY_PANEL_SONY_ACX565AKM enabled,
> the following BUG is seen during the boot:
>
> [ 7.302154] =====================================
> [ 7.307128] [ BUG: bad unlock balance detected! ]
> [ 7.312103] 3.12.0-los.git-2093492-00120-g5e01dc7 #3 Not tainted
> [ 7.318450] -------------------------------------
> [ 7.323425] kworker/u2:1/12 is trying to release lock (&ddata->mutex) at:
> [ 7.330657] [<c031b760>] acx565akm_enable+0x12c/0x18c
> [ 7.335998] but there are no more locks to release!
>
> Fix by removing double unlock and handling the locking completely inside
> acx565akm_panel_power_on() when doing the power on.
>
> Reported-by: Eduardo Valentin <eduardo.valentin@ti.com>
> Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
> Cc: stable@vger.kernel.org
> ---
> drivers/video/omap2/displays-new/panel-sony-acx565akm.c | 5 ++---
> 1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
> index e6d56f7..d94f35d 100644
> --- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
> +++ b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c
> @@ -526,6 +526,8 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
> struct omap_dss_device *in = ddata->in;
> int r;
>
> + mutex_lock(&ddata->mutex);
> +
> dev_dbg(&ddata->spi->dev, "%s\n", __func__);
>
> in->ops.sdi->set_timings(in, &ddata->videomode);
> @@ -614,10 +616,7 @@ static int acx565akm_enable(struct omap_dss_device *dssdev)
> if (omapdss_device_is_enabled(dssdev))
> return 0;
>
> - mutex_lock(&ddata->mutex);
> r = acx565akm_panel_power_on(dssdev);
> - mutex_unlock(&ddata->mutex);
> -
> if (r)
> return r;
>
>
Thanks, this is better. lock and unlock in different functions makes me
feel very uneasy...
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [PATCH 0/3] omapdss: venc: Add support for bypass and acbias.
From: Tomi Valkeinen @ 2013-11-18 13:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <F97741D2-FC6F-4DBD-A0DD-E35304501993@goldelico.com>
[-- Attachment #1: Type: text/plain, Size: 1339 bytes --]
On 2013-11-11 16:30, Dr. H. Nikolaus Schaller wrote:
> Maybe it looks as if it is an unsolvable problem. The OPA works only if acbias
> and bypass are enabled, but is not allowed to tell that it is there.
That's why the board file or dts file is there, to have "glue" data to
make different pieces work together.
The perfect (?) solution would be a CDF like data. The idea would be
that in the board file, you would describe configuration options for
VENC and for OPA. In this particular case, you'd tell VENC that it needs
to enable acbias and bypass when OPA is to be connected to VENC. Then
there could be more entries for VENC, saying disable acbias and bypass
when BAR is to be connected to VENC.
However, we don't have such support (yet).
For now, I hope it's enough if we handle VENC in a "single
configuration" manner, i.e. you'll tell VENC to enable acbias and bypass
when VENC is enabled. This means you can't have board setups where you'd
change the VENC->OPA connection to some other analog tv output at
runtime. I hope that's the case (i.e. OPA is always in use on that board).
If so, then I think you can just pass the acbias and bypass
configuration values via omapdss platform data. And VENC driver will use
them to configure those. OPA doesn't know anything about this at all.
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [RFC 03/23] OMAPDSS: raw read and write endian fix
From: Tomi Valkeinen @ 2013-11-18 13:13 UTC (permalink / raw)
To: Taras Kondratiuk, linux-omap
Cc: linaro-networking, Victor Kamensky,
Jean-Christophe Plagniol-Villard, linux-fbdev, linux-kernel
In-Reply-To: <1384560086-11994-4-git-send-email-taras.kondratiuk@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 709 bytes --]
On 2013-11-16 02:01, Taras Kondratiuk wrote:
> From: Victor Kamensky <victor.kamensky@linaro.org>
>
> All OMAP IP blocks expect LE data, but CPU may operate in BE mode.
> Need to use endian neutral functions to read/write h/w registers.
> I.e instead of __raw_read[lw] and __raw_write[lw] functions code
> need to use read[lw]_relaxed and write[lw]_relaxed functions.
> If the first simply reads/writes register, the second will byteswap
> it if host operates in BE mode.
>
> Changes are trivial sed like replacement of __raw_xxx functions
> with xxx_relaxed variant.
>
Looks fine to me. Quick test with o4 panda works fine.
Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Tomi
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* [PATCH 6/6] OMAPDSS: use runtime PM's autosuspend
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Use runtime PM's autosuspend support with delay of 100ms.
This will prevent the driver from turning the DSS modules off and on
multiple times e.g. when loading the module.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 5 ++++-
drivers/video/omap2/dss/dsi.c | 5 ++++-
drivers/video/omap2/dss/dss.c | 5 ++++-
drivers/video/omap2/dss/dss.h | 2 ++
drivers/video/omap2/dss/hdmi4.c | 5 ++++-
drivers/video/omap2/dss/rfbi.c | 5 ++++-
drivers/video/omap2/dss/venc.c | 5 ++++-
7 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 58f3626..0643eb0 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -258,7 +258,8 @@ void dispc_runtime_put(void)
DSSDBG("dispc_runtime_put\n");
- r = pm_runtime_put_sync(&dispc.pdev->dev);
+ pm_runtime_mark_last_busy(&dispc.pdev->dev);
+ r = pm_runtime_put_autosuspend(&dispc.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
EXPORT_SYMBOL(dispc_runtime_put);
@@ -3440,6 +3441,8 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = dispc_runtime_get();
if (r)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 6b30a58..19e4cad 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1110,7 +1110,8 @@ void dsi_runtime_put(struct platform_device *dsidev)
DSSDBG("dsi_runtime_put\n");
- r = pm_runtime_put_sync(&dsi->pdev->dev);
+ pm_runtime_mark_last_busy(&dsi->pdev->dev);
+ r = pm_runtime_put_autosuspend(&dsi->pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -5416,6 +5417,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
return r;
pm_runtime_enable(&dsidev->dev);
+ pm_runtime_set_autosuspend_delay(&dsidev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&dsidev->dev);
r = dsi_runtime_get(dsidev);
if (r)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index fa7bc00..d3b0122 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -689,7 +689,8 @@ static void dss_runtime_put(void)
DSSDBG("dss_runtime_put\n");
- r = pm_runtime_put_sync(&dss.pdev->dev);
+ pm_runtime_mark_last_busy(&dss.pdev->dev);
+ r = pm_runtime_put_autosuspend(&dss.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY);
}
@@ -821,6 +822,8 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
goto err_setup_clocks;
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = dss_runtime_get();
if (r)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index af83c4d..96505f0 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -73,6 +73,8 @@
#define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+#define DSS_AUTOSUSPEND_DELAY 100 /* in ms */
+
enum dss_io_pad_mode {
DSS_IO_PAD_MODE_RESET,
DSS_IO_PAD_MODE_RFBI,
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
index f1a45fe..f255641 100644
--- a/drivers/video/omap2/dss/hdmi4.c
+++ b/drivers/video/omap2/dss/hdmi4.c
@@ -77,7 +77,8 @@ static void hdmi_runtime_put(void)
DSSDBG("hdmi_runtime_put\n");
- r = pm_runtime_put_sync(&hdmi.pdev->dev);
+ pm_runtime_mark_last_busy(&hdmi.pdev->dev);
+ r = pm_runtime_put_autosuspend(&hdmi.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -631,6 +632,8 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
hdmi_init_output(pdev);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 74d3ed1..20dcbfb 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -147,7 +147,8 @@ static void rfbi_runtime_put(void)
DSSDBG("rfbi_runtime_put\n");
- r = pm_runtime_put_sync(&rfbi.pdev->dev);
+ pm_runtime_mark_last_busy(&rfbi.pdev->dev);
+ r = pm_runtime_put_autosuspend(&rfbi.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -981,6 +982,8 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
clk_put(clk);
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = rfbi_runtime_get();
if (r)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index e173961..bbd35bb 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -410,7 +410,8 @@ static void venc_runtime_put(void)
DSSDBG("venc_runtime_put\n");
- r = pm_runtime_put_sync(&venc.pdev->dev);
+ pm_runtime_mark_last_busy(&venc.pdev->dev);
+ r = pm_runtime_put_autosuspend(&venc.pdev->dev);
WARN_ON(r < 0 && r != -ENOSYS);
}
@@ -835,6 +836,8 @@ static int omap_venchw_probe(struct platform_device *pdev)
return r;
pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, DSS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
r = venc_runtime_get();
if (r)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/6] OMAPDSS: add debug print for runtime suspend/resume
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Add consistent debug prints on all suspend & resume callbacks in omapdss
to make it simpler to debug runtime PM.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 4 ++++
drivers/video/omap2/dss/dsi.c | 4 ++++
drivers/video/omap2/dss/dss.c | 5 +++++
drivers/video/omap2/dss/hdmi4.c | 4 ++++
drivers/video/omap2/dss/rfbi.c | 4 ++++
drivers/video/omap2/dss/venc.c | 4 ++++
6 files changed, 25 insertions(+)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 54716ad..58f3626 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -3475,11 +3475,15 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
return 0;
}
static int dispc_runtime_resume(struct device *dev)
{
+ DSSDBG("resume\n");
+
_omap_dispc_initial_config();
return 0;
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 6056b27..6b30a58 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -5477,6 +5477,8 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
static int dsi_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
dispc_runtime_put();
return 0;
@@ -5486,6 +5488,8 @@ static int dsi_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 0b78c89..fa7bc00 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -872,6 +872,8 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev)
static int dss_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
dss.ctx.control = dss_read_reg(DSS_CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@@ -889,6 +891,9 @@ static int dss_runtime_suspend(struct device *dev)
static int dss_runtime_resume(struct device *dev)
{
int r;
+
+ DSSDBG("resume\n");
+
/*
* Set an arbitrarily high tput request to ensure OPP100.
* What we should really do is to make a request to stay in OPP100,
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c
index e140096..f1a45fe 100644
--- a/drivers/video/omap2/dss/hdmi4.c
+++ b/drivers/video/omap2/dss/hdmi4.c
@@ -650,6 +650,8 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
static int hdmi_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
clk_disable_unprepare(hdmi.sys_clk);
dispc_runtime_put();
@@ -661,6 +663,8 @@ static int hdmi_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r < 0)
return r;
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index c8a81a2..74d3ed1 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -1016,6 +1016,8 @@ static int __exit omap_rfbihw_remove(struct platform_device *pdev)
static int rfbi_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
dispc_runtime_put();
return 0;
@@ -1025,6 +1027,8 @@ static int rfbi_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r < 0)
return r;
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 5f88ac4..e173961 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -867,6 +867,8 @@ static int __exit omap_venchw_remove(struct platform_device *pdev)
static int venc_runtime_suspend(struct device *dev)
{
+ DSSDBG("suspend\n");
+
if (venc.tv_dac_clk)
clk_disable_unprepare(venc.tv_dac_clk);
@@ -879,6 +881,8 @@ static int venc_runtime_resume(struct device *dev)
{
int r;
+ DSSDBG("resume\n");
+
r = dispc_runtime_get();
if (r < 0)
return r;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/6] OMAPDSS: remove dss_get_ctx_loss_count
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
OMAPDSS driver no longer needs dss_get_ctx_loss_count, so it can be
removed.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
arch/arm/mach-omap2/display.c | 1 -
drivers/video/omap2/dss/dss.c | 16 ----------------
drivers/video/omap2/dss/dss.h | 2 --
include/video/omapdss.h | 1 -
4 files changed, 20 deletions(-)
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 03a0516..e6d219c 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -341,7 +341,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
board_data->version = ver;
board_data->dsi_enable_pads = omap_dsi_enable_pads;
board_data->dsi_disable_pads = omap_dsi_disable_pads;
- board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
board_data->set_min_bus_tput = omap_dss_set_min_bus_tput;
omap_display_device.dev.platform_data = board_data;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index a5f674f..0b78c89 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -116,22 +116,6 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
return __raw_readl(dss.base + idx.idx);
}
-int dss_get_ctx_loss_count(void)
-{
- struct platform_device *core_pdev = dss_get_core_pdev();
- struct omap_dss_board_info *board_data = core_pdev->dev.platform_data;
- int cnt;
-
- if (!board_data->get_context_loss_count)
- return -ENOENT;
-
- cnt = board_data->get_context_loss_count(&dss.pdev->dev);
-
- WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
-
- return cnt;
-}
-
void dss_sdi_init(int datapairs)
{
u32 l;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f538e86..af83c4d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -233,8 +233,6 @@ void dss_dump_clocks(struct seq_file *s);
void dss_debug_dump_clocks(struct seq_file *s);
#endif
-int dss_get_ctx_loss_count(void);
-
void dss_sdi_init(int datapairs);
int dss_sdi_enable(void);
void dss_sdi_disable(void);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 3d7c51a..1eb9aa6 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -323,7 +323,6 @@ enum omapdss_version {
/* Board specific data */
struct omap_dss_board_info {
- int (*get_context_loss_count)(struct device *dev);
int num_devices;
struct omap_dss_device **devices;
struct omap_dss_device *default_device;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/6] OMAPDSS: DSS remove ctx stuff
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
The DSS core driver's suspend/resume can be cleaned up by storing the
required registers to a 'dss_context' struct, instead of having a 512
byte block of memory where the registers are directly stored.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dss.c | 77 ++++++++++++++++---------------------------
1 file changed, 28 insertions(+), 49 deletions(-)
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index bd01608..a5f674f 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -39,8 +39,6 @@
#include "dss.h"
#include "dss_features.h"
-#define DSS_SZ_REGS SZ_512
-
struct dss_reg {
u16 idx;
};
@@ -71,6 +69,13 @@ struct dss_features {
int (*dpi_select_source)(enum omap_channel channel);
};
+struct dss_context {
+ bool valid;
+ u32 control;
+ u32 sdi_control;
+ u32 pll_control;
+};
+
static struct {
struct platform_device *pdev;
void __iomem *base;
@@ -88,8 +93,7 @@ static struct {
enum omap_dss_clk_source dispc_clk_source;
enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
- bool ctx_valid;
- u32 ctx[DSS_SZ_REGS / sizeof(u32)];
+ struct dss_context ctx;
const struct dss_features *feat;
} dss;
@@ -112,49 +116,6 @@ static inline u32 dss_read_reg(const struct dss_reg idx)
return __raw_readl(dss.base + idx.idx);
}
-#define SR(reg) \
- dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
-#define RR(reg) \
- dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
-
-static void dss_save_context(void)
-{
- DSSDBG("dss_save_context\n");
-
- SR(CONTROL);
-
- if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
- OMAP_DISPLAY_TYPE_SDI) {
- SR(SDI_CONTROL);
- SR(PLL_CONTROL);
- }
-
- dss.ctx_valid = true;
-
- DSSDBG("context saved\n");
-}
-
-static void dss_restore_context(void)
-{
- DSSDBG("dss_restore_context\n");
-
- if (!dss.ctx_valid)
- return;
-
- RR(CONTROL);
-
- if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
- OMAP_DISPLAY_TYPE_SDI) {
- RR(SDI_CONTROL);
- RR(PLL_CONTROL);
- }
-
- DSSDBG("context restored\n");
-}
-
-#undef SR
-#undef RR
-
int dss_get_ctx_loss_count(void)
{
struct platform_device *core_pdev = dss_get_core_pdev();
@@ -927,7 +888,16 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev)
static int dss_runtime_suspend(struct device *dev)
{
- dss_save_context();
+ dss.ctx.control = dss_read_reg(DSS_CONTROL);
+
+ if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+ OMAP_DISPLAY_TYPE_SDI) {
+ dss.ctx.sdi_control = dss_read_reg(DSS_SDI_CONTROL);
+ dss.ctx.pll_control = dss_read_reg(DSS_PLL_CONTROL);
+ }
+
+ dss.ctx.valid = true;
+
dss_set_min_bus_tput(dev, 0);
return 0;
}
@@ -946,7 +916,16 @@ static int dss_runtime_resume(struct device *dev)
if (r)
return r;
- dss_restore_context();
+ if (dss.ctx.valid) {
+ dss_write_reg(DSS_CONTROL, dss.ctx.control);
+
+ if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
+ OMAP_DISPLAY_TYPE_SDI) {
+ dss_write_reg(DSS_SDI_CONTROL, dss.ctx.sdi_control);
+ dss_write_reg(DSS_PLL_CONTROL, dss.ctx.pll_control);
+ }
+ }
+
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/6] OMAPDSS: DISPC: Remove context restore
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Now that the apply layer writes the registers after DISPC has been
resumed, we can remove all the context restore code.
Only _omap_dispc_initial_config call is needed on resume, which
configures the non-user-configurable registers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/dispc.c | 255 +---------------------------------------
1 file changed, 1 insertion(+), 254 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 91c687f..54716ad 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -43,9 +43,6 @@
#include "dss_features.h"
#include "dispc.h"
-/* DISPC */
-#define DISPC_SZ_REGS SZ_4K
-
enum omap_burst_size {
BURST_SIZE_X2 = 0,
BURST_SIZE_X4 = 1,
@@ -98,8 +95,6 @@ static struct {
struct platform_device *pdev;
void __iomem *base;
- int ctx_loss_cnt;
-
int irq;
unsigned long core_clk_rate;
@@ -109,9 +104,6 @@ static struct {
/* maps which plane is using a fifo. fifo-id -> plane-id */
int fifo_assignment[DISPC_MAX_NR_FIFOS];
- bool ctx_valid;
- u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
-
const struct dispc_features *feat;
} dispc;
@@ -248,249 +240,6 @@ static void mgr_fld_write(enum omap_channel channel,
REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
}
-#define SR(reg) \
- dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
-#define RR(reg) \
- dispc_write_reg(DISPC_##reg, dispc.ctx[DISPC_##reg / sizeof(u32)])
-
-static void dispc_save_context(void)
-{
- int i, j;
-
- DSSDBG("dispc_save_context\n");
-
- SR(IRQENABLE);
- SR(CONTROL);
- SR(CONFIG);
- SR(LINE_NUMBER);
- if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
- SR(GLOBAL_ALPHA);
- if (dss_has_feature(FEAT_MGR_LCD2)) {
- SR(CONTROL2);
- SR(CONFIG2);
- }
- if (dss_has_feature(FEAT_MGR_LCD3)) {
- SR(CONTROL3);
- SR(CONFIG3);
- }
-
- for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
- SR(DEFAULT_COLOR(i));
- SR(TRANS_COLOR(i));
- SR(SIZE_MGR(i));
- if (i = OMAP_DSS_CHANNEL_DIGIT)
- continue;
- SR(TIMING_H(i));
- SR(TIMING_V(i));
- SR(POL_FREQ(i));
- SR(DIVISORo(i));
-
- SR(DATA_CYCLE1(i));
- SR(DATA_CYCLE2(i));
- SR(DATA_CYCLE3(i));
-
- if (dss_has_feature(FEAT_CPR)) {
- SR(CPR_COEF_R(i));
- SR(CPR_COEF_G(i));
- SR(CPR_COEF_B(i));
- }
- }
-
- for (i = 0; i < dss_feat_get_num_ovls(); i++) {
- SR(OVL_BA0(i));
- SR(OVL_BA1(i));
- SR(OVL_POSITION(i));
- SR(OVL_SIZE(i));
- SR(OVL_ATTRIBUTES(i));
- SR(OVL_FIFO_THRESHOLD(i));
- SR(OVL_ROW_INC(i));
- SR(OVL_PIXEL_INC(i));
- if (dss_has_feature(FEAT_PRELOAD))
- SR(OVL_PRELOAD(i));
- if (i = OMAP_DSS_GFX) {
- SR(OVL_WINDOW_SKIP(i));
- SR(OVL_TABLE_BA(i));
- continue;
- }
- SR(OVL_FIR(i));
- SR(OVL_PICTURE_SIZE(i));
- SR(OVL_ACCU0(i));
- SR(OVL_ACCU1(i));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_H(i, j));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_HV(i, j));
-
- for (j = 0; j < 5; j++)
- SR(OVL_CONV_COEF(i, j));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_V(i, j));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- SR(OVL_BA0_UV(i));
- SR(OVL_BA1_UV(i));
- SR(OVL_FIR2(i));
- SR(OVL_ACCU2_0(i));
- SR(OVL_ACCU2_1(i));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_H2(i, j));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_HV2(i, j));
-
- for (j = 0; j < 8; j++)
- SR(OVL_FIR_COEF_V2(i, j));
- }
- if (dss_has_feature(FEAT_ATTR2))
- SR(OVL_ATTRIBUTES2(i));
- }
-
- if (dss_has_feature(FEAT_CORE_CLK_DIV))
- SR(DIVISOR);
-
- dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
- dispc.ctx_valid = true;
-
- DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
-}
-
-static void dispc_restore_context(void)
-{
- int i, j, ctx;
-
- DSSDBG("dispc_restore_context\n");
-
- if (!dispc.ctx_valid)
- return;
-
- ctx = dss_get_ctx_loss_count();
-
- if (ctx >= 0 && ctx = dispc.ctx_loss_cnt)
- return;
-
- DSSDBG("ctx_loss_count: saved %d, current %d\n",
- dispc.ctx_loss_cnt, ctx);
-
- /*RR(IRQENABLE);*/
- /*RR(CONTROL);*/
- RR(CONFIG);
- RR(LINE_NUMBER);
- if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) ||
- dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
- RR(GLOBAL_ALPHA);
- if (dss_has_feature(FEAT_MGR_LCD2))
- RR(CONFIG2);
- if (dss_has_feature(FEAT_MGR_LCD3))
- RR(CONFIG3);
-
- for (i = 0; i < dss_feat_get_num_mgrs(); i++) {
- RR(DEFAULT_COLOR(i));
- RR(TRANS_COLOR(i));
- RR(SIZE_MGR(i));
- if (i = OMAP_DSS_CHANNEL_DIGIT)
- continue;
- RR(TIMING_H(i));
- RR(TIMING_V(i));
- RR(POL_FREQ(i));
- RR(DIVISORo(i));
-
- RR(DATA_CYCLE1(i));
- RR(DATA_CYCLE2(i));
- RR(DATA_CYCLE3(i));
-
- if (dss_has_feature(FEAT_CPR)) {
- RR(CPR_COEF_R(i));
- RR(CPR_COEF_G(i));
- RR(CPR_COEF_B(i));
- }
- }
-
- for (i = 0; i < dss_feat_get_num_ovls(); i++) {
- RR(OVL_BA0(i));
- RR(OVL_BA1(i));
- RR(OVL_POSITION(i));
- RR(OVL_SIZE(i));
- RR(OVL_ATTRIBUTES(i));
- RR(OVL_FIFO_THRESHOLD(i));
- RR(OVL_ROW_INC(i));
- RR(OVL_PIXEL_INC(i));
- if (dss_has_feature(FEAT_PRELOAD))
- RR(OVL_PRELOAD(i));
- if (i = OMAP_DSS_GFX) {
- RR(OVL_WINDOW_SKIP(i));
- RR(OVL_TABLE_BA(i));
- continue;
- }
- RR(OVL_FIR(i));
- RR(OVL_PICTURE_SIZE(i));
- RR(OVL_ACCU0(i));
- RR(OVL_ACCU1(i));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_H(i, j));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_HV(i, j));
-
- for (j = 0; j < 5; j++)
- RR(OVL_CONV_COEF(i, j));
-
- if (dss_has_feature(FEAT_FIR_COEF_V)) {
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_V(i, j));
- }
-
- if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
- RR(OVL_BA0_UV(i));
- RR(OVL_BA1_UV(i));
- RR(OVL_FIR2(i));
- RR(OVL_ACCU2_0(i));
- RR(OVL_ACCU2_1(i));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_H2(i, j));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_HV2(i, j));
-
- for (j = 0; j < 8; j++)
- RR(OVL_FIR_COEF_V2(i, j));
- }
- if (dss_has_feature(FEAT_ATTR2))
- RR(OVL_ATTRIBUTES2(i));
- }
-
- if (dss_has_feature(FEAT_CORE_CLK_DIV))
- RR(DIVISOR);
-
- /* enable last, because LCD & DIGIT enable are here */
- RR(CONTROL);
- if (dss_has_feature(FEAT_MGR_LCD2))
- RR(CONTROL2);
- if (dss_has_feature(FEAT_MGR_LCD3))
- RR(CONTROL3);
- /* clear spurious SYNC_LOST_DIGIT interrupts */
- dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
-
- /*
- * enable last so IRQs won't trigger before
- * the context is fully restored
- */
- RR(IRQENABLE);
-
- DSSDBG("context restored\n");
-}
-
-#undef SR
-#undef RR
-
int dispc_runtime_get(void)
{
int r;
@@ -3726,14 +3475,12 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
static int dispc_runtime_suspend(struct device *dev)
{
- dispc_save_context();
-
return 0;
}
static int dispc_runtime_resume(struct device *dev)
{
- dispc_restore_context();
+ _omap_dispc_initial_config();
return 0;
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/6] OMAPDSS: APPLY: set infos to dirty on enable
From: Tomi Valkeinen @ 2013-11-18 12:50 UTC (permalink / raw)
To: linux-fbdev, linux-omap; +Cc: Archit Taneja, Tomi Valkeinen
In-Reply-To: <1384779009-10512-1-git-send-email-tomi.valkeinen@ti.com>
Currently when DISPC is suspended, the driver stores all DISPC registers
to memory, so that they can be restored on resume. This is a bad way to
handle suspend/resume, as it's prone to failures and requires somewhat
large amount of extra space to store the registers.
A better approach is to program the DISPC from scratch when resuming.
This can be easily accomplished in apply layer by setting the manager
and overlay infos to dirty when the manager is to be enabled.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
drivers/video/omap2/dss/apply.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 60758db..6ab4cb6 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -1072,6 +1072,7 @@ static void dss_setup_fifos(void)
static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
{
struct mgr_priv_data *mp = get_mgr_priv(mgr);
+ struct omap_overlay *ovl;
unsigned long flags;
int r;
@@ -1091,6 +1092,27 @@ static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
goto err;
}
+ /*
+ * Mark the info & extra_info dirty for the manager and its enabled
+ * overlays to force register writes. This ensures that the relevant
+ * registers are set after DSS has been off and the registers have been
+ * reset.
+ */
+
+ mp->info_dirty = true;
+ mp->extra_info_dirty = true;
+
+ list_for_each_entry(ovl, &mgr->overlays, list) {
+ struct ovl_priv_data *op = get_ovl_priv(ovl);
+
+ if (!op->enabled)
+ continue;
+
+ op->info_dirty = true;
+ op->extra_info_dirty = true;
+ dispc_ovl_set_channel_out(ovl->id, mgr->id);
+ }
+
dss_setup_fifos();
dss_write_regs();
--
1.8.3.2
^ permalink raw reply related
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