* Re: [PATCH 04/04] sh: use ioread32/iowrite32 and mapped_reg for div6
From: Kuninori Morimoto @ 2011-12-09 5:49 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111208135922.18394.95163.sendpatchset@w520>
Hi Magnus, Paul
I tested these patch set on mackerel board with linus/master.
it works well.
But I'm afraid that this div6 patch didn't care
paul/common/clkfwk which has below commit.
it is still using clk->enable_reg.
Of course I can modify it after merge ;)
------------------------------------------------------
commit 56242a1fc595d158eddefbb4d6d76e82c2535f55
Author: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon Nov 21 21:33:18 2011 -0800
sh: clkfwk: setup clock parent from current register value
------------------------------------------------------
Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> From: Magnus Damm <damm@opensource.se>
>
> Convert the CPG DIV6 helper code to use the new mapped_reg
> together with ioread32() and iowrite32().
>
> Signed-off-by: Magnus Damm <damm@opensource.se>
> ---
>
> drivers/sh/clk/cpg.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> --- 0011/drivers/sh/clk/cpg.c
> +++ work/drivers/sh/clk/cpg.c 2011-12-08 22:19:00.000000000 +0900
> @@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(
> clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
> table, NULL);
>
> - idx = __raw_readl(clk->enable_reg) & 0x003f;
> + idx = ioread32(clk->mapped_reg) & 0x003f;
>
> return clk->freq_table[idx].frequency;
> }
> @@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct
> if (ret < 0)
> return ret;
>
> - value = __raw_readl(clk->enable_reg) &
> + value = ioread32(clk->mapped_reg) &
> ~(((1 << clk->src_width) - 1) << clk->src_shift);
>
> - __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
> + iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
>
> /* Rebuild the frequency table */
> clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
> @@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct c
> if (idx < 0)
> return idx;
>
> - value = __raw_readl(clk->enable_reg);
> + value = ioread32(clk->mapped_reg);
> value &= ~0x3f;
> value |= idx;
> - __raw_writel(value, clk->enable_reg);
> + iowrite32(value, clk->mapped_reg);
> return 0;
> }
>
> @@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk
>
> ret = sh_clk_div6_set_rate(clk, clk->rate);
> if (ret = 0) {
> - value = __raw_readl(clk->enable_reg);
> + value = ioread32(clk->mapped_reg);
> value &= ~0x100; /* clear stop bit to enable clock */
> - __raw_writel(value, clk->enable_reg);
> + iowrite32(value, clk->mapped_reg);
> }
> return ret;
> }
> @@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct c
> {
> unsigned long value;
>
> - value = __raw_readl(clk->enable_reg);
> + value = ioread32(clk->mapped_reg);
> value |= 0x100; /* stop clock */
> value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
> - __raw_writel(value, clk->enable_reg);
> + iowrite32(value, clk->mapped_reg);
> }
>
> static struct clk_ops sh_clk_div6_clk_ops = {
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: [PATCH] sh: fix cpuidle on sh7724, possibly others
From: Paul Mundt @ 2011-12-09 8:54 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <Pine.LNX.4.64.1112061704300.10715@axis700.grange>
On Wed, Dec 07, 2011 at 09:38:13AM +0100, Guennadi Liakhovetski wrote:
> cpuidle has been broken on sh7724 and, possibly, other SuperH SoCs since
>
> commit f533c3d340536198a4889a42a68d6c0d79a504e7
> Author: Paul Mundt <lethal@linux-sh.org>
> Date: Fri Oct 16 17:20:58 2009 +0900
>
> sh: Idle loop chainsawing for SMP-based light sleep.
>
> i.e., since 2.6.33-rc1. The reason is a missing local_irq_enable() on the
> path, actually entering a sleep mode. This patch adds the missing call.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> This fixes one of the problem with cpuidle on sh. When applied (suitably
> adjusted) directly after f533c3d340536198a4889a42a68d6c0d79a504e7, it does
> fix the problem. However, since that commit cpuidle has been broken (at
> least for my configuration) at least once more. This time bisection points
> out at
>
> commit 03625e7107cde46e2851557ec06426799e6ae7f2
> Author: Magnus Damm <damm@opensource.se>
> Date: Fri Oct 30 04:24:32 2009 +0000
>
> sh: Use RSMEM for sleep code on sh7724
>
> Still investigating.
>
> diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> index 1cc257c..e58640a 100644
> --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
> +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> @@ -48,6 +48,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
> */
> k = min_t(int, allowed_state, requested_state);
>
> + local_irq_enable();
> before = ktime_get();
> sh_mobile_call_standby(cpuidle_mode[k]);
> after = ktime_get();
Thanks for debugging this. This looks like a simple imbalance to me, but
the changeset you cite doesn't do any SR toggling that would account for
it, so that makes me suspect something else.
Looking at the code in question, perhaps this is the culprit?
---
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index a6f95ae..55b9024 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -136,7 +136,7 @@ static int sh_pm_enter(suspend_state_t state)
local_irq_disable();
set_bl_bit();
sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
- local_irq_disable();
+ local_irq_enable();
clear_bl_bit();
return 0;
}
^ permalink raw reply related
* Re: [PATCH 04/04] sh: use ioread32/iowrite32 and mapped_reg for div6
From: Paul Mundt @ 2011-12-09 8:56 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20111208135922.18394.95163.sendpatchset@w520>
On Thu, Dec 08, 2011 at 09:49:46PM -0800, Kuninori Morimoto wrote:
> I tested these patch set on mackerel board with linus/master.
> it works well.
>
> But I'm afraid that this div6 patch didn't care
> paul/common/clkfwk which has below commit.
> it is still using clk->enable_reg.
>
> Of course I can modify it after merge ;)
>
That's ok, it's trivial to fix, I'll just tidy it up by hand when
merging. I'll add your Tested-by.
^ permalink raw reply
* Re: [PATCH] sh: fix cpuidle on sh7724, possibly others
From: Guennadi Liakhovetski @ 2011-12-09 9:27 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <Pine.LNX.4.64.1112061704300.10715@axis700.grange>
Hi Paul
On Fri, 9 Dec 2011, Paul Mundt wrote:
> On Wed, Dec 07, 2011 at 09:38:13AM +0100, Guennadi Liakhovetski wrote:
> > cpuidle has been broken on sh7724 and, possibly, other SuperH SoCs since
> >
> > commit f533c3d340536198a4889a42a68d6c0d79a504e7
> > Author: Paul Mundt <lethal@linux-sh.org>
> > Date: Fri Oct 16 17:20:58 2009 +0900
> >
> > sh: Idle loop chainsawing for SMP-based light sleep.
> >
> > i.e., since 2.6.33-rc1. The reason is a missing local_irq_enable() on the
> > path, actually entering a sleep mode. This patch adds the missing call.
> >
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> >
> > This fixes one of the problem with cpuidle on sh. When applied (suitably
> > adjusted) directly after f533c3d340536198a4889a42a68d6c0d79a504e7, it does
> > fix the problem. However, since that commit cpuidle has been broken (at
> > least for my configuration) at least once more. This time bisection points
> > out at
> >
> > commit 03625e7107cde46e2851557ec06426799e6ae7f2
> > Author: Magnus Damm <damm@opensource.se>
> > Date: Fri Oct 30 04:24:32 2009 +0000
> >
> > sh: Use RSMEM for sleep code on sh7724
> >
> > Still investigating.
> >
> > diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> > index 1cc257c..e58640a 100644
> > --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
> > +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
> > @@ -48,6 +48,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
> > */
> > k = min_t(int, allowed_state, requested_state);
> >
> > + local_irq_enable();
> > before = ktime_get();
> > sh_mobile_call_standby(cpuidle_mode[k]);
> > after = ktime_get();
>
> Thanks for debugging this. This looks like a simple imbalance to me, but
> the changeset you cite doesn't do any SR toggling that would account for
> it, so that makes me suspect something else.
The commit, that I quoted, does add a local_irq_disable() in cpu_idle()
and a WARN_ON(irqs_disabled()) after the call to pm_idle(), so, it
expects, that inside pm_idle() interrupts are re-enabled. This is also
done in the two local implementations poll_idle() and default_idle(), but
not on the path, activated, once the cpuidle driver had been brought up.
After it has, it is only the cpuidle_idle_call() that gets executed, not
pm_idle(). And cpuidle_idle_call() ends up calling target_state->enter(),
which points at cpuidle_sleep_enter(), which locks up, if ktime_get() is
called with interrupts disabled. And it anyway has to return with
interrupts enebled. As for
> Looking at the code in question, perhaps this is the culprit?
>
> ---
>
> diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
> index a6f95ae..55b9024 100644
> --- a/arch/sh/kernel/cpu/shmobile/pm.c
> +++ b/arch/sh/kernel/cpu/shmobile/pm.c
> @@ -136,7 +136,7 @@ static int sh_pm_enter(suspend_state_t state)
> local_irq_disable();
> set_bl_bit();
> sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
> - local_irq_disable();
> + local_irq_enable();
> clear_bl_bit();
> return 0;
> }
I also was starring at this, failing to understand, but, I think, this is
a different bug altogether. I think, this .enter() method is for
suspending, not for cpuidle, or am I missing something?
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Product Order
From: "SIMKINS LTD" @ 2011-12-09 13:04 UTC (permalink / raw)
To: simkinsltd
Hello,
I am Manager of SIMKINS LTD. USA, My company is interested in the
purchase of your products.
Kindly send me an email with details of:
*Minimum Order Quantity
*Your delivery time
*Payment terms
*And your products warranty
I await to hear from you urgently
Mr Stefan Al Simkins.
Purchasing Manager.
SIMKINS LTD
___________________________________
NOCC, http://nocc.sourceforge.net
^ permalink raw reply
* [RFC][PATCH 0/4] PM / shmobile: Use PM QoS latency constraints in touchscreen driver
From: Rafael J. Wysocki @ 2011-12-09 23:42 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
Hi,
The following series of patches updates the SH7372 PM domain's so that
A4R doesn't need to be turned on during system sleep, drops the SH7372's
PM domains stay_on flag and makes the touchscreen add a PM QoS constraint
on its I2C controller to prevent the A4R domain containing it from being
turned off (due to power management) when the touchscreen is active.
Comments welcome!
Thanks,
Rafael
^ permalink raw reply
* [RFC][PATCH 1/4] PM / shmobile: Don't include SH7372's INTCS in syscore suspend/resume
From: Rafael J. Wysocki @ 2011-12-09 23:43 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Since the SH7372's INTCS in included into syscore suspend/resume,
which causes the chip to be accessed when PM domains have been
turned off during system suspend, the A4R domain containing the
INTCS has to stay on during system sleep, which is suboptimal
from the power consumption point of view.
For this reason, add a new INTC flag, skip_syscore_suspend, to mark
the INTCS for intc_suspend() and intc_resume(), so that they don't
touch it. This allows the A4R domain to be turned off during
system suspend and the INTCS state is resrored during system
resume by the A4R's "power on" code.
Suggested-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
arch/arm/mach-shmobile/intc-sh7372.c | 1 +
drivers/sh/intc/core.c | 8 ++++++++
drivers/sh/intc/internals.h | 1 +
include/linux/sh_intc.h | 1 +
4 files changed, 11 insertions(+)
Index: linux/include/linux/sh_intc.h
=================================--- linux.orig/include/linux/sh_intc.h
+++ linux/include/linux/sh_intc.h
@@ -95,6 +95,7 @@ struct intc_desc {
unsigned int num_resources;
intc_enum force_enable;
intc_enum force_disable;
+ bool skip_syscore_suspend;
struct intc_hw_desc hw;
};
Index: linux/arch/arm/mach-shmobile/intc-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/intc-sh7372.c
+++ linux/arch/arm/mach-shmobile/intc-sh7372.c
@@ -535,6 +535,7 @@ static struct resource intcs_resources[]
static struct intc_desc intcs_desc __initdata = {
.name = "sh7372-intcs",
.force_enable = ENABLED_INTCS,
+ .skip_syscore_suspend = true,
.resource = intcs_resources,
.num_resources = ARRAY_SIZE(intcs_resources),
.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
Index: linux/drivers/sh/intc/core.c
=================================--- linux.orig/drivers/sh/intc/core.c
+++ linux/drivers/sh/intc/core.c
@@ -354,6 +354,8 @@ int __init register_intc_controller(stru
if (desc->force_enable)
intc_enable_disable_enum(desc, d, desc->force_enable, 1);
+ d->skip_suspend = desc->skip_syscore_suspend;
+
nr_intc_controllers++;
return 0;
@@ -386,6 +388,9 @@ static int intc_suspend(void)
list_for_each_entry(d, &intc_list, list) {
int irq;
+ if (d->skip_suspend)
+ continue;
+
/* enable wakeup irqs belonging to this intc controller */
for_each_active_irq(irq) {
struct irq_data *data;
@@ -409,6 +414,9 @@ static void intc_resume(void)
list_for_each_entry(d, &intc_list, list) {
int irq;
+ if (d->skip_suspend)
+ continue;
+
for_each_active_irq(irq) {
struct irq_data *data;
struct irq_chip *chip;
Index: linux/drivers/sh/intc/internals.h
=================================--- linux.orig/drivers/sh/intc/internals.h
+++ linux/drivers/sh/intc/internals.h
@@ -67,6 +67,7 @@ struct intc_desc_int {
struct intc_window *window;
unsigned int nr_windows;
struct irq_chip chip;
+ bool skip_suspend;
};
^ permalink raw reply
* [RFC][PATCH 2/4] PM / shmobile: Remove the stay_on flag from SH7372's PM domains
From: Rafael J. Wysocki @ 2011-12-09 23:44 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
SH7372 uses two independent mechanisms for ensuring that power
domains will never be turned off: the stay_on flag and the "always
on" domain governor. Moreover, the "always on" governor is only taken
into accout by runtime PM code paths, while the stay_on flag affects
all attempts to turn the given domain off. Thus setting the stay_on
flag causes the "always on" governor to be unnecessary, which is
quite confusing.
However, the stay_on flag is currently only set for the A3SP PM
domain and only if console_suspend_enabled, so it may be replaced
by checking console_suspend_enabled directly in the A3SP's
.suspend() routine. [This requires domain .suspend() to return
a result, but that is a minor modification.]
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
arch/arm/mach-shmobile/include/mach/sh7372.h | 3 --
arch/arm/mach-shmobile/pm-sh7372.c | 36 ++++++++++++---------------
2 files changed, 18 insertions(+), 21 deletions(-)
Index: linux/arch/arm/mach-shmobile/include/mach/sh7372.h
=================================--- linux.orig/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ linux/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -480,11 +480,10 @@ struct platform_device;
struct sh7372_pm_domain {
struct generic_pm_domain genpd;
struct dev_power_governor *gov;
- void (*suspend)(void);
+ int (*suspend)(void);
void (*resume)(void);
unsigned int bit_shift;
bool no_debug;
- bool stay_on;
};
static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d)
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -82,11 +82,12 @@ static int pd_power_down(struct generic_
struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
unsigned int mask = 1 << sh7372_pd->bit_shift;
- if (sh7372_pd->suspend)
- sh7372_pd->suspend();
+ if (sh7372_pd->suspend) {
+ int ret = sh7372_pd->suspend();
- if (sh7372_pd->stay_on)
- return 0;
+ if (ret)
+ return ret;
+ }
if (__raw_readl(PSTR) & mask) {
unsigned int retry_count;
@@ -113,9 +114,6 @@ static int __pd_power_up(struct sh7372_p
unsigned int retry_count;
int ret = 0;
- if (sh7372_pd->stay_on)
- goto out;
-
if (__raw_readl(PSTR) & mask)
goto out;
@@ -148,10 +146,11 @@ static int pd_power_up(struct generic_pm
return __pd_power_up(to_sh7372_pd(genpd), true);
}
-static void sh7372_a4r_suspend(void)
+static int sh7372_a4r_suspend(void)
{
sh7372_intcs_suspend();
__raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
+ return 0;
}
static bool pd_active_wakeup(struct device *dev)
@@ -243,7 +242,6 @@ struct sh7372_pm_domain sh7372_a4r = {
.gov = &pm_domain_always_on_gov,
.suspend = sh7372_a4r_suspend,
.resume = sh7372_intcs_resume,
- .stay_on = true,
};
struct sh7372_pm_domain sh7372_a3rv = {
@@ -256,21 +254,23 @@ struct sh7372_pm_domain sh7372_a3ri = {
.bit_shift = 8,
};
+static int sh7372_a3sp_suspend(void)
+{
+ /*
+ * Serial consoles make use of SCIF hardware located in A3SP,
+ * keep such power domain on if "no_console_suspend" is set.
+ */
+ return console_suspend_enabled ? -EBUSY : 0;
+}
+
struct sh7372_pm_domain sh7372_a3sp = {
.genpd.name = "A3SP",
.bit_shift = 11,
.gov = &pm_domain_always_on_gov,
.no_debug = true,
+ .suspend = sh7372_a3sp_suspend,
};
-static void sh7372_a3sp_init(void)
-{
- /* serial consoles make use of SCIF hardware located in A3SP,
- * keep such power domain on if "no_console_suspend" is set.
- */
- sh7372_a3sp.stay_on = !console_suspend_enabled;
-}
-
struct sh7372_pm_domain sh7372_a3sg = {
.genpd.name = "A3SG",
.bit_shift = 13,
@@ -514,8 +514,6 @@ void __init sh7372_pm_init(void)
/* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
__raw_writel(0, PDNSEL);
- sh7372_a3sp_init();
-
sh7372_suspend_init();
sh7372_cpuidle_init();
}
^ permalink raw reply
* [RFC][PATCH 3/4] PM / QoS: Introduce dev_pm_qos_add_ancestor_request()
From: Rafael J. Wysocki @ 2011-12-09 23:45 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Some devices, like the I2C controller on SH7372, are not
necessary for providing power to their children or forwarding
wakeup signals (and generally interrupts) from them. They are
only needed by their children when there's some data to transfer,
so they may be suspended for the majority of time and resumed
on demand, when the children have data to send or receive. For this
purpose, however, their power.ignore_children flags have to be set,
or the PM core wouldn't allow them to be suspended while their
children were active.
Unfortunately, in some situations it may take too much time to
resume such devices so that they can assist their children in
transferring data. For example, if such a device belongs to a PM
domain which goes to the "power off" state when that device is
suspended, it may take too much time to restore power to the
domain in response to the request from one of the device's
children. In that case, if the parent's resume time is critical,
the domain should stay in the "power on" state, although it still may
be desirable to power manage the parent itself (e.g. by manipulating
its clock).
In general, device PM QoS may be used to address this problem.
Namely, if the device's children added PM QoS latency constraints
for it, they would be able to prevent it from being put into an
overly deep low-power state. However, in some cases the devices
needing to be serviced are not the immediate children of a
"children-ignoring" device, but its grandchildren or even less
direct descendants. In those cases, the entity wanting to add a
PM QoS request for a given device's ancestor that ignores its
children will have to find it in the first place, so introduce a new
helper function that may be used to achieve that. This function,
dev_pm_qos_add_ancestor_request(), will search for the first
ancestor of the given device whose power.ignore_children flag is
set and will add a device PM QoS latency request for that ancestor
on behalf of the caller. The request added this way may be removed
with the help of dev_pm_qos_remove_request() in the future, like
any other device PM QoS latency request.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/base/power/qos.c | 25 +++++++++++++++++++++++++
include/linux/pm_qos.h | 5 +++++
2 files changed, 30 insertions(+)
Index: linux/drivers/base/power/qos.c
=================================--- linux.orig/drivers/base/power/qos.c
+++ linux/drivers/base/power/qos.c
@@ -420,3 +420,28 @@ int dev_pm_qos_remove_global_notifier(st
return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier);
}
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier);
+
+/**
+ * dev_pm_qos_add_ancestor_request - Add PM QoS request for device's ancestor.
+ * @dev: Device whose ancestor to add the request for.
+ * @req: Pointer to the preallocated handle.
+ * @value: Constraint latency value.
+ */
+int dev_pm_qos_add_ancestor_request(struct device *dev,
+ struct dev_pm_qos_request *req, s32 value)
+{
+ struct device *ancestor = dev->parent;
+ int error = -ENODEV;
+
+ while (ancestor && !ancestor->power.ignore_children)
+ ancestor = ancestor->parent;
+
+ if (ancestor)
+ error = dev_pm_qos_add_request(ancestor, req, value);
+
+ if (error)
+ req->dev = NULL;
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
Index: linux/include/linux/pm_qos.h
=================================--- linux.orig/include/linux/pm_qos.h
+++ linux/include/linux/pm_qos.h
@@ -92,6 +92,8 @@ int dev_pm_qos_add_global_notifier(struc
int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier);
void dev_pm_qos_constraints_init(struct device *dev);
void dev_pm_qos_constraints_destroy(struct device *dev);
+int dev_pm_qos_add_ancestor_request(struct device *dev,
+ struct dev_pm_qos_request *req, s32 value);
#else
static inline int pm_qos_update_target(struct pm_qos_constraints *c,
struct plist_node *node,
@@ -153,6 +155,9 @@ static inline void dev_pm_qos_constraint
{
dev->power.power_state = PMSG_INVALID;
}
+int dev_pm_qos_add_ancestor_request(struct device *dev,
+ struct dev_pm_qos_request *req, s32 value)
+ { return 0; }
#endif
#endif
^ permalink raw reply
* [RFC][PATCH 4/4] PM / input / touchscreen: Make st1232 use device PM QoS constraints
From: Rafael J. Wysocki @ 2011-12-09 23:46 UTC (permalink / raw)
To: Linux-sh list; +Cc: Linux PM list, Guennadi Liakhovetski, Magnus Damm, LKML
In-Reply-To: <201112100042.45168.rjw@sisk.pl>
From: Rafael J. Wysocki <rjw@sisk.pl>
Make the st1232 driver use dev_pm_qos_add_ancestor_request() to
add a device PM QoS latency constraint for the I2C controller it
depends on, so that the controller won't go into an overly deep
low-power state when the touchscreen has to be particularly
responsive (e.g. when the user moves his or her finger on it)
and allow the A4R domain to be turned off if that doesn't violate
the PM QoS latency constraints.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
arch/arm/mach-shmobile/pm-sh7372.c | 28 +++++++++++++++++++++++++++-
drivers/input/touchscreen/st1232.c | 14 +++++++++++++-
2 files changed, 40 insertions(+), 2 deletions(-)
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
=================================--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -239,7 +239,6 @@ struct sh7372_pm_domain sh7372_d4 = {
struct sh7372_pm_domain sh7372_a4r = {
.genpd.name = "A4R",
.bit_shift = 5,
- .gov = &pm_domain_always_on_gov,
.suspend = sh7372_a4r_suspend,
.resume = sh7372_intcs_resume,
};
@@ -496,9 +495,36 @@ static int sh7372_enter_suspend(suspend_
return 0;
}
+/**
+ * sh7372_pm_notifier_fn - SH7372 PM notifier routine.
+ * @notifier: Unused.
+ * @pm_event: Event being handled.
+ * @unused: Unused.
+ *
+ * This is necessary, because the A4R domain has to be "on" when
+ * suspend_device_irqs() and resume_device_irqs() are executed during system
+ * suspend and resume, respectively, so that those functions don't crash
+ * while accessing the INTCS.
+ */
+static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
+ unsigned long pm_event, void *unused)
+{
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ pm_genpd_poweron(&sh7372_a4r.genpd);
+ break;
+ case PM_POST_SUSPEND:
+ pm_genpd_poweroff_unused();
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static void sh7372_suspend_init(void)
{
shmobile_suspend_ops.enter = sh7372_enter_suspend;
+ pm_notifier(sh7372_pm_notifier_fn, 0);
}
#else
static void sh7372_suspend_init(void) {}
Index: linux/drivers/input/touchscreen/st1232.c
=================================--- linux.orig/drivers/input/touchscreen/st1232.c
+++ linux/drivers/input/touchscreen/st1232.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/pm_qos.h>
#define ST1232_TS_NAME "st1232-ts"
@@ -46,6 +47,8 @@ struct st1232_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct st1232_ts_finger finger[MAX_FINGERS];
+ struct dev_pm_qos_request low_latency_req;
+ bool pen_down;
};
static int st1232_ts_read_data(struct st1232_ts_data *ts)
@@ -118,8 +121,17 @@ static irqreturn_t st1232_ts_irq_handler
}
/* SYN_MT_REPORT only if no contact */
- if (!count)
+ if (!count) {
input_mt_sync(input_dev);
+ if (ts->pen_down) {
+ dev_pm_qos_remove_request(&ts->low_latency_req);
+ ts->pen_down = false;
+ }
+ } else if (!ts->pen_down) {
+ /* First contact, request 100 mcs latency. */
+ dev_pm_qos_add_ancestor_request(&ts->client->dev,
+ &ts->low_latency_req, 100);
+ }
/* SYN_REPORT */
input_sync(input_dev);
^ permalink raw reply
* [PATCH] sh: clkfwk: sh_clk_init_parent() should be called after clk_register()
From: Kuninori Morimoto @ 2011-12-12 3:02 UTC (permalink / raw)
To: linux-sh
sh_clk_init_parent() are using clk->mapped_reg
which is mapped in clk_register()
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
This is for latest paul/common/clkfwk
drivers/sh/clk/cpg.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index a0d8faa..45fee36 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -222,11 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
clkp->ops = ops;
clkp->freq_table = freq_table + (k * freq_table_size);
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
- ret = sh_clk_init_parent(clkp);
+ ret = clk_register(clkp);
if (ret < 0)
break;
- ret = clk_register(clkp);
+ ret = sh_clk_init_parent(clkp);
}
return ret;
--
1.7.5.4
^ permalink raw reply related
* [NEXT] mach-shmobile and sh compilation broken
From: Guennadi Liakhovetski @ 2011-12-12 8:18 UTC (permalink / raw)
To: linux-sh
Hi all
Current next fails to compile for mach-shmobile:
arch/arm/include/asm/pgtable.h:47: warning: #warning "SH-Mobile's consistent DMA size conflicts with VMALLOC_END by 144MB"
In file included from /opt/src/linux-2.6/arch/arm/kernel/process.c:64:
arch/arm/mach-shmobile/include/mach/system.h:9: error: #error Fix me up
make[2]: *** [arch/arm/kernel/process.o] Error 1
(the first line is an unrelated warning, it's actually repeated multiple
times throughout compilation), and arch/sh:
mm/pgtable-generic.c: In function 'pmdp_clear_flush_young':
mm/pgtable-generic.c:76: error: call to '__build_bug_failed' declared with attribute error: BUILD_BUG failed
make[2]: *** [mm/pgtable-generic.o] Error 1
The latter has been there since a few days already, possibly longer than
a week.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Re: [PATCH (sh-2.6)] sh: do not export syscalls that are actually
From: Carmelo AMOROSO @ 2011-12-12 10:58 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1322685809-15587-1-git-send-email-carmelo.amoroso@st.com>
On 30/11/2011 21.56, Mike Frysinger wrote:
> On Wednesday 30 November 2011 15:43:29 Carmelo AMOROSO wrote:
>> Avoid user space to erroneously assume that a syscall is
>> implemented by picking __NR_xxx from kernel headers that are
>> actually mapped to sys_ni_syscall.
>
> Acked-by: Mike Frysinger <vapier@gentoo.org> -mike
Paul,
anu chance to include it ? to avoid any doubts, patch was done against
HEAD, the subject sh-2.6 was due to a old git setting.
cheers,
carmelo
^ permalink raw reply
* Xmas Lening Aanbieding
From: Joseph Evans @ 2011-12-12 13:12 UTC (permalink / raw)
Wir sind auf dem XAMS Kredit Angebot mit so viel Bonus, bitte
kontaktieren Sie mich, wenn Sie tun müssen, jede Form von Darlehen von
unserer Firma.
Grüße
We are on our xams loan special offer with so much bonus, please do
contact me if you do need any form of loan from our firm.
Regards
^ permalink raw reply
* Re: [RFC][PATCH 4/4] PM / input / touchscreen: Make st1232 use device
From: Guennadi Liakhovetski @ 2011-12-12 14:34 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: Linux-sh list, Linux PM list, Magnus Damm, LKML
In-Reply-To: <201112100046.32206.rjw@sisk.pl>
Hi Rafael
On Sat, 10 Dec 2011, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
>
> Make the st1232 driver use dev_pm_qos_add_ancestor_request() to
> add a device PM QoS latency constraint for the I2C controller it
> depends on, so that the controller won't go into an overly deep
> low-power state when the touchscreen has to be particularly
> responsive (e.g. when the user moves his or her finger on it)
> and allow the A4R domain to be turned off if that doesn't violate
> the PM QoS latency constraints.
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
> arch/arm/mach-shmobile/pm-sh7372.c | 28 +++++++++++++++++++++++++++-
> drivers/input/touchscreen/st1232.c | 14 +++++++++++++-
I don't think you wanted to put these two files in one patch.
> 2 files changed, 40 insertions(+), 2 deletions(-)
>
> Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
> =================================> --- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
> +++ linux/arch/arm/mach-shmobile/pm-sh7372.c
[snip]
> Index: linux/drivers/input/touchscreen/st1232.c
> =================================> --- linux.orig/drivers/input/touchscreen/st1232.c
> +++ linux/drivers/input/touchscreen/st1232.c
After you have separated this file, you might as well notice, that it is
almost identical to my version, that we discussed privately previously.
Your changes include:
> @@ -25,6 +25,7 @@
> #include <linux/module.h>
> #include <linux/slab.h>
> #include <linux/types.h>
> +#include <linux/pm_qos.h>
in my version I preserved the alphabetic order of include files, you break
it
>
> #define ST1232_TS_NAME "st1232-ts"
>
> @@ -46,6 +47,8 @@ struct st1232_ts_data {
> struct i2c_client *client;
> struct input_dev *input_dev;
> struct st1232_ts_finger finger[MAX_FINGERS];
> + struct dev_pm_qos_request low_latency_req;
> + bool pen_down;
> };
>
> static int st1232_ts_read_data(struct st1232_ts_data *ts)
> @@ -118,8 +121,17 @@ static irqreturn_t st1232_ts_irq_handler
> }
>
> /* SYN_MT_REPORT only if no contact */
> - if (!count)
> + if (!count) {
> input_mt_sync(input_dev);
> + if (ts->pen_down) {
> + dev_pm_qos_remove_request(&ts->low_latency_req);
> + ts->pen_down = false;
> + }
> + } else if (!ts->pen_down) {
> + /* First contact, request 100 mcs latency. */
> + dev_pm_qos_add_ancestor_request(&ts->client->dev,
> + &ts->low_latency_req, 100);
in my version I also was actually setting pen_down to true, which you seem
to have dropped, so, your version just wouldn't work. Of course, I wasn't
using the "ancestor" version of the above call, because it didn't exist
back then.
You also removed my debugging, which is, of course, correct - thanks for
doing that.
Given the above, I would appreciate it, if you split this patch into two
and make the st1232 part of it
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
after which you can add your
[rjw@sisk.pl: use dev_pm_qos_add_ancestor_request() to reach the correct ancestor]
and your Sob.
Thanks
Guennadi
> + }
>
> /* SYN_REPORT */
> input_sync(input_dev);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* [PATCH/RFC] mmc: add a device PM QoS constraint when a host is first
From: Guennadi Liakhovetski @ 2011-12-12 15:46 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-pm, Chris Ball, linux-sh, Rafael J. Wysocki
Some MMC hosts implement a fine-grained runtime PM, whereby they
runtime-suspend and -resume the host interface on each transfer. This can
negatively affect performance, if the user was trying to transfer data
blocks back-to-back. This patch adds a PM QoS constraint to avoid such a
throughput reduction. This constraint prevents runtime-suspending the
device, if the expected wakeup latency is larger than 100us.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
This patch has been tested on SuperH and ARM sh-mobile hosts with
sh_mobile_sdhi and sh_mmcif drivers. Would be good to also have it tested
on other platforms, enabling PM QoS, e.g., those, using the simple QoS
PM domain governor.
drivers/mmc/core/core.c | 16 +++++++++++++++-
include/linux/mmc/host.h | 2 ++
2 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index b27b940..40f666f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -22,6 +22,7 @@
#include <linux/scatterlist.h>
#include <linux/log2.h>
#include <linux/regulator/consumer.h>
+#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
@@ -589,8 +590,16 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
wake_up(&host->wq);
spin_unlock_irqrestore(&host->lock, flags);
remove_wait_queue(&host->wq, &wait);
- if (!stop)
+ if (!stop) {
+ if (host->claim_cnt = 1) {
+ int ret = dev_pm_qos_add_request(host->parent,
+ &host->pm_qos, 100);
+ if (ret < 0)
+ dev_err(host->parent,
+ "PM QoS request failed: %d\n", ret);
+ }
mmc_host_enable(host);
+ }
return stop;
}
@@ -615,6 +624,10 @@ int mmc_try_claim_host(struct mmc_host *host)
claimed_host = 1;
}
spin_unlock_irqrestore(&host->lock, flags);
+
+ if (claimed_host && host->claim_cnt = 1)
+ dev_pm_qos_add_request(host->parent, &host->pm_qos, 100);
+
return claimed_host;
}
EXPORT_SYMBOL(mmc_try_claim_host);
@@ -639,6 +652,7 @@ void mmc_do_release_host(struct mmc_host *host)
host->claimer = NULL;
spin_unlock_irqrestore(&host->lock, flags);
wake_up(&host->wq);
+ dev_pm_qos_remove_request(&host->pm_qos);
}
}
EXPORT_SYMBOL(mmc_do_release_host);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1d09562..3e9d2f3 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -11,6 +11,7 @@
#define LINUX_MMC_HOST_H
#include <linux/leds.h>
+#include <linux/pm_qos.h>
#include <linux/sched.h>
#include <linux/mmc/core.h>
@@ -175,6 +176,7 @@ struct mmc_host {
u32 ocr_avail_sd; /* SD-specific OCR */
u32 ocr_avail_mmc; /* MMC-specific OCR */
struct notifier_block pm_notify;
+ struct dev_pm_qos_request pm_qos;
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
--
1.7.2.5
^ permalink raw reply related
* Re: [PATCH] sh: clkfwk: sh_clk_init_parent() should be called after clk_register()
From: Paul Mundt @ 2011-12-13 2:21 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <877h22h4r5.wl%kuninori.morimoto.gx@renesas.com>
On Sun, Dec 11, 2011 at 07:02:09PM -0800, Kuninori Morimoto wrote:
> sh_clk_init_parent() are using clk->mapped_reg
> which is mapped in clk_register()
>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH (sh-2.6)] sh: do not export syscalls that are actually not implemented
From: Paul Mundt @ 2011-12-13 2:22 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1322685809-15587-1-git-send-email-carmelo.amoroso@st.com>
On Mon, Dec 12, 2011 at 11:58:39AM +0100, Carmelo AMOROSO wrote:
> On 30/11/2011 21.56, Mike Frysinger wrote:
> > On Wednesday 30 November 2011 15:43:29 Carmelo AMOROSO wrote:
> >> Avoid user space to erroneously assume that a syscall is
> >> implemented by picking __NR_xxx from kernel headers that are
> >> actually mapped to sys_ni_syscall.
> >
> > Acked-by: Mike Frysinger <vapier@gentoo.org> -mike
>
> Paul,
> anu chance to include it ? to avoid any doubts, patch was done against
> HEAD, the subject sh-2.6 was due to a old git setting.
>
It's on my review list, just haven't had a chance to go through it yet.
^ permalink raw reply
* [PATCH] ARM: mach-shmobile: fix AP4EVB A3SP domain PM
From: Guennadi Liakhovetski @ 2011-12-13 11:09 UTC (permalink / raw)
To: linux-sh
On SH7372 it is important to stop MSTP clock of all registered USB host
devices. Otherwise powering down the A3SP domain will become impossible:
the domain-specific bit in SPDCR will remain set. Subsequently, any attempt
to power down any further domains will fail in the same way. To fix this
problem the USB1 host device has to be added to the A3SP domain on AP4EVB,
similarly as it is done on mackerel.
While not that critical, this patch also adds the HDMI device to the A4LC
domain.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/arm/mach-shmobile/board-ap4evb.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 7e90d06..15a210a 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1412,6 +1412,8 @@ static void __init ap4evb_init(void)
sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device);
sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device);
+ sh7372_add_device_to_domain(&sh7372_a3sp, &usb1_host_device);
+ sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_device);
sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device);
hdmi_init_pm_clock();
--
1.7.2.5
^ permalink raw reply related
* [PATCH 00/57] SH Mobile LCDC: rework DSI/HDMI interface and add overlays support
From: Laurent Pinchart @ 2011-12-13 14:01 UTC (permalink / raw)
To: linux-fbdev
Hi everybody,
First of all, sorry for the patch bomb. I usually try to send smaller patch
sets by splitting them into coherent subsets, but getting the code in a proper
shape took time and required several iterations of the whole set.
These patches can be divided in 4 groups.
- Patches 01 to 29 rework the interface between the LCDC and MIPI/DSI and HDMI
drivers. The MIPI/DSI and HDMI drivers are now FB-agnostic, except for the
usage of the fb_videomode structure used to pass video mode information to
the LCDC driver.
- Patches 30 to 38 perform additional cleanup to the LCDC driver made possible
by the previous patches.
- Patches 39 to 54 rework the MERAM driver to allocate ICBs and MERAM regions
automatically instead of relying on manually allocated regions specified in
platform data. They're a first step in the longer term goal of making MERAM
usable for other purpose than LCDC cache.
- Patches 55 to 57 add overlays support to the LCDC driver. They should be
considered as a prototype implementation for now. I plan to rework them, but
early feedback is always appreciated.
I would like to push patches 01 to 54 (after review of course) to v3.4 (or
v3.3 if time and review permits).
Laurent Pinchart (57):
fbdev: sh_mobile_lcdc: Reorder code into sections
fbdev: sh_mobile_lcdc: Mark init-only symbols with __devinit(const)
fbdev: sh_mobile_lcdc: Move pm runtime enable to probe()
fbdev: sh_mobile_lcdc: Don't pass struct device around
fbdev: sh_mobile_lcdc: Create functions to turn the display on/off
fbdev: sh_mobile_hdmi: Don't access LCDC channel in notifier callback
sh_mobile_hdmi: Remove platform data lcd_dev field
fbdev: sh_mobile_lcdc: Add sh_mobile_lcdc_entity definition
fbdev: sh_mobile_hdmi: Implement sh_mobile_lcdc_entity interface
fbdev: sh_mipi_dsi: Implement sh_mobile_lcdc_entity interface
fbdev: sh_mobile_lcdc: Handle HDMI/MIPI transmitter device directly
arm: mach-shmobile: Add LCDC tx_dev field to platform data
fbdev: sh_mipi_dsi: Don't hook up into board_cfg display operations
fbdev: sh_mobile_hdmi: Don't hook up into board_cfg display
operations
arm: mach-shmobile: Don't initialize the hdmi_info lcd_chan field
fbdev: sh_mobile_hdmi: Remove sh_mobile_hdmi_info lcd_chan field
fbdev: sh_mobile_lcdc: Remove board configuration owner field
fbdev: sh_mobile_lcdc: Remove board configuration board_data field
fbdev: sh_mobile_lcdc: Move brightness ops to sh_mobile_lcdc_bl_info
fbdev: sh_mobile_lcdc: Merge board_cfg and lcd_size_cfg into
panel_cfg
sh_mobile_lcdc: Add an lcdc channel pointer to sh_mobile_lcdc_entity
sh_mobile_hdmi: Use sh_mobile_lcdc_entity::channel to access fb_info
fbdev: sh_mobile_lcdc: Remove fb_info parameter to display_on
operation
fbdev: sh_mobile_lcdc: Return display connection state in display_on
sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan
sh_mobile_hdmi: Use LCDC notification callback
fbdev: sh_mobile_lcdc: Pass a video mode to the notify callback
fbdev: sh_mobile_hdmi: Don't set sh_hdmi::mode in the display on
handler
fbdev: sh_mobile_hdmi: Don't access LCDC fb_info
fbdev: sh_mobile_lcdc: Store display mode in a struct fb_videomode
fbdev: sh_mobile_lcdc: Rename (lcd|num)_cfg (lcd|num)_modes
fbdev: sh_mobile_lcdc: Reorganize the sh_mobile_lcdc_chan structure
fbdev: sh_mobile_lcdc: Add sh_mobile_format_info() function
fbdev: sh_mobile_lcdc: Store the format in struct sh_mobile_lcdc_chan
fbdev: sh_mobile_lcdc: Split fb init/cleanup from channel
init/cleanup
fbdev: sh_mobile_lcdc: Pass physical device pointer to DMA functions
fbdev: sh_mobile_lcdc: Store configuration in channel structure
fbdev: sh_mobile_lcdc: Pass channel pointer to
sh_mobile_wait_for_vsync
arm: mach-shmobile: Split MERAM resources into regs and meram
fbdev: sh_mobile_meram: Request memory regions for memory resources
fbdev: sh_mobile_meram: Add _cfg suffix to struct sh_mobile_meram_icb
fbdev: sh_mobile_meram: Make variables unsigned where applicable
fbdev: sh_mobile_meram: Make current_reg field store the current reg
set
fbdev: sh_mobile_meram: Add struct sh_mobile_meram_icb
fbdev: sh_mobile_meram: Don't inline everything
fbdev: sh_mobile_meram: Divide the code into sections
fbdev: sh_mobile_meram: Use genalloc to manage MERAM allocation
fbdev: sh_mobile_meram: Allocate ICBs automatically
arm: mach-shmobile: Don't set MERAM ICB numbers in platform data
fbdev: sh_mobile_meram: Remove unused sh_mobile_meram_icb_cfg fields
fbdev: sh_mobile_lcdc: Don't store copy of platform data
arm: mach-shmobile: Constify sh_mobile_meram_cfg structures
fbdev: sh_mobile_meram: Don't perform update in register operation
fbdev: sh_mobile_meram: Remove unneeded sanity checks
fbdev: sh_mobile_lcdc: Constify sh_mobile_lcdc_fix structure
fbdev: sh_mobile_lcdc: Rename fb operation handlers with a common
prefix
fbdev: sh_mobile_lcdc: Implement overlays support
arch/arm/mach-shmobile/board-ag5evm.c | 24 +-
arch/arm/mach-shmobile/board-ap4evb.c | 289 ++--
arch/arm/mach-shmobile/board-mackerel.c | 106 +-
arch/sh/boards/mach-ap325rxa/setup.c | 22 +-
arch/sh/boards/mach-ecovec24/setup.c | 20 +-
arch/sh/boards/mach-kfr2r09/lcd_wqvga.c | 10 +-
arch/sh/boards/mach-kfr2r09/setup.c | 8 +-
arch/sh/boards/mach-migor/lcd_qvga.c | 3 +-
arch/sh/boards/mach-migor/setup.c | 16 +-
arch/sh/boards/mach-se/7724/setup.c | 12 +-
arch/sh/include/mach-kfr2r09/mach/kfr2r09.h | 16 +-
arch/sh/include/mach-migor/mach/migor.h | 2 +-
drivers/video/Kconfig | 1 +
drivers/video/sh_mipi_dsi.c | 97 +-
drivers/video/sh_mobile_hdmi.c | 297 +---
drivers/video/sh_mobile_lcdcfb.c | 2357 +++++++++++++++++++--------
drivers/video/sh_mobile_lcdcfb.h | 84 +-
drivers/video/sh_mobile_meram.c | 673 ++++----
include/video/sh_mobile_hdmi.h | 2 -
include/video/sh_mobile_lcdc.h | 42 +-
include/video/sh_mobile_meram.h | 40 +-
21 files changed, 2518 insertions(+), 1603 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH 01/57] fbdev: sh_mobile_lcdc: Reorder code into sections
From: Laurent Pinchart @ 2011-12-13 14:01 UTC (permalink / raw)
To: linux-fbdev
Make the driver more readable by reordering code and splitting it into
logical sections. Reorder the headers alphabetically.
No modification to the code have been performed.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 421 +++++++++++++++++++++-----------------
1 files changed, 231 insertions(+), 190 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index aac5b36..8b18360 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -8,26 +8,27 @@
* for more details.
*/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
+#include <linux/atomic.h>
+#include <linux/backlight.h>
#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_device.h>
+#include <linux/console.h>
#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <linux/console.h>
-#include <linux/backlight.h>
-#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+
#include <video/sh_mobile_lcdc.h>
#include <video/sh_mobile_meram.h>
-#include <linux/atomic.h>
#include "sh_mobile_lcdcfb.h"
@@ -37,6 +38,24 @@
#define MAX_XRES 1920
#define MAX_YRES 1080
+struct sh_mobile_lcdc_priv {
+ void __iomem *base;
+ int irq;
+ atomic_t hw_usecnt;
+ struct device *dev;
+ struct clk *dot_clk;
+ unsigned long lddckr;
+ struct sh_mobile_lcdc_chan ch[2];
+ struct notifier_block notifier;
+ int started;
+ int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
+ struct sh_mobile_meram_info *meram_dev;
+};
+
+/* -----------------------------------------------------------------------------
+ * Registers access
+ */
+
static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
[LDDCKPAT1R] = 0x400,
[LDDCKPAT2R] = 0x404,
@@ -75,38 +94,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
[LDPMR] = 0x63c,
};
-static const struct fb_videomode default_720p = {
- .name = "HDMI 720p",
- .xres = 1280,
- .yres = 720,
-
- .left_margin = 220,
- .right_margin = 110,
- .hsync_len = 40,
-
- .upper_margin = 20,
- .lower_margin = 5,
- .vsync_len = 5,
-
- .pixclock = 13468,
- .refresh = 60,
- .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
-};
-
-struct sh_mobile_lcdc_priv {
- void __iomem *base;
- int irq;
- atomic_t hw_usecnt;
- struct device *dev;
- struct clk *dot_clk;
- unsigned long lddckr;
- struct sh_mobile_lcdc_chan ch[2];
- struct notifier_block notifier;
- int started;
- int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
- struct sh_mobile_meram_info *meram_dev;
-};
-
static bool banked(int reg_nr)
{
switch (reg_nr) {
@@ -127,6 +114,11 @@ static bool banked(int reg_nr)
return false;
}
+static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
+{
+ return chan->cfg.chan = LCDC_CHAN_SUBLCD;
+}
+
static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
int reg_nr, unsigned long data)
{
@@ -169,11 +161,77 @@ static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
cpu_relax();
}
-static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
+/* -----------------------------------------------------------------------------
+ * Clock management
+ */
+
+static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
{
- return chan->cfg.chan = LCDC_CHAN_SUBLCD;
+ if (atomic_inc_and_test(&priv->hw_usecnt)) {
+ if (priv->dot_clk)
+ clk_enable(priv->dot_clk);
+ pm_runtime_get_sync(priv->dev);
+ if (priv->meram_dev && priv->meram_dev->pdev)
+ pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
+ }
}
+static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
+{
+ if (atomic_sub_return(1, &priv->hw_usecnt) = -1) {
+ if (priv->meram_dev && priv->meram_dev->pdev)
+ pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
+ pm_runtime_put(priv->dev);
+ if (priv->dot_clk)
+ clk_disable(priv->dot_clk);
+ }
+}
+
+static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
+ int clock_source,
+ struct sh_mobile_lcdc_priv *priv)
+{
+ char *str;
+
+ switch (clock_source) {
+ case LCDC_CLK_BUS:
+ str = "bus_clk";
+ priv->lddckr = LDDCKR_ICKSEL_BUS;
+ break;
+ case LCDC_CLK_PERIPHERAL:
+ str = "peripheral_clk";
+ priv->lddckr = LDDCKR_ICKSEL_MIPI;
+ break;
+ case LCDC_CLK_EXTERNAL:
+ str = NULL;
+ priv->lddckr = LDDCKR_ICKSEL_HDMI;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (str) {
+ priv->dot_clk = clk_get(&pdev->dev, str);
+ if (IS_ERR(priv->dot_clk)) {
+ dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
+ return PTR_ERR(priv->dot_clk);
+ }
+ }
+
+ /* Runtime PM support involves two step for this driver:
+ * 1) Enable Runtime PM
+ * 2) Force Runtime PM Resume since hardware is accessed from probe()
+ */
+ priv->dev = &pdev->dev;
+ pm_runtime_enable(priv->dev);
+ pm_runtime_resume(priv->dev);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Sys panel and deferred I/O
+ */
+
static void lcdc_sys_write_index(void *handle, unsigned long data)
{
struct sh_mobile_lcdc_chan *ch = handle;
@@ -216,69 +274,6 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
lcdc_sys_read_data,
};
-static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
-{
- if (var->grayscale > 1)
- return var->grayscale;
-
- switch (var->bits_per_pixel) {
- case 16:
- return V4L2_PIX_FMT_RGB565;
- case 24:
- return V4L2_PIX_FMT_BGR24;
- case 32:
- return V4L2_PIX_FMT_BGR32;
- default:
- return 0;
- }
-}
-
-static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
-{
- return var->grayscale > 1;
-}
-
-static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
-{
- if (var->grayscale <= 1)
- return false;
-
- switch (var->grayscale) {
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- case V4L2_PIX_FMT_NV24:
- case V4L2_PIX_FMT_NV42:
- return true;
-
- default:
- return false;
- }
-}
-
-static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
-{
- if (atomic_inc_and_test(&priv->hw_usecnt)) {
- if (priv->dot_clk)
- clk_enable(priv->dot_clk);
- pm_runtime_get_sync(priv->dev);
- if (priv->meram_dev && priv->meram_dev->pdev)
- pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
- }
-}
-
-static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
-{
- if (atomic_sub_return(1, &priv->hw_usecnt) = -1) {
- if (priv->meram_dev && priv->meram_dev->pdev)
- pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
- pm_runtime_put(priv->dev);
- if (priv->dot_clk)
- clk_disable(priv->dot_clk);
- }
-}
-
static int sh_mobile_lcdc_sginit(struct fb_info *info,
struct list_head *pagelist)
{
@@ -345,6 +340,55 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
}
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
+{
+ if (var->grayscale > 1)
+ return var->grayscale;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ return V4L2_PIX_FMT_RGB565;
+ case 24:
+ return V4L2_PIX_FMT_BGR24;
+ case 32:
+ return V4L2_PIX_FMT_BGR32;
+ default:
+ return 0;
+ }
+}
+
+static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
+{
+ return var->grayscale > 1;
+}
+
+static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
+{
+ if (var->grayscale <= 1)
+ return false;
+
+ switch (var->grayscale) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_NV42:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Start, stop and IRQ
+ */
+
static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
{
struct sh_mobile_lcdc_priv *priv = data;
@@ -790,86 +834,9 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
sh_mobile_lcdc_clk_off(priv);
}
-static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
-{
- int interface_type = ch->cfg.interface_type;
-
- switch (interface_type) {
- case RGB8:
- case RGB9:
- case RGB12A:
- case RGB12B:
- case RGB16:
- case RGB18:
- case RGB24:
- case SYS8A:
- case SYS8B:
- case SYS8C:
- case SYS8D:
- case SYS9:
- case SYS12:
- case SYS16A:
- case SYS16B:
- case SYS16C:
- case SYS18:
- case SYS24:
- break;
- default:
- return -EINVAL;
- }
-
- /* SUBLCD only supports SYS interface */
- if (lcdc_chan_is_sublcd(ch)) {
- if (!(interface_type & LDMT1R_IFM))
- return -EINVAL;
-
- interface_type &= ~LDMT1R_IFM;
- }
-
- ch->ldmt1r_value = interface_type;
- return 0;
-}
-
-static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
- int clock_source,
- struct sh_mobile_lcdc_priv *priv)
-{
- char *str;
-
- switch (clock_source) {
- case LCDC_CLK_BUS:
- str = "bus_clk";
- priv->lddckr = LDDCKR_ICKSEL_BUS;
- break;
- case LCDC_CLK_PERIPHERAL:
- str = "peripheral_clk";
- priv->lddckr = LDDCKR_ICKSEL_MIPI;
- break;
- case LCDC_CLK_EXTERNAL:
- str = NULL;
- priv->lddckr = LDDCKR_ICKSEL_HDMI;
- break;
- default:
- return -EINVAL;
- }
-
- if (str) {
- priv->dot_clk = clk_get(&pdev->dev, str);
- if (IS_ERR(priv->dot_clk)) {
- dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
- return PTR_ERR(priv->dot_clk);
- }
- }
-
- /* Runtime PM support involves two step for this driver:
- * 1) Enable Runtime PM
- * 2) Force Runtime PM Resume since hardware is accessed from probe()
- */
- priv->dev = &pdev->dev;
- pm_runtime_enable(priv->dev);
- pm_runtime_resume(priv->dev);
- return 0;
-}
+/* -----------------------------------------------------------------------------
+ * Frame buffer operations
+ */
static int sh_mobile_lcdc_setcolreg(u_int regno,
u_int red, u_int green, u_int blue,
@@ -1334,6 +1301,10 @@ static struct fb_ops sh_mobile_lcdc_ops = {
.fb_set_par = sh_mobile_set_par,
};
+/* -----------------------------------------------------------------------------
+ * Backlight
+ */
+
static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
{
struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
@@ -1393,6 +1364,10 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
backlight_device_unregister(bdev);
}
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
static int sh_mobile_lcdc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1436,6 +1411,10 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
.runtime_resume = sh_mobile_lcdc_runtime_resume,
};
+/* -----------------------------------------------------------------------------
+ * Framebuffer notifier
+ */
+
/* locking: called with info->lock held */
static int sh_mobile_lcdc_notify(struct notifier_block *nb,
unsigned long action, void *data)
@@ -1476,6 +1455,28 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
return NOTIFY_OK;
}
+/* -----------------------------------------------------------------------------
+ * Probe/remove and driver init/exit
+ */
+
+static const struct fb_videomode default_720p = {
+ .name = "HDMI 720p",
+ .xres = 1280,
+ .yres = 720,
+
+ .left_margin = 220,
+ .right_margin = 110,
+ .hsync_len = 40,
+
+ .upper_margin = 20,
+ .lower_margin = 5,
+ .vsync_len = 5,
+
+ .pixclock = 13468,
+ .refresh = 60,
+ .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
+};
+
static int sh_mobile_lcdc_remove(struct platform_device *pdev)
{
struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
@@ -1527,6 +1528,46 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
return 0;
}
+static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+{
+ int interface_type = ch->cfg.interface_type;
+
+ switch (interface_type) {
+ case RGB8:
+ case RGB9:
+ case RGB12A:
+ case RGB12B:
+ case RGB16:
+ case RGB18:
+ case RGB24:
+ case SYS8A:
+ case SYS8B:
+ case SYS8C:
+ case SYS8D:
+ case SYS9:
+ case SYS12:
+ case SYS16A:
+ case SYS16B:
+ case SYS16C:
+ case SYS18:
+ case SYS24:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* SUBLCD only supports SYS interface */
+ if (lcdc_chan_is_sublcd(ch)) {
+ if (!(interface_type & LDMT1R_IFM))
+ return -EINVAL;
+
+ interface_type &= ~LDMT1R_IFM;
+ }
+
+ ch->ldmt1r_value = interface_type;
+ return 0;
+}
+
static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
struct device *dev)
{
--
1.7.3.4
^ permalink raw reply related
* [PATCH 02/57] fbdev: sh_mobile_lcdc: Mark init-only symbols with __devinit(const)
From: Laurent Pinchart @ 2011-12-13 14:01 UTC (permalink / raw)
To: linux-fbdev
default_720p and sh_mobile_lcdc_check_interface are used at device
initialization time only. Mark them as __devinitconst and __devinit
respectively.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 8b18360..a6bf4fb 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -1459,7 +1459,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
* Probe/remove and driver init/exit
*/
-static const struct fb_videomode default_720p = {
+static const struct fb_videomode default_720p __devinitconst = {
.name = "HDMI 720p",
.xres = 1280,
.yres = 720,
@@ -1528,7 +1528,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
return 0;
}
-static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
+static int __devinit
+sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
{
int interface_type = ch->cfg.interface_type;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 03/57] fbdev: sh_mobile_lcdc: Move pm runtime enable to probe()
From: Laurent Pinchart @ 2011-12-13 14:01 UTC (permalink / raw)
To: linux-fbdev
The pm_runtime_enable() and pm_runtime_resume() calls don't belong to
sh_mobile_lcdc_setup_clocks(). Move them to the probe function. Remove
the unneeded pm_runtime_resume() call.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 34 ++++++++++++++++------------------
1 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index a6bf4fb..7ceeed4 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -191,6 +191,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
int clock_source,
struct sh_mobile_lcdc_priv *priv)
{
+ struct clk *clk;
char *str;
switch (clock_source) {
@@ -210,21 +211,16 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
return -EINVAL;
}
- if (str) {
- priv->dot_clk = clk_get(&pdev->dev, str);
- if (IS_ERR(priv->dot_clk)) {
- dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
- return PTR_ERR(priv->dot_clk);
- }
+ if (str = NULL)
+ return 0;
+
+ clk = clk_get(&pdev->dev, str);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
+ return PTR_ERR(clk);
}
- /* Runtime PM support involves two step for this driver:
- * 1) Enable Runtime PM
- * 2) Force Runtime PM Resume since hardware is accessed from probe()
- */
- priv->dev = &pdev->dev;
- pm_runtime_enable(priv->dev);
- pm_runtime_resume(priv->dev);
+ priv->dot_clk = clk;
return 0;
}
@@ -1513,11 +1509,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
}
- if (priv->dot_clk)
+ if (priv->dot_clk) {
+ pm_runtime_disable(&pdev->dev);
clk_put(priv->dot_clk);
-
- if (priv->dev)
- pm_runtime_disable(priv->dev);
+ }
if (priv->base)
iounmap(priv->base);
@@ -1740,6 +1735,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ priv->dev = &pdev->dev;
+ priv->meram_dev = pdata->meram_dev;
platform_set_drvdata(pdev, priv);
error = request_irq(i, sh_mobile_lcdc_irq, 0,
@@ -1805,7 +1802,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
goto err1;
}
- priv->meram_dev = pdata->meram_dev;
+ /* Enable runtime PM. */
+ pm_runtime_enable(&pdev->dev);
for (i = 0; i < num_channels; i++) {
struct sh_mobile_lcdc_chan *ch = priv->ch + i;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 04/57] fbdev: sh_mobile_lcdc: Don't pass struct device around
From: Laurent Pinchart @ 2011-12-13 14:01 UTC (permalink / raw)
To: linux-fbdev
Pass a pointer to a struct sh_mobile_lcdc_priv instead, which stores a
pointer to the device.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 41 +++++++++++++++++++------------------
1 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 7ceeed4..8b78487 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -187,9 +187,8 @@ static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
}
}
-static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
- int clock_source,
- struct sh_mobile_lcdc_priv *priv)
+static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
+ int clock_source)
{
struct clk *clk;
char *str;
@@ -214,9 +213,9 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
if (str = NULL)
return 0;
- clk = clk_get(&pdev->dev, str);
+ clk = clk_get(priv->dev, str);
if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
+ dev_err(priv->dev, "cannot get dot clock %s\n", str);
return PTR_ERR(clk);
}
@@ -1564,8 +1563,9 @@ sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
return 0;
}
-static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
- struct device *dev)
+static int __devinit
+sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
+ struct sh_mobile_lcdc_chan *ch)
{
struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg;
const struct fb_videomode *max_mode;
@@ -1581,9 +1581,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
mutex_init(&ch->open_lock);
/* Allocate the frame buffer device. */
- ch->info = framebuffer_alloc(0, dev);
+ ch->info = framebuffer_alloc(0, priv->dev);
if (!ch->info) {
- dev_err(dev, "unable to allocate fb_info\n");
+ dev_err(priv->dev, "unable to allocate fb_info\n");
return -ENOMEM;
}
@@ -1605,8 +1605,8 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
/* NV12/NV21 buffers must have even number of lines */
if ((cfg->fourcc = V4L2_PIX_FMT_NV12 ||
cfg->fourcc = V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
- dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
- "mode.\n");
+ dev_err(priv->dev, "yres must be multiple of 2 for "
+ "YCbCr420 mode.\n");
return -EINVAL;
}
@@ -1619,7 +1619,7 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
if (!max_size)
max_size = MAX_XRES * MAX_YRES;
else
- dev_dbg(dev, "Found largest videomode %ux%u\n",
+ dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
max_mode->xres, max_mode->yres);
/* Create the mode list. */
@@ -1670,16 +1670,17 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
max_size = max_size * var->bits_per_pixel / 8 * 2;
/* Allocate frame buffer memory and color map. */
- buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL);
+ buf = dma_alloc_coherent(priv->dev, max_size, &ch->dma_handle,
+ GFP_KERNEL);
if (!buf) {
- dev_err(dev, "unable to allocate buffer\n");
+ dev_err(priv->dev, "unable to allocate buffer\n");
return -ENOMEM;
}
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
if (ret < 0) {
- dev_err(dev, "unable to allocate cmap\n");
- dma_free_coherent(dev, max_size, buf, ch->dma_handle);
+ dev_err(priv->dev, "unable to allocate cmap\n");
+ dma_free_coherent(priv->dev, max_size, buf, ch->dma_handle);
return ret;
}
@@ -1702,7 +1703,7 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
}
info->screen_base = buf;
- info->device = dev;
+ info->device = priv->dev;
ch->display_var = *var;
return 0;
@@ -1796,7 +1797,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
if (!priv->base)
goto err1;
- error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
+ error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
if (error) {
dev_err(&pdev->dev, "unable to setup clocks\n");
goto err1;
@@ -1808,7 +1809,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
for (i = 0; i < num_channels; i++) {
struct sh_mobile_lcdc_chan *ch = priv->ch + i;
- error = sh_mobile_lcdc_channel_init(ch, &pdev->dev);
+ error = sh_mobile_lcdc_channel_init(priv, ch);
if (error)
goto err1;
}
@@ -1838,7 +1839,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
if (error < 0)
goto err1;
- dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
+ dev_info(&pdev->dev, "registered %s/%s as %dx%d %dbpp.\n",
pdev->name, (ch->cfg.chan = LCDC_CHAN_MAINLCD) ?
"mainlcd" : "sublcd", info->var.xres, info->var.yres,
info->var.bits_per_pixel);
--
1.7.3.4
^ permalink raw reply related
* [PATCH 05/57] fbdev: sh_mobile_lcdc: Create functions to turn the display on/off
From: Laurent Pinchart @ 2011-12-13 14:02 UTC (permalink / raw)
To: linux-fbdev
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 53 ++++++++++++++++++++------------------
1 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 8b78487..afa1fac 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -224,7 +224,7 @@ static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
}
/* -----------------------------------------------------------------------------
- * Sys panel and deferred I/O
+ * Display, panel and deferred I/O
*/
static void lcdc_sys_write_index(void *handle, unsigned long data)
@@ -335,6 +335,27 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
}
+static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
+{
+ struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
+
+ /* HDMI must be enabled before LCDC configuration */
+ if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
+ board_cfg->display_on(board_cfg->board_data, ch->info);
+ module_put(board_cfg->owner);
+ }
+}
+
+static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
+{
+ struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
+
+ if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
+ board_cfg->display_off(board_cfg->board_data);
+ module_put(board_cfg->owner);
+ }
+}
+
/* -----------------------------------------------------------------------------
* Format helpers
*/
@@ -648,7 +669,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
{
struct sh_mobile_meram_info *mdev = priv->meram_dev;
- struct sh_mobile_lcdc_board_cfg *board_cfg;
struct sh_mobile_lcdc_chan *ch;
unsigned long tmp;
int ret;
@@ -665,8 +685,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
- ch = &priv->ch[k];
+ struct sh_mobile_lcdc_board_cfg *board_cfg;
+ ch = &priv->ch[k];
if (!ch->enabled)
continue;
@@ -754,11 +775,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
fb_deferred_io_init(ch->info);
}
- board_cfg = &ch->cfg.board_cfg;
- if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
- board_cfg->display_on(board_cfg->board_data, ch->info);
- module_put(board_cfg->owner);
- }
+ sh_mobile_lcdc_display_on(ch);
if (ch->bl) {
ch->bl->props.power = FB_BLANK_UNBLANK;
@@ -772,7 +789,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
{
struct sh_mobile_lcdc_chan *ch;
- struct sh_mobile_lcdc_board_cfg *board_cfg;
int k;
/* clean up deferred io and ask board code to disable panel */
@@ -799,11 +815,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
backlight_update_status(ch->bl);
}
- board_cfg = &ch->cfg.board_cfg;
- if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
- board_cfg->display_off(board_cfg->board_data);
- module_put(board_cfg->owner);
- }
+ sh_mobile_lcdc_display_off(ch);
/* disable the meram */
if (ch->meram_enabled) {
@@ -1417,7 +1429,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
struct fb_event *event = data;
struct fb_info *info = event->info;
struct sh_mobile_lcdc_chan *ch = info->par;
- struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
if (&ch->lcdc->notifier != nb)
return NOTIFY_DONE;
@@ -1427,10 +1438,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
switch(action) {
case FB_EVENT_SUSPEND:
- if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
- board_cfg->display_off(board_cfg->board_data);
- module_put(board_cfg->owner);
- }
+ sh_mobile_lcdc_display_off(ch);
sh_mobile_lcdc_stop(ch->lcdc);
break;
case FB_EVENT_RESUME:
@@ -1438,12 +1446,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
sh_mobile_fb_reconfig(info);
mutex_unlock(&ch->open_lock);
- /* HDMI must be enabled before LCDC configuration */
- if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
- board_cfg->display_on(board_cfg->board_data, info);
- module_put(board_cfg->owner);
- }
-
+ sh_mobile_lcdc_display_on(ch);
sh_mobile_lcdc_start(ch->lcdc);
}
--
1.7.3.4
^ 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