* [PATCH v16 RESEND 7/7] drm_modes: add of_videomode helpers
From: Steffen Trumtrar @ 2013-01-21 11:08 UTC (permalink / raw)
To: devicetree-discuss, David Airlie
Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
linux-media, Tomi Valkeinen, Stephen Warren,
Florian Tobias Schandinat, Rob Clark, Leela Krishna Amudala,
Mohammed, Afzal, kernel
In-Reply-To: <1358766482-6275-1-git-send-email-s.trumtrar@pengutronix.de>
Add helper to get drm_display_mode from devicetree.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Afzal Mohammed <Afzal@ti.com>
---
drivers/gpu/drm/drm_modes.c | 33 +++++++++++++++++++++++++++++++++
include/drm/drmP.h | 4 ++++
2 files changed, 37 insertions(+)
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 184a22d..fd53454 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -35,6 +35,7 @@
#include <linux/export.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
+#include <video/of_videomode.h>
#include <video/videomode.h>
/**
@@ -541,6 +542,38 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
#endif
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+/**
+ * of_get_drm_display_mode - get a drm_display_mode from devicetree
+ * @np: device_node with the timing specification
+ * @dmode: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings and
+ * work with that instead.
+ */
+int of_get_drm_display_mode(struct device_node *np,
+ struct drm_display_mode *dmode, int index)
+{
+ struct videomode vm;
+ int ret;
+
+ ret = of_get_videomode(np, &vm, index);
+ if (ret)
+ return ret;
+
+ drm_display_mode_from_videomode(&vm, dmode);
+
+ pr_debug("%s: got %dx%d display mode from %s\n",
+ of_node_full_name(np), vm.hactive, vm.vactive, np->name);
+ drm_mode_debug_printmodeline(dmode);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
+#endif
+
/**
* drm_mode_set_name - set the name on a mode
* @mode: name will be set in this mode
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 5fbb0fe..e26ca59 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -85,6 +85,7 @@ struct module;
struct drm_file;
struct drm_device;
+struct device_node;
struct videomode;
#include <drm/drm_os_linux.h>
@@ -1458,6 +1459,9 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
extern int drm_display_mode_from_videomode(const struct videomode *vm,
struct drm_display_mode *dmode);
+extern int of_get_drm_display_mode(struct device_node *np,
+ struct drm_display_mode *dmode,
+ int index);
/* Modesetting support */
extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Stephen Warren @ 2013-01-21 17:46 UTC (permalink / raw)
To: Alexandre Courbot
Cc: Thierry Reding, linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, Mark Zhang,
gnurou-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1358591420-7790-3-git-send-email-acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
On 01/19/2013 03:30 AM, Alexandre Courbot wrote:
> Add a PWM-backlight subdriver for Tegra boards, with support for
> Ventana.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
> arch/arm/boot/dts/tegra20-ventana.dts | 18 +++-
> arch/arm/configs/tegra_defconfig | 1 +
> drivers/video/backlight/Kconfig | 7 ++
> drivers/video/backlight/pwm_bl.c | 3 +
> drivers/video/backlight/pwm_bl_tegra.c | 159 +++++++++++++++++++++++++++++++++
This should be at least 3 separate patches: (1) Driver code (2) Ventana
.dts file (3) Tegra defconfig.
> diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
> + backlight {
> + compatible = "pwm-backlight-ventana";
If this is Ventana-specific, this should have a vendor prefix; "nvidia,"
would be appropriate.
But, why is this Ventana-specific; surely it's at most panel-specific,
or perhaps even generic across any/most LCD panels?
There needs to be binding documentation.
> + 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 = <&vdd_bl_reg>;
"power" doesn't seem like a good regulator name; power to what? Is this
for the backlight, since I see there's a panel-supply below?
> + panel-supply = <&vdd_pnl_reg>;
> + bl-gpio = <&gpio 28 0>;
> + bl-panel = <&gpio 10 0>;
GPIO names usually have "gpios" in their name, so I assume those should
be bl-enable-gpios, panel-enable-gpios?
> diff --git a/drivers/video/backlight/pwm_bl_tegra.c b/drivers/video/backlight/pwm_bl_tegra.c
> +static void exit_ventana(struct device *dev)
> +{
> + struct ventana_bl_data *data = pwm_backlight_get_subdriver_data(dev);
> +
> + devm_gpio_free(dev, data->panel_gpio);
> + devm_gpio_free(dev, data->bl_gpio);
> + devm_regulator_put(data->vdd_panel);
> + devm_regulator_put(data->vdd_power);
> + devm_kfree(dev, data);
> +}
There shouldn't be a need to explicitly free devm-allocated objects in
almost all cases; that's the whole point of the devm APIs.
> +static struct pwm_backlight_subdriver pwm_backlight_ventana_subdriver = {
> + .name = "pwm-backlight-ventana",
> + .init = init_ventana,
> + .exit = exit_ventana,
> + .notify = notify_ventana,
> + .notify_after = notify_after_ventana,
> +};
It seems like all of that code should be completely generic.
> +static int __init pwm_backlight_tegra_init(void)
> +{
> + pwm_backlight_add_subdriver(&pwm_backlight_ventana_subdriver);
> + return 0;
> +}
> +
> +static void __exit pwm_backlight_tegra_exit(void)
> +{
> + pwm_backlight_remove_subdriver(&pwm_backlight_ventana_subdriver);
> +}
> +
> +module_init(pwm_backlight_tegra_init);
> +module_exit(pwm_backlight_tegra_exit);
Rather than invent some new registration mechanism, if we need
board-/panel-/...-specific drivers, it'd be better to make each of those
specific drivers a full platform device in an of itself (i.e. regular
Linux platform device/driver, have its own probe(), etc.), and have
those specific drivers call into the base PWM backlight code, treating
it like a utility API.
> +MODULE_DESCRIPTION("Backlight Driver for Tegra boards");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:pwm-tegra-backlight");
> +
> +
Some extra blank lines there.
^ permalink raw reply
* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Alex Courbot @ 2013-01-22 3:24 UTC (permalink / raw)
To: Stephen Warren
Cc: Thierry Reding,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Mark Zhang,
gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
In-Reply-To: <50FD7EF9.1010205-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
On Tuesday 22 January 2013 01:46:33 Stephen Warren wrote:
> > arch/arm/boot/dts/tegra20-ventana.dts | 18 +++-
> > arch/arm/configs/tegra_defconfig | 1 +
> > drivers/video/backlight/Kconfig | 7 ++
> > drivers/video/backlight/pwm_bl.c | 3 +
> > drivers/video/backlight/pwm_bl_tegra.c | 159
> > +++++++++++++++++++++++++++++++++
> This should be at least 3 separate patches: (1) Driver code (2) Ventana
> .dts file (3) Tegra defconfig.
Will do that.
> If this is Ventana-specific, this should have a vendor prefix; "nvidia,"
> would be appropriate.
>
> But, why is this Ventana-specific; surely it's at most panel-specific,
> or perhaps even generic across any/most LCD panels?
Yes, we could use the panel model here instead. Not sure how many other panels
follow the same powering sequence though.
Making it Ventana-specific would have allowed to group all Tegra board support
into the same driver, and considering that probably not many devices use the
same panels as we do this seemed to make sense at first.
> > + power-supply = <&vdd_bl_reg>;
>
> "power" doesn't seem like a good regulator name; power to what? Is this
> for the backlight, since I see there's a panel-supply below?
>
> > + panel-supply = <&vdd_pnl_reg>;
> >
> > + bl-gpio = <&gpio 28 0>;
> > + bl-panel = <&gpio 10 0>;
>
> GPIO names usually have "gpios" in their name, so I assume those should
> be bl-enable-gpios, panel-enable-gpios?
Indeed, even though there is only one gpio here. Maybe we could group them
into a single property and retrieve them by index - that's what the DT GPIO
APIs seem to be designed for initially.
> > +static struct pwm_backlight_subdriver pwm_backlight_ventana_subdriver = {
> > + .name = "pwm-backlight-ventana",
> > + .init = init_ventana,
> > + .exit = exit_ventana,
> > + .notify = notify_ventana,
> > + .notify_after = notify_after_ventana,
> > +};
>
> It seems like all of that code should be completely generic.
Sorry, I don't get your point here - could you elaborate?
> Rather than invent some new registration mechanism, if we need
> board-/panel-/...-specific drivers, it'd be better to make each of those
> specific drivers a full platform device in an of itself (i.e. regular
> Linux platform device/driver, have its own probe(), etc.), and have
> those specific drivers call into the base PWM backlight code, treating
> it like a utility API.
That's what would make the most sense indeed, but would require some extra
changes in pwm-backlight and might go against Thierry's wish to keep it
simple. On the other hand I totally agree this would be more elegant. Every
pwm-backlight based driver would just need to invoke pwm_bl's probe/remove
function from its own. Thierry, would that be an acceptable alternative to the
sub-driver thing despite the slightly deeper changes this involves?
Thanks,
Alex.
^ permalink raw reply
* Re: [PATCH 30/33] video: Convert to devm_ioremap_resource()
From: Jingoo Han @ 2013-01-22 4:17 UTC (permalink / raw)
To: 'Thierry Reding', linux-kernel
Cc: 'Greg Kroah-Hartman', 'Dmitry Torokhov',
'Arnd Bergmann', 'Wolfram Sang',
'Florian Tobias Schandinat', linux-fbdev,
'Jingoo Han'
In-Reply-To: <1358762966-20791-31-git-send-email-thierry.reding@avionic-design.de>
On Monday, January 21, 2013 7:09 PM, Thierry wrote
>
> Convert all uses of devm_request_and_ioremap() to the newly introduced
> devm_ioremap_resource() which provides more consistent error handling.
>
> devm_ioremap_resource() provides its own error messages so all explicit
> error messages can be removed from the failure code paths.
>
> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
> Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> ---
> drivers/video/exynos/exynos_dp_core.c | 8 +++-----
> drivers/video/jz4740_fb.c | 6 +++---
> drivers/video/omap2/dss/hdmi.c | 8 +++-----
> drivers/video/omap2/vrfb.c | 9 ++++-----
> drivers/video/s3c-fb.c | 7 +++----
> 5 files changed, 16 insertions(+), 22 deletions(-)
>
For drivers/video/s3c-fb.c, drivers/video/exynos/exynos_dp_core.c
Acked-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
^ permalink raw reply
* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Thierry Reding @ 2013-01-22 7:06 UTC (permalink / raw)
To: Alex Courbot
Cc: Stephen Warren, linux-fbdev@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
Mark Zhang, gnurou@gmail.com
In-Reply-To: <12033649.LY58cllSHv@percival>
[-- Attachment #1: Type: text/plain, Size: 4044 bytes --]
On Tue, Jan 22, 2013 at 12:24:34PM +0900, Alex Courbot wrote:
> On Tuesday 22 January 2013 01:46:33 Stephen Warren wrote:
> > > arch/arm/boot/dts/tegra20-ventana.dts | 18 +++-
> > > arch/arm/configs/tegra_defconfig | 1 +
> > > drivers/video/backlight/Kconfig | 7 ++
> > > drivers/video/backlight/pwm_bl.c | 3 +
> > > drivers/video/backlight/pwm_bl_tegra.c | 159
> > > +++++++++++++++++++++++++++++++++
> > This should be at least 3 separate patches: (1) Driver code (2) Ventana
> > .dts file (3) Tegra defconfig.
>
> Will do that.
>
> > If this is Ventana-specific, this should have a vendor prefix; "nvidia,"
> > would be appropriate.
> >
> > But, why is this Ventana-specific; surely it's at most panel-specific,
> > or perhaps even generic across any/most LCD panels?
>
> Yes, we could use the panel model here instead. Not sure how many other panels
> follow the same powering sequence though.
>
> Making it Ventana-specific would have allowed to group all Tegra board support
> into the same driver, and considering that probably not many devices use the
> same panels as we do this seemed to make sense at first.
>
> > > + power-supply = <&vdd_bl_reg>;
> >
> > "power" doesn't seem like a good regulator name; power to what? Is this
> > for the backlight, since I see there's a panel-supply below?
> >
> > > + panel-supply = <&vdd_pnl_reg>;
> > >
> > > + bl-gpio = <&gpio 28 0>;
> > > + bl-panel = <&gpio 10 0>;
> >
> > GPIO names usually have "gpios" in their name, so I assume those should
> > be bl-enable-gpios, panel-enable-gpios?
>
> Indeed, even though there is only one gpio here. Maybe we could group them
> into a single property and retrieve them by index - that's what the DT GPIO
> APIs seem to be designed for initially.
>
> > > +static struct pwm_backlight_subdriver pwm_backlight_ventana_subdriver = {
> > > + .name = "pwm-backlight-ventana",
> > > + .init = init_ventana,
> > > + .exit = exit_ventana,
> > > + .notify = notify_ventana,
> > > + .notify_after = notify_after_ventana,
> > > +};
> >
> > It seems like all of that code should be completely generic.
>
> Sorry, I don't get your point here - could you elaborate?
>
> > Rather than invent some new registration mechanism, if we need
> > board-/panel-/...-specific drivers, it'd be better to make each of those
> > specific drivers a full platform device in an of itself (i.e. regular
> > Linux platform device/driver, have its own probe(), etc.), and have
> > those specific drivers call into the base PWM backlight code, treating
> > it like a utility API.
>
> That's what would make the most sense indeed, but would require some extra
> changes in pwm-backlight and might go against Thierry's wish to keep it
> simple. On the other hand I totally agree this would be more elegant. Every
> pwm-backlight based driver would just need to invoke pwm_bl's probe/remove
> function from its own. Thierry, would that be an acceptable alternative to the
> sub-driver thing despite the slightly deeper changes this involves?
I'm confused. Why would you want to call into pwm_bl directly? If we're
going to split this up into separate platform devices, why not look up a
given backlight device and use the backlight API on that? The pieces of
the puzzle are all there: you can use of_find_backlight_by_node() to
obtain a backlight device from a device tree node, so I'd expect the DT
to look something like this:
backlight: backlight {
compatible = "pwm-backlight";
...
};
panel: panel {
compatible = "...";
...
backlight = <&backlight>;
...
};
After that you can wire it up with host1x using something like:
host1x {
dc@54200000 {
rgb {
status = "okay";
nvidia,panel = <&panel>;
};
};
};
Maybe with such a binding, we should move the various display-timings
properties to the panel node as well and have an API to retrieve them
for use by tegra-drm.
Thierry
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH 0/3] pwm-backlight: add subdrivers & Tegra support
From: Thierry Reding @ 2013-01-22 7:17 UTC (permalink / raw)
To: Alex Courbot
Cc: Stephen Warren,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Mark Zhang,
gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
In-Reply-To: <6871054.sK10m5bePf@percival>
[-- Attachment #1: Type: text/plain, Size: 2461 bytes --]
On Mon, Jan 21, 2013 at 05:18:11PM +0900, Alex Courbot wrote:
> Hi Thierry,
>
> On Monday 21 January 2013 15:49:28 Thierry Reding wrote:
> > Eventually this should all be covered by the CDF, but since that's not
> > ready yet we want something ad-hoc to get the hardware supported. As
> > such I would like to see this go into some sort of minimalistic, Tegra-
> > specific display/panel framework. I'd prefer to keep the pwm-backlight
> > driver as simple and generic as possible, that is, a driver for a PWM-
> > controlled backlight.
> >
> > Another advantage of moving this into a sort of display framework is
> > that it may help in defining the requirements for a CDF and that moving
> > the code to the CDF should be easier once it is done.
> >
> > Last but not least, abstracting away the panel allows other things such
> > as physical dimensions and display modes to be properly encapsulated. I
> > think that power-on/off timing requirements for panels also belong to
> > this set since they are usually specific to a given panel.
> >
> > Maybe adding these drivers to tegra-drm for now would be a good option.
> > That way the corresponding glue can be added without a need for inter-
> > tree dependencies.
>
> IIRC (because that was a while ago already) having a Tegra-only display
> framework is exactly what we wanted to avoid in the first place. This series
> does nothing but leverage the callbacks mechanism that already exists in pwm-
> backlight and make it available to DT systems. If we start making a Tegra-
> specific solution, then other architectures will have to reinvent the wheel
> again. I really don't think we want to go that way.
>
> These patches only makes slight changes to pwm_bl.c and do not extend its
> capabilities. I agree that a suitable solution will require the CDF, but by
> the meantime, let's go for the practical route instead of repeating the same
> mistakes (i.e. architecture-specific frameworks) again.
>
> There are certainly better ways to do this, but I'm not convinced at all that
> a Tegra-only solution is one of them.
Well, your proposal is a Tegra-only solution as well. Anything we come
up with now will be Tegra-only because it will eventually be integrated
with the CDF.
Trying to come up with something generic would be counter-productive.
CDF *is* the generic solution. All we would be doing is add a competing
framework.
Thierry
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH 0/4] pwm_backlight: Error fixes and update for DT support
From: Peter Ujfalusi @ 2013-01-22 13:39 UTC (permalink / raw)
To: Richard Purdie
Cc: Grant Likely, Rob Landley, Thierry Reding,
Florian Tobias Schandinat, Andrew Morton, devicetree-discuss,
linux-doc, linux-kernel, linux-fbdev
Hi,
This small series will:
- Fix the case when the kernel is booted in non DT mode and the board file try
to use levels array to specify the brightness levels.
- Validate the dft_brightness in all cases not only in DT mode.
- Add support in case of DT boot to be able to use the whole range of PWM.
Currently boards in legacy mode uses the 'max_brightness' value to specify the
maximum steps the PWM can be configured. When these boards move to DT support
they can no longer do this, they have to use the levels array. If we want to
have the same range in both DT and non DT case we would need to add all the
numbers from 0 to max (which can be 256) to the 'brightness-levels' array.
With the new property we can simply allow the whole range to be configured.
Regards,
Peter
---
Peter Ujfalusi (4):
pwm_backlight: Fix PWM levels support in non DT case
pwm_backlight: Validate dft_brightness in main probe function
pwm_backlight: Refactor the DT parsing code
pwm_backlight: Add support for the whole range of the PWM in DT mode
.../bindings/video/backlight/pwm-backlight.txt | 12 +++++-
drivers/video/backlight/pwm_bl.c | 49 ++++++++++++----------
2 files changed, 38 insertions(+), 23 deletions(-)
--
1.8.1.1
^ permalink raw reply
* [PATCH 1/4] pwm_backlight: Fix PWM levels support in non DT case
From: Peter Ujfalusi @ 2013-01-22 13:39 UTC (permalink / raw)
To: Richard Purdie
Cc: Grant Likely, Rob Landley, Thierry Reding,
Florian Tobias Schandinat, Andrew Morton, devicetree-discuss,
linux-doc, linux-kernel, linux-fbdev
In-Reply-To: <1358861996-27194-1-git-send-email-peter.ujfalusi@ti.com>
It is expected that board files would have:
static unsigned int bl_levels[] = { 0, 50, 100, 150, 200, 250, };
static struct platform_pwm_backlight_data bl_data = {
.levels = bl_levels,
.max_brightness = ARRAY_SIZE(bl_levels),
.dft_brightness = 4,
.pwm_period_ns = 7812500,
};
In this case the max_brightness would be out of range in the levels array.
Decrement the received max_brightness in every case (DT or non DT) when the
levels has been provided.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/video/backlight/pwm_bl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 069983c..f0d6854 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -142,7 +142,6 @@ static int pwm_backlight_parse_dt(struct device *dev,
}
data->dft_brightness = value;
- data->max_brightness--;
}
/*
@@ -202,6 +201,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
}
if (data->levels) {
+ data->max_brightness--;
max = data->levels[data->max_brightness];
pb->levels = data->levels;
} else
--
1.8.1.1
^ permalink raw reply related
* [PATCH 2/4] pwm_backlight: Validate dft_brightness in main probe function
From: Peter Ujfalusi @ 2013-01-22 13:39 UTC (permalink / raw)
To: Richard Purdie
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Florian Tobias Schandinat,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andrew Morton
In-Reply-To: <1358861996-27194-1-git-send-email-peter.ujfalusi-l0cyMroinI0@public.gmane.org>
Move the dft_brightness validity check from the DT parsing function to the
main probe. In this way we can validate it in case we are booting with or
without DT.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/video/backlight/pwm_bl.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index f0d6854..2a81c24 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -135,12 +135,6 @@ static int pwm_backlight_parse_dt(struct device *dev,
if (ret < 0)
return ret;
- if (value >= data->max_brightness) {
- dev_warn(dev, "invalid default brightness level: %u, using %u\n",
- value, data->max_brightness - 1);
- value = data->max_brightness - 1;
- }
-
data->dft_brightness = value;
}
@@ -249,6 +243,12 @@ static int pwm_backlight_probe(struct platform_device *pdev)
goto err_alloc;
}
+ if (data->dft_brightness > data->max_brightness) {
+ dev_warn(&pdev->dev,
+ "invalid default brightness level: %u, using %u\n",
+ data->dft_brightness, data->max_brightness);
+ data->dft_brightness = data->max_brightness;
+ }
bl->props.brightness = data->dft_brightness;
backlight_update_status(bl);
--
1.8.1.1
^ permalink raw reply related
* [PATCH 3/4] pwm_backlight: Refactor the DT parsing code
From: Peter Ujfalusi @ 2013-01-22 13:39 UTC (permalink / raw)
To: Richard Purdie
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Florian Tobias Schandinat,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andrew Morton
In-Reply-To: <1358861996-27194-1-git-send-email-peter.ujfalusi-l0cyMroinI0@public.gmane.org>
In preparation to support the whole range of the PWM device in a similar way
it is possible when we boot in legacy mode (non DT mode).
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
drivers/video/backlight/pwm_bl.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 2a81c24..df2d115 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -100,7 +100,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
{
struct device_node *node = dev->of_node;
struct property *prop;
- int length;
+ int num_levels = 0;
u32 value;
int ret;
@@ -110,26 +110,27 @@ static int pwm_backlight_parse_dt(struct device *dev,
memset(data, 0, sizeof(*data));
/* determine the number of brightness levels */
- prop = of_find_property(node, "brightness-levels", &length);
+ prop = of_find_property(node, "brightness-levels", &num_levels);
if (!prop)
return -EINVAL;
- data->max_brightness = length / sizeof(u32);
+ num_levels /= sizeof(u32);
/* read brightness levels from DT property */
- if (data->max_brightness > 0) {
- size_t size = sizeof(*data->levels) * data->max_brightness;
+ if (num_levels > 0) {
+ size_t size = sizeof(*data->levels) * num_levels;
data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
if (!data->levels)
return -ENOMEM;
ret = of_property_read_u32_array(node, "brightness-levels",
- data->levels,
- data->max_brightness);
+ data->levels, num_levels);
if (ret < 0)
return ret;
+ data->max_brightness = num_levels;
+
ret = of_property_read_u32(node, "default-brightness-level",
&value);
if (ret < 0)
--
1.8.1.1
^ permalink raw reply related
* [PATCH 4/4] pwm_backlight: Add support for the whole range of the PWM in DT mode
From: Peter Ujfalusi @ 2013-01-22 13:39 UTC (permalink / raw)
To: Richard Purdie
Cc: Grant Likely, Rob Landley, Thierry Reding,
Florian Tobias Schandinat, Andrew Morton, devicetree-discuss,
linux-doc, linux-kernel, linux-fbdev
In-Reply-To: <1358861996-27194-1-git-send-email-peter.ujfalusi@ti.com>
When booting with DT make it possible to use the whole range of the PWM when
controlling the backlight in a same way it is possible when the kernel is
booted in non DT mode.
A new property "max-brightness-level" can be used to specify the maximum
value the PWM can handle (time slots).
DTS files can use either the "brightness-levels" or the "max-brightness-level"
to configure the PWM.
In case both of these properties exist the driver will prefer the
"brightness-levels" over the "max-brightness-level".
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
---
.../bindings/video/backlight/pwm-backlight.txt | 12 +++++++++--
drivers/video/backlight/pwm_bl.c | 24 ++++++++++++++--------
2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
index 1e4fc72..517924b 100644
--- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
@@ -3,13 +3,21 @@ pwm-backlight bindings
Required properties:
- compatible: "pwm-backlight"
- pwms: OF device-tree PWM specification (see PWM binding[0])
+
+ Brightness range can be configured with either "brightness-levels" or with
+ "max-brightness-level".
- 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
from these values. 0 means a 0% duty cycle (darkest/off), while the
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)
+ - max-brightness-level: The maximum brightness level the PWM supports. When
+ the brightness is specified using this property the whole range from 0 to
+ "max-brightness-level" will be available to configure.
+ - default-brightness-level: the default brightness level. With
+ "brightness-levels" it is an index into the array defined by the
+ "brightness-levels" property. When it is used with "max-brightness-level"
+ it is the value in the range from 0 to "max-brightness-level"
Optional properties:
- pwm-names: a list of names for the PWM devices specified in the
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index df2d115..c0e4bc7 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -111,10 +111,17 @@ static int pwm_backlight_parse_dt(struct device *dev,
/* determine the number of brightness levels */
prop = of_find_property(node, "brightness-levels", &num_levels);
- if (!prop)
- return -EINVAL;
+ if (!prop) {
+ /* Levels not provided, look for the maximum property */
+ ret = of_property_read_u32(node, "max-brightness-level",
+ &value);
+ if (ret < 0)
+ return ret;
- num_levels /= sizeof(u32);
+ data->max_brightness = value;
+ } else {
+ num_levels /= sizeof(u32);
+ }
/* read brightness levels from DT property */
if (num_levels > 0) {
@@ -130,14 +137,13 @@ static int pwm_backlight_parse_dt(struct device *dev,
return ret;
data->max_brightness = num_levels;
+ }
- ret = of_property_read_u32(node, "default-brightness-level",
- &value);
- if (ret < 0)
- return ret;
+ ret = of_property_read_u32(node, "default-brightness-level", &value);
+ if (ret < 0)
+ return ret;
- data->dft_brightness = value;
- }
+ data->dft_brightness = value;
/*
* TODO: Most users of this driver use a number of GPIOs to control
--
1.8.1.1
^ permalink raw reply related
* [PATCH 1/3] fb: backlight: Add the Himax HX-8357B LCD controller
From: Maxime Ripard @ 2013-01-22 16:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358871791-14214-1-git-send-email-maxime.ripard@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/video/backlight/Kconfig | 7 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/hx8357.c | 482 ++++++++++++++++++++++++++++++++++++++
3 files changed, 490 insertions(+)
create mode 100644 drivers/video/backlight/hx8357.c
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 765a945..c39bed0 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -126,6 +126,13 @@ config LCD_AMS369FG06
If you have an AMS369FG06 AMOLED Panel, say Y to enable its
LCD control driver.
+config LCD_HX8357
+ tristate "Himax HX-8357 LCD Driver"
+ depends on SPI
+ help
+ If you have a HX-8357 LCD panel, say Y to enable its LCD control
+ driver.
+
endif # LCD_CLASS_DEVICE
#
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index e7ce729..b69d391 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
obj-$(CONFIG_LCD_LD9040) += ld9040.o
obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o
+obj-$(CONFIG_LCD_HX8357) += hx8357.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
new file mode 100644
index 0000000..ee4d607
--- /dev/null
+++ b/drivers/video/backlight/hx8357.c
@@ -0,0 +1,482 @@
+/*
+ * Driver for the Himax HX-8357 LCD Controller
+ *
+ * Copyright 2012 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/delay.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+
+#define HX8357_NUM_IM_PINS 3
+
+#define HX8357_SWRESET 0x01
+#define HX8357_GET_RED_CHANNEL 0x06
+#define HX8357_GET_GREEN_CHANNEL 0x07
+#define HX8357_GET_BLUE_CHANNEL 0x08
+#define HX8357_GET_POWER_MODE 0x0a
+#define HX8357_GET_MADCTL 0x0b
+#define HX8357_GET_PIXEL_FORMAT 0x0c
+#define HX8357_GET_DISPLAY_MODE 0x0d
+#define HX8357_GET_SIGNAL_MODE 0x0e
+#define HX8357_GET_DIAGNOSTIC_RESULT 0x0f
+#define HX8357_ENTER_SLEEP_MODE 0x10
+#define HX8357_EXIT_SLEEP_MODE 0x11
+#define HX8357_ENTER_PARTIAL_MODE 0x12
+#define HX8357_ENTER_NORMAL_MODE 0x13
+#define HX8357_EXIT_INVERSION_MODE 0x20
+#define HX8357_ENTER_INVERSION_MODE 0x21
+#define HX8357_SET_DISPLAY_OFF 0x28
+#define HX8357_SET_DISPLAY_ON 0x29
+#define HX8357_SET_COLUMN_ADDRESS 0x2a
+#define HX8357_SET_PAGE_ADDRESS 0x2b
+#define HX8357_WRITE_MEMORY_START 0x2c
+#define HX8357_READ_MEMORY_START 0x2e
+#define HX8357_SET_PARTIAL_AREA 0x30
+#define HX8357_SET_SCROLL_AREA 0x33
+#define HX8357_SET_TEAR_OFF 0x34
+#define HX8357_SET_TEAR_ON 0x35
+#define HX8357_SET_ADDRESS_MODE 0x36
+#define HX8357_SET_SCROLL_START 0x37
+#define HX8357_EXIT_IDLE_MODE 0x38
+#define HX8357_ENTER_IDLE_MOD 0x39
+#define HX8357_SET_PIXEL_FORMAT 0x3a
+#define HX8357_SET_PIXEL_FORMAT_DBI_3BIT (0x1)
+#define HX8357_SET_PIXEL_FORMAT_DBI_16BIT (0x5)
+#define HX8357_SET_PIXEL_FORMAT_DBI_18BIT (0x6)
+#define HX8357_SET_PIXEL_FORMAT_DPI_3BIT (0x1 << 4)
+#define HX8357_SET_PIXEL_FORMAT_DPI_16BIT (0x5 << 4)
+#define HX8357_SET_PIXEL_FORMAT_DPI_18BIT (0x6 << 4)
+#define HX8357_WRITE_MEMORY_CONTINUE 0x3c
+#define HX8357_READ_MEMORY_CONTINUE 0x3e
+#define HX8357_SET_TEAR_SCAN_LINES 0x44
+#define HX8357_GET_SCAN_LINES 0x45
+#define HX8357_READ_DDB_START 0xa1
+#define HX8357_SET_DISPLAY_MODE 0xb4
+#define HX8357_SET_DISPLAY_MODE_RGB_THROUGH (0x3)
+#define HX8357_SET_DISPLAY_MODE_RGB_INTERFACE (1 << 4)
+#define HX8357_SET_PANEL_DRIVING 0xc0
+#define HX8357_SET_DISPLAY_FRAME 0xc5
+#define HX8357_SET_RGB 0xc6
+#define HX8357_SET_RGB_ENABLE_HIGH (1 << 1)
+#define HX8357_SET_GAMMA 0xc8
+#define HX8357_SET_POWER 0xd0
+#define HX8357_SET_VCOM 0xd1
+#define HX8357_SET_POWER_NORMAL 0xd2
+#define HX8357_SET_PANEL_RELATED 0xe9
+
+struct hx8357_data {
+ unsigned im_pins[HX8357_NUM_IM_PINS];
+ unsigned reset;
+ struct spi_device *spi;
+ int state;
+};
+
+static int hx8357_spi_write_then_read(struct lcd_device *lcdev,
+ void *txbuf, u16 txlen,
+ void *rxbuf, u16 rxlen)
+{
+ struct hx8357_data *lcd = lcd_get_data(lcdev);
+ struct spi_message msg;
+ struct spi_transfer xfer[2];
+ u16 *local_txbuf = NULL;
+ int ret = 0;
+
+ memset(xfer, 0, sizeof(xfer));
+ spi_message_init(&msg);
+
+ if (txlen) {
+ int i;
+
+ local_txbuf = kcalloc(sizeof(*local_txbuf), txlen, GFP_KERNEL);
+
+ if (!local_txbuf) {
+ dev_err(&lcdev->dev, "Couldn't allocate data buffer.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < txlen; i++) {
+ local_txbuf[i] = ((u8 *)txbuf)[i];
+ if (i > 0)
+ local_txbuf[i] |= 1 << 8;
+ }
+
+ xfer[0].len = 2 * txlen;
+ xfer[0].bits_per_word = 9;
+ xfer[0].tx_buf = local_txbuf;
+ spi_message_add_tail(&xfer[0], &msg);
+ }
+
+ if (rxlen) {
+ xfer[1].len = rxlen;
+ xfer[1].bits_per_word = 8;
+ xfer[1].rx_buf = rxbuf;
+ spi_message_add_tail(&xfer[1], &msg);
+ }
+
+ ret = spi_sync(lcd->spi, &msg);
+ if (ret < 0)
+ dev_err(&lcdev->dev, "Couldn't send SPI data.\n");
+
+ if (txlen)
+ kfree(local_txbuf);
+
+ return ret;
+}
+
+static inline int hx8357_spi_write_array(struct lcd_device *lcdev,
+ u8 *value, u8 len)
+{
+ return hx8357_spi_write_then_read(lcdev, value, len, NULL, 0);
+}
+
+static inline int hx8357_spi_write_byte(struct lcd_device *lcdev,
+ u8 value)
+{
+ return hx8357_spi_write_then_read(lcdev, &value, 1, NULL, 0);
+}
+
+static int hx8357_enter_standby(struct lcd_device *lcdev)
+{
+ int ret;
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_OFF);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(10000, 12000);
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_ENTER_SLEEP_MODE);
+ if (ret < 0)
+ return ret;
+
+ msleep(120);
+
+ return 0;
+}
+
+static int hx8357_exit_standby(struct lcd_device *lcdev)
+{
+ int ret;
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
+ if (ret < 0)
+ return ret;
+
+ msleep(120);
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int hx8357_lcd_init(struct lcd_device *lcdev)
+{
+ struct hx8357_data *lcd = lcd_get_data(lcdev);
+ u8 buf[16];
+ int ret;
+
+ /*
+ * Set the interface selection pins to SPI mode, with three
+ * wires
+ */
+ gpio_set_value_cansleep(lcd->im_pins[0], 1);
+ gpio_set_value_cansleep(lcd->im_pins[1], 0);
+ gpio_set_value_cansleep(lcd->im_pins[2], 1);
+
+ /* Reset the screen */
+ gpio_set_value(lcd->reset, 1);
+ usleep_range(10000, 12000);
+ gpio_set_value(lcd->reset, 0);
+ usleep_range(10000, 12000);
+ gpio_set_value(lcd->reset, 1);
+ msleep(120);
+
+ buf[0] = HX8357_SET_POWER;
+ buf[1] = 0x44;
+ buf[2] = 0x41;
+ buf[3] = 0x06;
+ ret = hx8357_spi_write_array(lcdev, buf, 4);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_VCOM;
+ buf[1] = 0x40;
+ buf[2] = 0x10;
+ ret = hx8357_spi_write_array(lcdev, buf, 3);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_POWER_NORMAL;
+ buf[1] = 0x05;
+ buf[2] = 0x12;
+ ret = hx8357_spi_write_array(lcdev, buf, 3);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_PANEL_DRIVING;
+ buf[1] = 0x14;
+ buf[2] = 0x3b;
+ buf[3] = 0x00;
+ buf[4] = 0x02;
+ buf[5] = 0x11;
+ ret = hx8357_spi_write_array(lcdev, buf, 6);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_DISPLAY_FRAME;
+ buf[1] = 0x0c;
+ ret = hx8357_spi_write_array(lcdev, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_PANEL_RELATED;
+ buf[1] = 0x01;
+ ret = hx8357_spi_write_array(lcdev, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = 0xea;
+ buf[1] = 0x03;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ ret = hx8357_spi_write_array(lcdev, buf, 4);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = 0xeb;
+ buf[1] = 0x40;
+ buf[2] = 0x54;
+ buf[3] = 0x26;
+ buf[4] = 0xdb;
+ ret = hx8357_spi_write_array(lcdev, buf, 5);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_GAMMA;
+ buf[1] = 0x00;
+ buf[2] = 0x15;
+ buf[3] = 0x00;
+ buf[4] = 0x22;
+ buf[5] = 0x00;
+ buf[6] = 0x08;
+ buf[7] = 0x77;
+ buf[8] = 0x26;
+ buf[9] = 0x77;
+ buf[10] = 0x22;
+ buf[11] = 0x04;
+ buf[12] = 0x00;
+ ret = hx8357_spi_write_array(lcdev, buf, 13);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_ADDRESS_MODE;
+ buf[1] = 0xc0;
+ ret = hx8357_spi_write_array(lcdev, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_PIXEL_FORMAT;
+ buf[1] = HX8357_SET_PIXEL_FORMAT_DPI_18BIT |
+ HX8357_SET_PIXEL_FORMAT_DBI_18BIT;
+ ret = hx8357_spi_write_array(lcdev, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_COLUMN_ADDRESS;
+ buf[1] = 0x00;
+ buf[2] = 0x00;
+ buf[3] = 0x01;
+ buf[4] = 0x3f;
+ ret = hx8357_spi_write_array(lcdev, buf, 5);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_PAGE_ADDRESS;
+ buf[1] = 0x00;
+ buf[2] = 0x00;
+ buf[3] = 0x01;
+ buf[4] = 0xdf;
+ ret = hx8357_spi_write_array(lcdev, buf, 5);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_RGB;
+ buf[1] = 0x02;
+ ret = hx8357_spi_write_array(lcdev, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ buf[0] = HX8357_SET_DISPLAY_MODE;
+ buf[1] = HX8357_SET_DISPLAY_MODE_RGB_THROUGH |
+ HX8357_SET_DISPLAY_MODE_RGB_INTERFACE;
+ ret = hx8357_spi_write_array(lcdev, buf, 2);
+ if (ret < 0)
+ return ret;
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_EXIT_SLEEP_MODE);
+ if (ret < 0)
+ return ret;
+
+ msleep(120);
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_SET_DISPLAY_ON);
+ if (ret < 0)
+ return ret;
+
+ usleep_range(5000, 7000);
+
+ ret = hx8357_spi_write_byte(lcdev, HX8357_WRITE_MEMORY_START);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
+
+static int hx8357_set_power(struct lcd_device *lcdev, int power)
+{
+ struct hx8357_data *lcd = lcd_get_data(lcdev);
+ int ret = 0;
+
+ if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->state))
+ ret = hx8357_exit_standby(lcdev);
+ else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->state))
+ ret = hx8357_enter_standby(lcdev);
+
+ if (ret = 0)
+ lcd->state = power;
+ else
+ dev_warn(&lcdev->dev, "failed to set power mode %d\n", power);
+
+ return ret;
+}
+
+static int hx8357_get_power(struct lcd_device *lcdev)
+{
+ struct hx8357_data *lcd = lcd_get_data(lcdev);
+
+ return lcd->state;
+}
+
+static struct lcd_ops hx8357_ops = {
+ .set_power = hx8357_set_power,
+ .get_power = hx8357_get_power,
+};
+
+static int __devinit hx8357_probe(struct spi_device *spi)
+{
+ struct lcd_device *lcdev;
+ struct hx8357_data *lcd;
+ int i, ret;
+
+ lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
+ if (!lcd) {
+ dev_err(&spi->dev, "Couldn't allocate lcd internal structure!\n");
+ return -ENOMEM;
+ }
+
+ ret = spi_setup(spi);
+ if (ret < 0) {
+ dev_err(&spi->dev, "SPI setup failed.\n");
+ return ret;
+ }
+
+ lcd->spi = spi;
+
+ lcd->reset = of_get_named_gpio(spi->dev.of_node, "gpios-reset", 0);
+ if (!gpio_is_valid(lcd->reset)) {
+ dev_err(&spi->dev, "Missing dt property: gpios-reset\n");
+ return -EINVAL;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, lcd->reset,
+ GPIOF_OUT_INIT_HIGH,
+ "hx8357-reset");
+ if (ret) {
+ dev_err(&spi->dev,
+ "failed to request gpio %d: %d\n",
+ lcd->reset, ret);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < HX8357_NUM_IM_PINS; i++) {
+ lcd->im_pins[i] = of_get_named_gpio(spi->dev.of_node,
+ "im-gpios", i);
+ if (lcd->im_pins[i] = -EPROBE_DEFER) {
+ dev_info(&spi->dev, "GPIO requested is not here yet, deferring the probe\n");
+ return -EPROBE_DEFER;
+ }
+ if (!gpio_is_valid(lcd->im_pins[i])) {
+ dev_err(&spi->dev, "Missing dt property: im-gpios\n");
+ return -EINVAL;
+ }
+
+ ret = devm_gpio_request_one(&spi->dev, lcd->im_pins[i],
+ GPIOF_DIR_OUT, "im_pins");
+ if (ret) {
+ dev_err(&spi->dev, "failed to request gpio %d: %d\n",
+ lcd->im_pins[i], ret);
+ return -EINVAL;
+ }
+ }
+
+ lcdev = lcd_device_register("mxsfb", &spi->dev, lcd, &hx8357_ops);
+ if (IS_ERR(lcdev)) {
+ ret = PTR_ERR(lcdev);
+ return ret;
+ }
+ spi_set_drvdata(spi, lcdev);
+
+ ret = hx8357_lcd_init(lcdev);
+ if (ret) {
+ dev_err(&spi->dev, "Couldn't initialize panel\n");
+ goto init_error;
+ }
+
+ dev_info(&spi->dev, "Panel probed\n");
+
+ return 0;
+
+init_error:
+ lcd_device_unregister(lcdev);
+ return ret;
+}
+
+static int __devexit hx8357_remove(struct spi_device *spi)
+{
+ struct lcd_device *lcdev = spi_get_drvdata(spi);
+
+ lcd_device_unregister(lcdev);
+ return 0;
+}
+
+static const struct of_device_id hx8357_dt_ids[] = {
+ { .compatible = "himax,hx8357" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, hx8357_dt_ids);
+
+static struct spi_driver hx8357_driver = {
+ .probe = hx8357_probe,
+ .remove = __devexit_p(hx8357_remove),
+ .driver = {
+ .name = "hx8357",
+ .of_match_table = of_match_ptr(hx8357_dt_ids),
+ },
+};
+
+module_spi_driver(hx8357_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Himax HX-8357 LCD Driver");
+MODULE_LICENSE("GPL");
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 2/3] tegra: pwm-backlight: add tegra pwm-bl driver
From: Stephen Warren @ 2013-01-22 16:30 UTC (permalink / raw)
To: Alex Courbot
Cc: Thierry Reding,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Mark Zhang,
gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
In-Reply-To: <12033649.LY58cllSHv@percival>
On 01/21/2013 08:24 PM, Alex Courbot wrote:
> On Tuesday 22 January 2013 01:46:33 Stephen Warren wrote:
>>> arch/arm/boot/dts/tegra20-ventana.dts | 18 +++-
>>> arch/arm/configs/tegra_defconfig | 1 +
>>> drivers/video/backlight/Kconfig | 7 ++
>>> drivers/video/backlight/pwm_bl.c | 3 +
>>> drivers/video/backlight/pwm_bl_tegra.c | 159
>>> +static struct pwm_backlight_subdriver pwm_backlight_ventana_subdriver = {
>>> + .name = "pwm-backlight-ventana",
>>> + .init = init_ventana,
>>> + .exit = exit_ventana,
>>> + .notify = notify_ventana,
>>> + .notify_after = notify_after_ventana,
>>> +};
>>
>> It seems like all of that code should be completely generic.
>
> Sorry, I don't get your point here - could you elaborate?
Nothing there (i.e. in the body of any of those functions) seems
remotely specific to Ventana or even Ventana's panel; presumably it
would work for any built-in LCD panel?
^ permalink raw reply
* [PATCH v3 00/12] video: da8xx-fb: am335x DT support
From: Afzal Mohammed @ 2013-01-22 16:52 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
Hi,
This series adds DT support to da8xx-fb driver (device found on
DaVinci and AM335x SoC's). It does certain cleanup's in the process.
This series as compared to previous version handles configuration of
the LCDC clock rate by modelling as a clock divider of CCF. This would
take effect only if CCF is selected, if not, no change to existing
method.
This makes use of Steffen Trumtrar's v16 of display timing DT support.
Testing has been done on AM335x SoC based boards like AM335x EVM. It
has also been verified that display on DA850 EVM (non-DT boot) works
as earlier.
This series is based on v3.8-rc3,
and is dependent on,
1. Series v16 "of: add display helper" by,
Steffen Trumtrar <s.trumtrar@pengutronix.de>
2. Patch "da8xx: Allow use by am33xx based devices" by,
Pantelis Antoniou <panto@antoniou-consulting.com>
3. Series v3 "video: da8xx-fb: runtime timing configuration" by,
me (Afzal Mohammed <afzal@ti.com>)
To test this series on AM335x based boards,
1. Series v2 "ARM: dts: AM33XX: lcdc support" by,
me (Afzal Mohammed <afzal@ti.com>),
2. Series "HWMOD fixes for AM33xx PWM submodules and device tree nodes" by,
Philip, Avinash <avinashphilip@ti.com>
3. Series "clk: divider: prepare for minimum divider" by,
me (Afzal Mohammed <afzal@ti.com>),
4. Series "ARM: AM335x: LCDC platform support" by,
me (Afzal Mohammed <afzal@ti.com>),
would be needed.
All above dependencies along with those required for testing is available
@ git://gitorious.org/x0148406-public/linux-kernel.git tags/da8xx-fb-dt-v3
Regards
Afzal
v3: model CCF clock divider with parent propogation if CCF selected
v2: 2 new patches - one to configure clock rate properly (12/12)and
other to make io operations safe (1/12)
Afzal Mohammed (11):
video: da8xx-fb: make io operations safe
video: da8xx-fb: enable sync lost intr for v2 ip
video: da8xx-fb: use devres
video: da8xx-fb: ensure non-null cfg in pdata
video: da8xx-fb: reorganize panel detection
video: da8xx-fb: minimal dt support
video: da8xx-fb: invoke platform callback safely
video: da8xx-fb: obtain fb_videomode info from dt
video: da8xx-fb: ensure pdata only for non-dt
video: da8xx-fb: setup struct lcd_ctrl_config for dt
video: da8xx-fb: CCF clock divider handling
Manjunathappa, Prakash (1):
video: da8xx-fb: fix 24bpp raster configuration
.../devicetree/bindings/video/fb-da8xx.txt | 37 ++++
drivers/video/da8xx-fb.c | 217 ++++++++++++++++-----
2 files changed, 201 insertions(+), 53 deletions(-)
create mode 100644 Documentation/devicetree/bindings/video/fb-da8xx.txt
--
1.7.12
^ permalink raw reply
* [PATCH v3 02/12] video: da8xx-fb: fix 24bpp raster configuration
From: Afzal Mohammed @ 2013-01-22 16:52 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette,
Manjunathappa, Prakash
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
From: "Manjunathappa, Prakash" <prakash.pm@ti.com>
Set only LCD_V2_TFT_24BPP_MODE bit for 24bpp and LCD_V2_TFT_24BPP_UNPACK
bit along with LCD_V2_TFT_24BPP_MODE for 32bpp configuration.
Patch is tested on am335x-evm for 24bpp and da850-evm for 16bpp
configurations.
Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 35a33ca..7f92f37 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -550,10 +550,10 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
case 4:
case 16:
break;
- case 24:
- reg |= LCD_V2_TFT_24BPP_MODE;
case 32:
reg |= LCD_V2_TFT_24BPP_UNPACK;
+ case 24:
+ reg |= LCD_V2_TFT_24BPP_MODE;
break;
case 8:
--
1.7.12
^ permalink raw reply related
* [PATCH v3 06/12] video: da8xx-fb: reorganize panel detection
From: Afzal Mohammed @ 2013-01-22 16:52 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Move panel detection to a separate function, this helps in readability
as well as makes DT support cleaner.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 3b146bc..b6ea5e9 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1253,6 +1253,27 @@ static struct fb_ops da8xx_fb_ops = {
.fb_blank = cfb_blank,
};
+static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
+{
+ struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
+ struct fb_videomode *lcdc_info;
+ int i;
+
+ for (i = 0, lcdc_info = known_lcd_panels;
+ i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
+ if (strcmp(fb_pdata->type, lcdc_info->name) = 0)
+ break;
+ }
+
+ if (i = ARRAY_SIZE(known_lcd_panels)) {
+ dev_err(&dev->dev, "no panel found\n");
+ return NULL;
+ }
+ dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
+
+ return lcdc_info;
+}
+
static int fb_probe(struct platform_device *device)
{
struct da8xx_lcdc_platform_data *fb_pdata @@ -1262,7 +1283,7 @@ static int fb_probe(struct platform_device *device)
struct fb_info *da8xx_fb_info;
struct clk *fb_clk = NULL;
struct da8xx_fb_par *par;
- int ret, i;
+ int ret;
unsigned long ulcm;
if (fb_pdata = NULL) {
@@ -1270,6 +1291,10 @@ static int fb_probe(struct platform_device *device)
return -ENOENT;
}
+ lcdc_info = da8xx_fb_get_videomode(device);
+ if (lcdc_info = NULL)
+ return -ENODEV;
+
lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
if (!da8xx_fb_reg_base) {
@@ -1303,21 +1328,6 @@ static int fb_probe(struct platform_device *device)
break;
}
- for (i = 0, lcdc_info = known_lcd_panels;
- i < ARRAY_SIZE(known_lcd_panels);
- i++, lcdc_info++) {
- if (strcmp(fb_pdata->type, lcdc_info->name) = 0)
- break;
- }
-
- if (i = ARRAY_SIZE(known_lcd_panels)) {
- dev_err(&device->dev, "GLCD: No valid panel found\n");
- ret = -ENODEV;
- goto err_pm_runtime_disable;
- } else
- dev_info(&device->dev, "GLCD: Found %s panel\n",
- fb_pdata->type);
-
lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
if (!lcd_cfg) {
--
1.7.12
^ permalink raw reply related
* [PATCH v3 07/12] video: da8xx-fb: minimal dt support
From: Afzal Mohammed @ 2013-01-22 16:53 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Driver is provided a means to have the probe triggered by DT.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
Documentation/devicetree/bindings/video/fb-da8xx.txt | 16 ++++++++++++++++
drivers/video/da8xx-fb.c | 7 +++++++
2 files changed, 23 insertions(+)
create mode 100644 Documentation/devicetree/bindings/video/fb-da8xx.txt
diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
new file mode 100644
index 0000000..581e014
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
@@ -0,0 +1,16 @@
+TI LCD Controller on DA830/DA850/AM335x SoC's
+
+Required properties:
+- compatible:
+ DA830 - "ti,da830-lcdc"
+ AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
+- reg: Address range of lcdc register set
+- interrupts: lcdc interrupt
+
+Example:
+
+lcdc@4830e000 {
+ compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupts = <36>;
+};
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index b6ea5e9..08ee8eb 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1595,6 +1595,12 @@ static int fb_resume(struct platform_device *dev)
#define fb_resume NULL
#endif
+static const struct of_device_id da8xx_fb_of_match[] = {
+ {.compatible = "ti,da830-lcdc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, da8xx_fb_of_match);
+
static struct platform_driver da8xx_fb_driver = {
.probe = fb_probe,
.remove = fb_remove,
@@ -1603,6 +1609,7 @@ static struct platform_driver da8xx_fb_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(da8xx_fb_of_match),
},
};
--
1.7.12
^ permalink raw reply related
* [PATCH v3 11/12] video: da8xx-fb: setup struct lcd_ctrl_config for dt
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
strcut lcd_ctrl_config information required for driver is currently
obtained via platform data. To handle DT probing, create
lcd_ctrl_config and populate it with default values, these values are
sufficient for the panels so far used with this controller to work.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 1c1a616..5455682 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1254,6 +1254,35 @@ static struct fb_ops da8xx_fb_ops = {
.fb_blank = cfb_blank,
};
+static struct lcd_ctrl_config *da8xx_fb_create_cfg(struct platform_device *dev)
+{
+ struct lcd_ctrl_config *cfg;
+
+ cfg = devm_kzalloc(&dev->dev, sizeof(struct fb_videomode), GFP_KERNEL);
+ if (!cfg) {
+ dev_err(&dev->dev, "memory allocation failed\n");
+ return NULL;
+ }
+
+ /* default values */
+
+ if (lcd_revision = LCD_VERSION_1)
+ cfg->bpp = 16;
+ else
+ cfg->bpp = 32;
+
+ /*
+ * For panels so far used with this LCDC, below statement is sufficient.
+ * For new panels, if required, struct lcd_ctrl_cfg fields to be updated
+ * with additional/modified values. Those values would have to be then
+ * obtained from dt(requiring new dt bindings).
+ */
+
+ cfg->panel_shade = COLOR_ACTIVE;
+
+ return cfg;
+}
+
static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
{
struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
@@ -1345,7 +1374,10 @@ static int fb_probe(struct platform_device *device)
break;
}
- lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+ if (device->dev.of_node)
+ lcd_cfg = da8xx_fb_create_cfg(device);
+ else
+ lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
if (!lcd_cfg) {
ret = -EINVAL;
--
1.7.12
^ permalink raw reply related
* [PATCH v3 12/12] video: da8xx-fb: CCF clock divider handling
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Common clock framework provides a basic clock divider. Make use of it
to handle clock configuration in the LCDC IP, wherever applicable;
out of two platforms having this IP, only am335x is converted to use
CCF, DaVinci is not yet converted. Hence wrap the modification such
that it will come into effect only if CCF is selected, otherwise,
prgram dividers as earlier. Once DaVinci is converted to use CCF,
this ifdef'ery can be removed.
Divider clock instantiated is made as a one that allows the rate
propogation to it's parent, that provides more options w.r.t pixel
clock rates that could be configured.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
v3: model CCF clock divider with parent propogation if CCF selected
v2: new patch
drivers/video/da8xx-fb.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 5455682..3c9db1d 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/lcm.h>
+#include <linux/clk-provider.h>
#include <video/of_display_timing.h>
#include <video/da8xx-fb.h>
#include <asm/div64.h>
@@ -133,6 +134,10 @@
#define WSI_TIMEOUT 50
#define PALETTE_SIZE 256
+#define LCD_CLK_SHIFT 8
+#define LCD_CLK_WIDTH 8
+#define LCD_CLK_MIN_DIV 2
+
static void __iomem *da8xx_fb_reg_base;
static struct resource *lcdc_regs;
static unsigned int lcd_revision;
@@ -181,6 +186,9 @@ struct da8xx_fb_par {
u32 pseudo_palette[16];
struct fb_videomode mode;
struct lcd_ctrl_config cfg;
+#ifdef CONFIG_COMMON_CLK
+ struct clk *child_clk;
+#endif
};
static struct fb_var_screeninfo da8xx_fb_var;
@@ -689,6 +697,19 @@ static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
}
+#ifdef CONFIG_COMMON_CLK
+static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+ unsigned pixclock)
+{
+ unsigned long rate;
+
+ rate = PICOS2KHZ(pixclock) * 1000;
+ rate = clk_round_rate(par->child_clk, rate);
+ rate = KHZ2PICOS(rate / 1000);
+
+ return rate;
+}
+#else
static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
unsigned pixclock)
{
@@ -697,25 +718,49 @@ static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
div = da8xx_fb_calc_clk_divider(par, pixclock);
return KHZ2PICOS(par->lcd_fck_rate / (1000 * div));
}
+#endif
static inline void da8xx_fb_config_clk_divider(unsigned div)
{
/* Configure the LCD clock divisor. */
lcdc_write(LCD_CLK_DIVISOR(div) |
(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+}
+static inline void da8xx_fb_clkc_enable(void)
+{
if (lcd_revision = LCD_VERSION_2)
lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
}
-static inline void da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+#ifdef CONFIG_COMMON_CLK
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+ struct fb_videomode *mode)
+{
+ int ret;
+
+ ret = clk_set_rate(par->child_clk, PICOS2KHZ(mode->pixclock) * 1000);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(par->dev, "unable to setup pixel clock of %u ps",
+ mode->pixclock);
+ return ret;
+ }
+ da8xx_fb_clkc_enable();
+ return 0;
+}
+#else
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
struct fb_videomode *mode)
{
unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
da8xx_fb_config_clk_divider(div);
+ da8xx_fb_clkc_enable();
+
+ return 0;
}
+#endif
static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
struct fb_videomode *panel)
@@ -723,7 +768,9 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
u32 bpp;
int ret = 0;
- da8xx_fb_calc_config_clk_divider(par, panel);
+ ret = da8xx_fb_calc_config_clk_divider(par, panel);
+ if (IS_ERR_VALUE(ret))
+ return ret;
if (panel->sync & FB_SYNC_CLK_INVERT)
lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -1406,6 +1453,22 @@ static int fb_probe(struct platform_device *device)
da8xx_fb_lcd_reset();
+#ifdef CONFIG_COMMON_CLK
+ lcdc_write(LCD_RASTER_MODE | LCD_CLK_DIVISOR(0x2), LCD_CTRL_REG);
+ par->child_clk = clk_register_divider(NULL, "da8xx_fb_clk",
+ __clk_get_name(fb_clk),
+ CLK_SET_RATE_PARENT,
+ da8xx_fb_reg_base + LCD_CTRL_REG,
+ LCD_CLK_SHIFT, LCD_CLK_WIDTH,
+ LCD_CLK_MIN_DIV,
+ CLK_DIVIDER_ONE_BASED, NULL);
+ if (IS_ERR(par->child_clk)) {
+ dev_err(&device->dev, "error registering clk\n");
+ ret = -ENODEV;
+ goto err_release_fb;
+ }
+#endif
+
/* allocate frame buffer */
par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE);
--
1.7.12
^ permalink raw reply related
* [PATCH v3 10/12] video: da8xx-fb: ensure pdata only for non-dt
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
This driver is DT probe-able, hence ensure presence of platform data
only for non-DT boot.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 0c68712..1c1a616 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1303,7 +1303,7 @@ static int fb_probe(struct platform_device *device)
int ret;
unsigned long ulcm;
- if (fb_pdata = NULL) {
+ if (fb_pdata = NULL && !device->dev.of_node) {
dev_err(&device->dev, "Can not get platform data\n");
return -ENOENT;
}
--
1.7.12
^ permalink raw reply related
* [PATCH v3 09/12] video: da8xx-fb: obtain fb_videomode info from dt
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Obtain fb_videomode details for the connected lcd panel using the
display timing details present in DT.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
.../devicetree/bindings/video/fb-da8xx.txt | 21 +++++++++++++++++++++
drivers/video/da8xx-fb.c | 17 +++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
index 581e014..0741f78 100644
--- a/Documentation/devicetree/bindings/video/fb-da8xx.txt
+++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
@@ -6,6 +6,12 @@ Required properties:
AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
- reg: Address range of lcdc register set
- interrupts: lcdc interrupt
+- display-timings: typical videomode of lcd panel, represented as child.
+ Refer Documentation/devicetree/bindings/video/display-timing.txt for
+ display timing binding details. If multiple videomodes are mentioned
+ in display timings node, typical videomode has to be mentioned as the
+ native mode or it has to be first child (driver cares only for native
+ videomode).
Example:
@@ -13,4 +19,19 @@ lcdc@4830e000 {
compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
reg = <0x4830e000 0x1000>;
interrupts = <36>;
+ display-timings {
+ 800x480p62 {
+ clock-frequency = <30000000>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <39>;
+ hback-porch = <39>;
+ hsync-len = <47>;
+ vback-porch = <29>;
+ vfront-porch = <13>;
+ vsync-len = <2>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
};
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 0beed20..0c68712 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/lcm.h>
+#include <video/of_display_timing.h>
#include <video/da8xx-fb.h>
#include <asm/div64.h>
@@ -1257,8 +1258,24 @@ static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
{
struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
struct fb_videomode *lcdc_info;
+ struct device_node *np = dev->dev.of_node;
int i;
+ if (np) {
+ lcdc_info = devm_kzalloc(&dev->dev,
+ sizeof(struct fb_videomode),
+ GFP_KERNEL);
+ if (!lcdc_info) {
+ dev_err(&dev->dev, "memory allocation failed\n");
+ return NULL;
+ }
+ if (of_get_fb_videomode(np, lcdc_info, OF_USE_NATIVE_MODE)) {
+ dev_err(&dev->dev, "timings not available in DT\n");
+ return NULL;
+ }
+ return lcdc_info;
+ }
+
for (i = 0, lcdc_info = known_lcd_panels;
i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
if (strcmp(fb_pdata->type, lcdc_info->name) = 0)
--
1.7.12
^ permalink raw reply related
* [PATCH v3 08/12] video: da8xx-fb: invoke platform callback safely
From: Afzal Mohammed @ 2013-01-22 16:54 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Ensure that platform data is present before checking whether platform
callback is present (the one used to control backlight). So far this
was not an issue as driver was purely non-DT triggered, but now DT
support has been added.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 08ee8eb..0beed20 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1347,7 +1347,7 @@ static int fb_probe(struct platform_device *device)
par->dev = &device->dev;
par->lcdc_clk = fb_clk;
par->lcd_fck_rate = clk_get_rate(fb_clk);
- if (fb_pdata->panel_power_ctrl) {
+ if (fb_pdata && fb_pdata->panel_power_ctrl) {
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
par->panel_power_ctrl(1);
}
--
1.7.12
^ permalink raw reply related
* [PATCH v3 05/12] video: da8xx-fb: ensure non-null cfg in pdata
From: Afzal Mohammed @ 2013-01-22 16:55 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Ensure that platform data contains pointer for lcd_ctrl_config.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 7a32e83..3b146bc 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1320,6 +1320,11 @@ static int fb_probe(struct platform_device *device)
lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+ if (!lcd_cfg) {
+ ret = -EINVAL;
+ goto err_pm_runtime_disable;
+ }
+
da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
&device->dev);
if (!da8xx_fb_info) {
--
1.7.12
^ permalink raw reply related
* [PATCH v3 04/12] video: da8xx-fb: use devres
From: Afzal Mohammed @ 2013-01-22 16:55 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Replace existing resource handling in the driver with managed device
resource.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
drivers/video/da8xx-fb.c | 35 ++++++-----------------------------
1 file changed, 6 insertions(+), 29 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index ca69e01..7a32e83 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1036,12 +1036,9 @@ static int fb_remove(struct platform_device *dev)
par->p_palette_base);
dma_free_coherent(NULL, par->vram_size, par->vram_virt,
par->vram_phys);
- free_irq(par->irq, par);
pm_runtime_put_sync(&dev->dev);
pm_runtime_disable(&dev->dev);
framebuffer_release(info);
- iounmap(da8xx_fb_reg_base);
- release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
}
return 0;
@@ -1265,7 +1262,6 @@ static int fb_probe(struct platform_device *device)
struct fb_info *da8xx_fb_info;
struct clk *fb_clk = NULL;
struct da8xx_fb_par *par;
- resource_size_t len;
int ret, i;
unsigned long ulcm;
@@ -1275,29 +1271,16 @@ static int fb_probe(struct platform_device *device)
}
lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
- if (!lcdc_regs) {
- dev_err(&device->dev,
- "Can not get memory resource for LCD controller\n");
- return -ENOENT;
- }
-
- len = resource_size(lcdc_regs);
-
- lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);
- if (!lcdc_regs)
- return -EBUSY;
-
- da8xx_fb_reg_base = ioremap(lcdc_regs->start, len);
+ da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
if (!da8xx_fb_reg_base) {
- ret = -EBUSY;
- goto err_request_mem;
+ dev_err(&device->dev, "memory resource setup failed\n");
+ return -EADDRNOTAVAIL;
}
- fb_clk = clk_get(&device->dev, "fck");
+ fb_clk = devm_clk_get(&device->dev, "fck");
if (IS_ERR(fb_clk)) {
dev_err(&device->dev, "Can not get device clock\n");
- ret = -ENODEV;
- goto err_ioremap;
+ return -ENODEV;
}
pm_runtime_enable(&device->dev);
@@ -1458,7 +1441,7 @@ static int fb_probe(struct platform_device *device)
lcdc_irq_handler = lcdc_irq_handler_rev02;
}
- ret = request_irq(par->irq, lcdc_irq_handler, 0,
+ ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
DRIVER_NAME, par);
if (ret)
goto irq_freq;
@@ -1488,12 +1471,6 @@ err_pm_runtime_disable:
pm_runtime_put_sync(&device->dev);
pm_runtime_disable(&device->dev);
-err_ioremap:
- iounmap(da8xx_fb_reg_base);
-
-err_request_mem:
- release_mem_region(lcdc_regs->start, len);
-
return ret;
}
--
1.7.12
^ permalink raw reply related
* [PATCH v3 01/12] video: da8xx-fb: make io operations safe
From: Afzal Mohammed @ 2013-01-22 16:56 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-kernel
Cc: Florian Tobias Schandinat, Tomi Valkeinen, Grant Likely,
Rob Herring, Rob Landley, Steffen Trumtrar, Mike Turquette
In-Reply-To: <cover.1358871750.git.afzal@ti.com>
Replace __raw_readl/__raw_writel with readl/writel; this driver is
reused on ARMv7 (AM335x SoC).
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
v2: new patch
drivers/video/da8xx-fb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 720604c..35a33ca 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -141,12 +141,12 @@ static int frame_done_flag;
static inline unsigned int lcdc_read(unsigned int addr)
{
- return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
+ return (unsigned int)readl(da8xx_fb_reg_base + (addr));
}
static inline void lcdc_write(unsigned int val, unsigned int addr)
{
- __raw_writel(val, da8xx_fb_reg_base + (addr));
+ writel(val, da8xx_fb_reg_base + (addr));
}
struct da8xx_fb_par {
--
1.7.12
^ 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