* Re: [RFC][PATCH V2 3/3] tegra: add pwm backlight device tree nodes
From: Thierry Reding @ 2012-07-12 10:04 UTC (permalink / raw)
To: Simon Glass
Cc: Alexandre Courbot, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
In-Reply-To: <CAPnjgZ1QbjE+-tr0c01K2feUdEE2wMBfR=bKpTxnyDOJbY8+1Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 3691 bytes --]
On Thu, Jul 12, 2012 at 11:37:33AM +0200, Simon Glass wrote:
> Hi Alex,
>
> On Mon, Jul 9, 2012 at 8:08 AM, Alexandre Courbot <acourbot@nvidia.com> wrote:
> > Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> > ---
> > arch/arm/boot/dts/tegra20-ventana.dts | 31 +++++++++++++++++++++++++++++++
> > arch/arm/boot/dts/tegra20.dtsi | 2 +-
> > 2 files changed, 32 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
> > index be90544..c67d9e1 100644
> > --- a/arch/arm/boot/dts/tegra20-ventana.dts
> > +++ b/arch/arm/boot/dts/tegra20-ventana.dts
> > @@ -317,6 +317,37 @@
> > bus-width = <8>;
> > };
> >
>
> I would like to do something similar in U-Boot for Tegra, although
> perhaps not right away. For now I will go with something considerably
> simpler! But if this is merged into the kernel we will move to it in
> U-Boot. Anyway here are my comments:
>
> > + backlight {
> > + compatible = "pwm-backlight";
> > + brightness-levels = <0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 255>;
>
> We seem to have a lot of these - should we move to a range and step size?
These actually seem to be a little bogus. The reason for introducing the
levels was to allow calibration of these values because they in fact
usually do not scale linearly. Instead, a linear brightness increase
usually maps to something like a logarithmic (at best) increase of the
duty cycle.
> > + default-brightness-level = <12>;
> > +
> > + pwms = <&pwm 2 5000000>;
> > + pwm-names = "backlight";
> > + power-supply = <&backlight_reg>;
> > + enable-gpios = <&gpio 28 0>;
> > +
> > + power-on-sequence = "REGULATOR", "power", <1>,
> > + "DELAY", <10>,
> > + "PWM", "backlight", <1>,
> > + "GPIO", "enable", <1>;
>
> So the names REGULATOR, DELAY, etc. here are looked up through some
> existing mechanism? In general I am not a big fan of mixing strings
> and numbers in a property. Maybe something like:
>
> power_on_sequence {
> step@0 {
> phandle = <&backlight_reg>;
> enable = <1>;
> post-delay = <10>;
> }
> step@1 {
> phandle = <&pwm 2 5000000>;
> }
> step@2 {
> phandle = <&gpio 28 0>;
> enable = <1>;
> }
I actually like that a lot. What's missing from your example is a way to
specify the type of the phandle because it cannot be safely inferred.
Perhaps this could be done by just the property name:
power_on_sequence {
step@0 {
power-supply = <&backlight_reg>;
enable = <1>;
post-delay = <10>;
};
step@1 {
pwm = <&pwm 2 5000000>;
};
step@2 {
enable-gpios = <&gpio 28 0>;
enable = <1>;
};
};
However I think one of the reasons for Alex to choose his particular
representation is that people want this to be representable in the
platform data as well, which unfortunately can't deal very well with
this kind of situation.
Usually in the kernel you have one API to obtain a resource (pwm_get(),
regulator_get(), ...) which takes as an argument a device handle and a
name. For device tree, that API will lookup the resource by phandle,
while the non-DT code path typically uses a static lookup table.
It's a shame that we have to keep this kind of backwards compatibility
because it prevents these things from being represented in a logic way
in the DT sense.
Thierry
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [RFC][PATCH V2 3/3] tegra: add pwm backlight device tree nodes
From: Alex Courbot @ 2012-07-12 10:11 UTC (permalink / raw)
To: Simon Glass
Cc: Thierry Reding, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org,
devicetree-discuss@lists.ozlabs.org
In-Reply-To: <CAPnjgZ1QbjE+-tr0c01K2feUdEE2wMBfR=bKpTxnyDOJbY8+1Q@mail.gmail.com>
Hi Simon,
On Thu 12 Jul 2012 06:37:33 PM JST, Simon Glass wrote:
> I would like to do something similar in U-Boot for Tegra, although
> perhaps not right away. For now I will go with something considerably
> simpler! But if this is merged into the kernel we will move to it in
> U-Boot.
Cool, I'd love to see that used in U-Boot as well.
>> + default-brightness-level = <12>;
>> +
>> + pwms = <&pwm 2 5000000>;
>> + pwm-names = "backlight";
>> + power-supply = <&backlight_reg>;
>> + enable-gpios = <&gpio 28 0>;
>> +
>> + power-on-sequence = "REGULATOR", "power", <1>,
>> + "DELAY", <10>,
>> + "PWM", "backlight", <1>,
>> + "GPIO", "enable", <1>;
>
> So the names REGULATOR, DELAY, etc. here are looked up through some
> existing mechanism? In general I am not a big fan of mixing strings
> and numbers in a property.
Yes, these are strings we are looking up to know the type of the next
element to power on/off in the sequence. I don't like these, honestly,
and would rather have them replaced by constants - however there is no
way to define constants in the DT AFAIK (but I have heard some other
persons are interested in having them too), and this is the only way I
have found to keep the sequence readable.
> Maybe something like:
>
> power_on_sequence {
> step@0 {
> phandle = <&backlight_reg>;
> enable = <1>;
> post-delay = <10>;
> }
> step@1 {
> phandle = <&pwm 2 5000000>;
> }
> step@2 {
> phandle = <&gpio 28 0>;
> enable = <1>;
> }
I see a few problems with this: first, how do you know the types of your
phandles? At step 0, we should get a regulator, step 1 is a PWM and step
2 is a GPIO. This is why I have used strings to identify the type of the
phandle and the number (and type) of additional arguments to parse for a
step.
Second, I am afraid the representation in memory would be significantly
bigger since the properties names would have to be stored as well (I am
no DT expert, please correct me if I am wrong). Lastly, the additional
freedom of having extra properties might make the parser more complicated.
I agree the type strings are a problem in the current form - if we could
get constants in the device tree, that would be much better. Your way of
representing the sequences is interesting though, if we can solve the
type issue (and also evaluate its cost in terms of memory footprint), it
would be interesting to consider it as well.
Alex.
^ permalink raw reply
* Re: [PATCH 1/2] video: da8xx-fb: configure FIFO threshold to reduce underflow errors
From: Sergei Shtylyov @ 2012-07-12 13:23 UTC (permalink / raw)
To: linux-fbdev
Hello.
On 11-07-2012 19:14, Manjunathappa, Prakash wrote:
> Patch works around the below silicon errata:
> During LCDC initialization, there is the potential for a FIFO
> underflow condition to occur. A FIFO underflow condition
> occurs when the input FIFO is completely empty and the LCDC
> raster controller logic that drives data to the output pins
> attempts to fetch data from the FIFO. When a FIFO underflow
> condition occurs, incorrect data will be driven out on the
> LCDC data pins.
> Software should poll the FUF bit field in the LCD_STAT register
> to check if an error condition has occurred or service the
> interrupt if FUF_EN is enabled when FUF occurs. If the FUF bit
> field has been set to 1, this will indicate an underflow
> condition has occurred and then the software should execute a
> reset of the LCDC via the LPSC.
> This problem may occur if the LCDC FIFO threshold size
> (LCDDMA_CTRL[TH_FIFO_READY]) is left at its default value after
> reset. Increasing the FIFO threshold size will reduce or
> eliminate underflows. Setting the threshold size to 256 double
> words or larger is recommended.
> Above issue is described in section 2.1.3 of silicon errata
> http://www.ti.com/lit/er/sprz313e/sprz313e.pdf
> Signed-off-by: Rajashekhara, Sudhakar <sudhakar.raj@ti.com>
> Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
> ---
> drivers/video/da8xx-fb.c | 15 +++++++++++----
> include/video/da8xx-fb.h | 3 +++
> 2 files changed, 14 insertions(+), 4 deletions(-)
> diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> index 47118c7..2010dd7 100644
> --- a/drivers/video/da8xx-fb.c
> +++ b/drivers/video/da8xx-fb.c
> @@ -344,8 +344,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
> lcd_enable_raster();
> }
>
> -/* Configure the Burst Size of DMA */
> -static int lcd_cfg_dma(int burst_size)
> +/* Configure the Burst Size and fifo threhold of DMA */
> +static int lcd_cfg_dma(int burst_size, int fifo_th)
One space too much.
> {
> u32 reg;
>
> @@ -719,8 +722,10 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
>
> if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
> lcd_disable_raster();
> + clk_disable(par->lcdc_clk);
> lcdc_write(stat, LCD_MASKED_STAT_REG);
Will LCDC register wrtite work without LCDC clock?
> lcd_enable_raster();
> + clk_enable(par->lcdc_clk);
> } else if (stat & LCD_PL_LOAD_DONE) {
> /*
> * Must disable raster before changing state of any control bit.
> @@ -774,8 +779,10 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
>
> if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
> lcd_disable_raster();
> + clk_disable(par->lcdc_clk);
> lcdc_write(stat, LCD_STAT_REG);
Same question.
WBR, Sergei
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Peter De Schrijver @ 2012-07-12 14:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120711200402.GC2772@gmail.com>
On Wed, Jul 11, 2012 at 10:04:02PM +0200, Mike Turquette wrote:
> On 20120711-15:44, Mark Brown wrote:
> > On Wed, Jul 11, 2012 at 09:03:41AM -0500, Rob Herring wrote:
> >
> > > I'd expect a single property with freq/volt pairs or 2 properties for
> > > freq and voltage where there is a 1:1 relationship (freq N uses voltage N).
> >
> > I strongly agree - the current proposal is very hard to read due to the
> > separation between the voltage and frequency values. Some devices do
> > also need to scale multiple rails together, especially when this gets
> > used for I/O devices.
> >
> > I'd also expect to see a range of voltages for each frequency rather
> > than a specific voltage; usually things are at least characterised with
> > a specified tolerance.
>
> Not only should we support multiple voltage rails but also multiple
> clocks. For some devices a DVFS transition is composed of scaling
> multiple clock rates together. So some sort of clock identifier
> (phandle?) is needed as well. (forgive my ignorance on the phandle
> part, as I am a DT noob)
I would say this constraint should be expressed in a seperate DT node. In
short I think we have 3 things to model:
+ frequency/voltage relationships
+ power rail constraints (eg voltage difference limit between 2 rails)
+ clock constraints (eg. clock x frequency must be a fixed ratio of clock y
frequency)
Cheers,
Peter.
^ permalink raw reply
* RE: [PATCH 1/2] video: da8xx-fb: configure FIFO threshold to reduce underflow errors
From: Manjunathappa, Prakash @ 2012-07-12 14:13 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <4FFECFCE.2000308@mvista.com>
Hi Sergei,
On Thu, Jul 12, 2012 at 18:53:26, Sergei Shtylyov wrote:
> Hello.
>
> On 11-07-2012 19:14, Manjunathappa, Prakash wrote:
>
> > Patch works around the below silicon errata:
> > During LCDC initialization, there is the potential for a FIFO
> > underflow condition to occur. A FIFO underflow condition
> > occurs when the input FIFO is completely empty and the LCDC
> > raster controller logic that drives data to the output pins
> > attempts to fetch data from the FIFO. When a FIFO underflow
> > condition occurs, incorrect data will be driven out on the
> > LCDC data pins.
>
> > Software should poll the FUF bit field in the LCD_STAT register
> > to check if an error condition has occurred or service the
> > interrupt if FUF_EN is enabled when FUF occurs. If the FUF bit
> > field has been set to 1, this will indicate an underflow
> > condition has occurred and then the software should execute a
> > reset of the LCDC via the LPSC.
>
> > This problem may occur if the LCDC FIFO threshold size
> > (LCDDMA_CTRL[TH_FIFO_READY]) is left at its default value after
> > reset. Increasing the FIFO threshold size will reduce or
> > eliminate underflows. Setting the threshold size to 256 double
> > words or larger is recommended.
>
> > Above issue is described in section 2.1.3 of silicon errata
> > http://www.ti.com/lit/er/sprz313e/sprz313e.pdf
>
> > Signed-off-by: Rajashekhara, Sudhakar <sudhakar.raj@ti.com>
> > Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
> > ---
> > drivers/video/da8xx-fb.c | 15 +++++++++++----
> > include/video/da8xx-fb.h | 3 +++
> > 2 files changed, 14 insertions(+), 4 deletions(-)
>
> > diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
> > index 47118c7..2010dd7 100644
> > --- a/drivers/video/da8xx-fb.c
> > +++ b/drivers/video/da8xx-fb.c
> > @@ -344,8 +344,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
> > lcd_enable_raster();
> > }
> >
> > -/* Configure the Burst Size of DMA */
> > -static int lcd_cfg_dma(int burst_size)
> > +/* Configure the Burst Size and fifo threhold of DMA */
> > +static int lcd_cfg_dma(int burst_size, int fifo_th)
>
> One space too much.
>
Yes, I will correct this. Don't know how checkpatch missing it.
> > {
> > u32 reg;
> >
> > @@ -719,8 +722,10 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
> >
> > if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
> > lcd_disable_raster();
> > + clk_disable(par->lcdc_clk);
> > lcdc_write(stat, LCD_MASKED_STAT_REG);
>
> Will LCDC register wrtite work without LCDC clock?
>
Yes it cannot happen. I will remove it.
Thanks,
Prakash
^ permalink raw reply
* Re: [RFC][PATCH V2 3/3] tegra: add pwm backlight device tree nodes
From: Simon Glass @ 2012-07-12 14:27 UTC (permalink / raw)
To: Alex Courbot
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
In-Reply-To: <4FFEA2D4.9050308-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Hi Alex,
On Thu, Jul 12, 2012 at 12:11 PM, Alex Courbot <acourbot@nvidia.com> wrote:
> Hi Simon,
>
>
> On Thu 12 Jul 2012 06:37:33 PM JST, Simon Glass wrote:
>>
>> I would like to do something similar in U-Boot for Tegra, although
>> perhaps not right away. For now I will go with something considerably
>> simpler! But if this is merged into the kernel we will move to it in
>> U-Boot.
>
>
> Cool, I'd love to see that used in U-Boot as well.
>
>
>>> + default-brightness-level = <12>;
>>> +
>>> + pwms = <&pwm 2 5000000>;
>>> + pwm-names = "backlight";
>>> + power-supply = <&backlight_reg>;
>>> + enable-gpios = <&gpio 28 0>;
>>> +
>>> + power-on-sequence = "REGULATOR", "power", <1>,
>>> + "DELAY", <10>,
>>> + "PWM", "backlight", <1>,
>>> + "GPIO", "enable", <1>;
>>
>>
>> So the names REGULATOR, DELAY, etc. here are looked up through some
>> existing mechanism? In general I am not a big fan of mixing strings
>> and numbers in a property.
>
>
> Yes, these are strings we are looking up to know the type of the next
> element to power on/off in the sequence. I don't like these, honestly, and
> would rather have them replaced by constants - however there is no way to
> define constants in the DT AFAIK (but I have heard some other persons are
> interested in having them too), and this is the only way I have found to
> keep the sequence readable.
That might be the 100th time that I have heard this. I have brought a
patch from Stephen Warren into our tree to solve this locally, but it
is not merged upstream.
>
>
>> Maybe something like:
>>
>> power_on_sequence {
>> step@0 {
>> phandle = <&backlight_reg>;
>> enable = <1>;
>> post-delay = <10>;
>> }
>> step@1 {
>> phandle = <&pwm 2 5000000>;
>> }
>> step@2 {
>> phandle = <&gpio 28 0>;
>> enable = <1>;
>> }
>
>
> I see a few problems with this: first, how do you know the types of your
> phandles? At step 0, we should get a regulator, step 1 is a PWM and step 2
> is a GPIO. This is why I have used strings to identify the type of the
> phandle and the number (and type) of additional arguments to parse for a
> step.
Well it's similar to giving them names - you would need to look up the
phandle and see its compatible string or which driver type owns it.
Maybe too complicated, and no such infrastructure exists, so:
>> power_on_sequence {
>> step@0 {
type = "regulator";
>> phandle = <&backlight_reg>;
>> enable = <1>;
>> post-delay = <10>;
>> }
>> step@1 {
type = "pwm";
>> phandle = <&pwm 2 5000000>;
>> }
>> step@2 {
type = "gpio";
>> phandle = <&gpio 28 0>;
>> enable = <1>;
>> }
>
> Second, I am afraid the representation in memory would be significantly
> bigger since the properties names would have to be stored as well (I am no
> DT expert, please correct me if I am wrong). Lastly, the additional freedom
> of having extra properties might make the parser more complicated.
The property names are only stored one, in the string table. I am not
sure about parsing complexity, but it might actually be easier.
>
> I agree the type strings are a problem in the current form - if we could get
> constants in the device tree, that would be much better. Your way of
> representing the sequences is interesting though, if we can solve the type
> issue (and also evaluate its cost in terms of memory footprint), it would be
> interesting to consider it as well.
At a guess:
>>> + power-on-sequence = "REGULATOR", "power", <1>,
>>> + "DELAY", <10>,
>>> + "PWM", "backlight", <1>,
>>> + "GPIO", "enable", <1>;
About 106 bytes I think
>> step@0 { 16
type = "regulator"; 24
>> phandle = <&backlight_reg>; 16
>> enable = <1>; 16
>> post-delay = <10>; 16
>> }
>> step@1 { 16
type = "pwm"; 16
>> phandle = <&pwm 2 5000000>; 24
>> }
>> step@2 { 16
type = "gpio"; 20
>> phandle = <&gpio 28 0>; 24
>> enable = <1>; 16
>> }
220?
From my understanding mixing strings and numbers in a property is
frowned on though.
>
> Alex.
Regards,
Simon
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Mark Brown @ 2012-07-12 15:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4FFE4FE6.20109@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 472 bytes --]
On Thu, Jul 12, 2012 at 09:47:42AM +0530, Prashant Gaikwad wrote:
> On Wednesday 11 July 2012 08:14 PM, Mark Brown wrote:
> >I'd also expect to see a range of voltages for each frequency rather
> >than a specific voltage; usually things are at least characterised with
> >a specified tolerance.
> But then how will you determine the operating voltage for a frequency?
By passing the range into the regulator API - the regulator API always
takes a voltage range anyway.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Mike Turquette @ 2012-07-12 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4FFE4FE6.20109@nvidia.com>
On 20120712-09:47, Prashant Gaikwad wrote:
> On Wednesday 11 July 2012 08:14 PM, Mark Brown wrote:
> >On Wed, Jul 11, 2012 at 09:03:41AM -0500, Rob Herring wrote:
> >
> >>I'd expect a single property with freq/volt pairs or 2 properties for
> >>freq and voltage where there is a 1:1 relationship (freq N uses voltage N).
> >I strongly agree - the current proposal is very hard to read due to the
> >separation between the voltage and frequency values. Some devices do
> >also need to scale multiple rails together, especially when this gets
> >used for I/O devices.
>
> Multiple rails for single clock or would it be multiple clocks?
>
Voltage rails do not correspond to clocks. They correspond to the IP
block in question (e.g. the "module" or "device" that consumes clocks
and voltage).
Regards,
Mike
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Mike Turquette @ 2012-07-12 17:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120712141001.GE9437@tbergstrom-lnx.Nvidia.com>
On 20120712-17:10, Peter De Schrijver wrote:
> On Wed, Jul 11, 2012 at 10:04:02PM +0200, Mike Turquette wrote:
> > On 20120711-15:44, Mark Brown wrote:
> > > On Wed, Jul 11, 2012 at 09:03:41AM -0500, Rob Herring wrote:
> > >
> > > > I'd expect a single property with freq/volt pairs or 2 properties for
> > > > freq and voltage where there is a 1:1 relationship (freq N uses voltage N).
> > >
> > > I strongly agree - the current proposal is very hard to read due to the
> > > separation between the voltage and frequency values. Some devices do
> > > also need to scale multiple rails together, especially when this gets
> > > used for I/O devices.
> > >
> > > I'd also expect to see a range of voltages for each frequency rather
> > > than a specific voltage; usually things are at least characterised with
> > > a specified tolerance.
> >
> > Not only should we support multiple voltage rails but also multiple
> > clocks. For some devices a DVFS transition is composed of scaling
> > multiple clock rates together. So some sort of clock identifier
> > (phandle?) is needed as well. (forgive my ignorance on the phandle
> > part, as I am a DT noob)
>
> I would say this constraint should be expressed in a seperate DT node. In
> short I think we have 3 things to model:
>
Peter,
I agree with your observations in general, but I think some specificity
is needed:
> + frequency/voltage relationships
We should be clear that the voltage does NOT belong to the clock, but to
the device/module/IP block that consumes that clock. This is an
important detail since it means that a clock does not have a
corresponding table of voltages (e.g. one table per clock), but instead
a device has a table of voltages corresponding to each clock.
This is very necessary when a single clock drives multiple devices which
are driven by separate voltage rails.
> + power rail constraints (eg voltage difference limit between 2 rails)
This should come from regulator DT data and not anything DVFS-specific,
correct?
> + clock constraints (eg. clock x frequency must be a fixed ratio of clock y
> frequency)
Yeah, after sending my email above yesterday I instantly regretted it.
It is true that *functional* clock dependencies are really the purview
of the device driver. E.g. for Device X to operate at FAST_SPEED, scale
functional_clk up to 200MHz and l3_ddr_clk up to 100MHz. On OMAP our
display subsystem block also has clock ratio rules that must be honored,
but it just open-coded.
It is possible to model those in DT if we really want, but shouldn't be
a priority for these dvfs-specific bindings.
Regards,
Mike
>
> Cheers,
>
> Peter.
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Mark Brown @ 2012-07-12 17:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120712171016.GL2772@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1266 bytes --]
On Thu, Jul 12, 2012 at 10:10:16AM -0700, Mike Turquette wrote:
> On 20120712-17:10, Peter De Schrijver wrote:
> > + power rail constraints (eg voltage difference limit between 2 rails)
> This should come from regulator DT data and not anything DVFS-specific,
> correct?
Currently the regulator API will only constrain individual rails (and
shortly likely parent/child relationships). It will not do anything to
constrain between different rails, this has been left to the consumers.
For this stuff it may still make sense to do that if we've got a set of
operating points defined which apply over multiple inputs (like clock
and frequency) - we'll naturally impose these constraints by virtue of
selecting the operating point.
> > + clock constraints (eg. clock x frequency must be a fixed ratio of clock y
> > frequency)
> Yeah, after sending my email above yesterday I instantly regretted it.
> It is true that *functional* clock dependencies are really the purview
> of the device driver. E.g. for Device X to operate at FAST_SPEED, scale
> functional_clk up to 200MHz and l3_ddr_clk up to 100MHz. On OMAP our
> display subsystem block also has clock ratio rules that must be honored,
> but it just open-coded.
This is similar to the regulator thing.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [RFC][PATCH V2 3/3] tegra: add pwm backlight device tree nodes
From: Alex Courbot @ 2012-07-13 5:32 UTC (permalink / raw)
To: Simon Glass
Cc: Thierry Reding, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-fbdev@vger.kernel.org,
devicetree-discuss@lists.ozlabs.org
In-Reply-To: <CAPnjgZ2=Ga2P-40trA_=UABm=i7Uy4NTAM=ehea11mE22VfDew@mail.gmail.com>
On 07/12/2012 11:27 PM, Simon Glass wrote
>> I agree the type strings are a problem in the current form - if we could get
>> constants in the device tree, that would be much better. Your way of
>> representing the sequences is interesting though, if we can solve the type
>> issue (and also evaluate its cost in terms of memory footprint), it would be
>> interesting to consider it as well.
>
> At a guess:
>
>>>> + power-on-sequence = "REGULATOR", "power", <1>,
>>>> + "DELAY", <10>,
>>>> + "PWM", "backlight", <1>,
>>>> + "GPIO", "enable", <1>;
>
> About 106 bytes I think
>
>>> step@0 { 16
> type = "regulator"; 24
>>> phandle = <&backlight_reg>; 16
>>> enable = <1>; 16
>>> post-delay = <10>; 16
>>> }
>>> step@1 { 16
> type = "pwm"; 16
>>> phandle = <&pwm 2 5000000>; 24
>>> }
>>> step@2 { 16
> type = "gpio"; 20
>>> phandle = <&gpio 28 0>; 24
>>> enable = <1>; 16
>>> }
>
> 220?
I compiled both versions to try it out. Your version was just 50 bytes
larger than mine (I assumed that with yours, we would be able to remove
the top-level pwm/regulator/gpio definitions that are referred by the
sequence). The question here is do we want to have something more
DT-ish, or are we trying to save every possible byte in the DT structure?
As Thierry also mentionned, we are trying to provide the same feature
using the platform interface. I am not sure how we can elegantly support
both ways through this.
> From my understanding mixing strings and numbers in a property is
> frowned on though.
But doesn't it make sense in the current case? The power sequence is
basically a program that is run by an interpreter. From this
perspective, it makes more sense to me to have it as a binary field
rather than a hierarchy of nodes and properties that will be harder to
parse and will make error detection more complicated. I don't really see
any practical benefit from turning the steps into sub-nodes, but then
again I am not so familiar with the DT.
Alex.
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Peter De Schrijver @ 2012-07-13 10:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120712171016.GL2772@gmail.com>
Hi Mike,
>
> Peter,
>
> I agree with your observations in general, but I think some specificity
> is needed:
>
> > + frequency/voltage relationships
>
> We should be clear that the voltage does NOT belong to the clock, but to
> the device/module/IP block that consumes that clock. This is an
> important detail since it means that a clock does not have a
> corresponding table of voltages (e.g. one table per clock), but instead
> a device has a table of voltages corresponding to each clock.
>
Or the other way around, a table of clock frequencies, 1 for each voltage.
> This is very necessary when a single clock drives multiple devices which
> are driven by separate voltage rails.
>
Ah ok. How does this work in practice? A device can only run at a given clock
rate if all the rails are at a certain voltage?
> > + power rail constraints (eg voltage difference limit between 2 rails)
>
> This should come from regulator DT data and not anything DVFS-specific,
> correct?
>
That's true. I think it can even be open-coded as this is a SoC internal
thing. All boards using this SoC will have the same limits, so I see little
reason to move this info to DT.
> > + clock constraints (eg. clock x frequency must be a fixed ratio of clock y
> > frequency)
>
> Yeah, after sending my email above yesterday I instantly regretted it.
> It is true that *functional* clock dependencies are really the purview
> of the device driver. E.g. for Device X to operate at FAST_SPEED, scale
> functional_clk up to 200MHz and l3_ddr_clk up to 100MHz. On OMAP our
> display subsystem block also has clock ratio rules that must be honored,
> but it just open-coded.
>
> It is possible to model those in DT if we really want, but shouldn't be
> a priority for these dvfs-specific bindings.
>
Agreed.
Cheers,
Peter.
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Mike Turquette @ 2012-07-13 17:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120713103408.GF9437@tbergstrom-lnx.Nvidia.com>
On 20120713-13:34, Peter De Schrijver wrote:
> Hi Mike,
>
> >
> > Peter,
> >
> > I agree with your observations in general, but I think some specificity
> > is needed:
> >
> > > + frequency/voltage relationships
> >
> > We should be clear that the voltage does NOT belong to the clock, but to
> > the device/module/IP block that consumes that clock. This is an
> > important detail since it means that a clock does not have a
> > corresponding table of voltages (e.g. one table per clock), but instead
> > a device has a table of voltages corresponding to each clock.
> >
>
> Or the other way around, a table of clock frequencies, 1 for each voltage.
>
ACK
You said what I meant to say. Some previous iterations of an
omap-specific dvfs api tried to use voltage as the unique key for
accessing frequency/voltage tables, and that can get really ugly for a
variety of reasons. Plus device drivers typically request performance
in Hertz (e.g. clk_set_rate), so exposing a voltage-centric interface to
them is generally useless.
The OPP library does some of this right (drivers/base/power/opp.c). It
keeps a list of tables on a per-device bases, which is a big step in the
right direction. Unfortunately it is lacking in other areas, such as
not specifying which clock corresponds to the to table. Thus a device
can only have one table and that table does not encode any information
about which clock to use (which is important for devices that use a mux
to change rate). The dvfs DT bindings should not repeat those mistakes.
> > This is very necessary when a single clock drives multiple devices which
> > are driven by separate voltage rails.
> >
>
> Ah ok. How does this work in practice? A device can only run at a given clock
> rate if all the rails are at a certain voltage?
>
More like an adjustable rate clock higher up the tree affects the rate
of multiple devices downstream, and those devices happen to be on
separate rails. Either way I think that the design should account for
this possibility.
Regards,
Mike
> > > + power rail constraints (eg voltage difference limit between 2 rails)
> >
> > This should come from regulator DT data and not anything DVFS-specific,
> > correct?
> >
>
> That's true. I think it can even be open-coded as this is a SoC internal
> thing. All boards using this SoC will have the same limits, so I see little
> reason to move this info to DT.
>
> > > + clock constraints (eg. clock x frequency must be a fixed ratio of clock y
> > > frequency)
> >
> > Yeah, after sending my email above yesterday I instantly regretted it.
> > It is true that *functional* clock dependencies are really the purview
> > of the device driver. E.g. for Device X to operate at FAST_SPEED, scale
> > functional_clk up to 200MHz and l3_ddr_clk up to 100MHz. On OMAP our
> > display subsystem block also has clock ratio rules that must be honored,
> > but it just open-coded.
> >
> > It is possible to model those in DT if we really want, but shouldn't be
> > a priority for these dvfs-specific bindings.
> >
>
> Agreed.
>
> Cheers,
>
> Peter.
^ permalink raw reply
* Re: Device tree binding for DVFS table
From: Prashant Gaikwad @ 2012-07-13 18:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4FFE4DD0.7020407@nvidia.com>
Hi,
On Thursday 12 July 2012 09:38 AM, Prashant Gaikwad wrote:
> On Wednesday 11 July 2012 07:33 PM, Rob Herring wrote:
>> On 07/11/2012 07:56 AM, Prashant Gaikwad wrote:
>>> Hi,
>>>
>>> I am working on DT binding for Tegra DVFS.
<snip>
>>> compatible = "nvidia,tegra30-dvfs-table";
>>> reg_id =<&sm0>;
>>> #address-cells =<1>;
>>> #size-cells =<0>;
>>> voltage-array =<750 775 800 825 850 875 900 925 950 975
>>> 1000 1025 1050 1100 1125>;
>> The SOC is really characterized at all these voltages?
>
> Not really, but different processes of single SoC are characterized
> for different voltages and this array covers all those voltages.
>
>>> };
>>>
>>> device {
>>> dvfs =<&cpu-dvfs-table>;
>>> frequency-table@102 {
>>> reg =<0x102>;
>>> frequencies =<314 314 314 456 456 456 608 608
>>> 608
>>> 760 817 817 912 1000>;
>> I don't see the point of repeating frequencies.
>>> };
>>> frequency-table@002 {
>>> reg =<0x002>;
>>> frequencies =<598 598 750 750 893 893 1000>;
>>> };
>> How do you determine the voltage for a frequency on table 2?
>>
>> I'd expect a single property with freq/volt pairs or 2 properties for
>> freq and voltage where there is a 1:1 relationship (freq N uses
>> voltage N).
>
>
> How this will work:
>
> voltage-array =<750 775 800 825 850 875 900 925 950 975 1000 1025
> 1050 1100 1125>
> frequencies-1 =<314 314 314 456 456 456 608 608 608 760 817 817
> 912 1000>;
> frequencies-2 =<598 598 750 750 893 893 1000>;
>
>
> Freq and voltage has 1:1 relationship but as single voltage table is
> used for different processes we have more entries in voltage table
> than freq table.
> Frequency table 1 is mapped till 1100mV while frequency table 2 is
> mapped till 900mV only, it maintains 1:1 relationship.
>
> About repeating frequencies, operating voltage for a frequency would
> be the highest one mapped in the table.
> For example, in frequency table 2 operating voltage for 750MHz would
> be 825mV while for 893MHz it would be 875mV. Unmapped entries could be
> replaced with 0 to make reading better.
>
> Advantage it provides is single voltage table used for multiple
> frequency tables, as can be observed from above tables, operating
> voltage for 314MHz in freq table 1 is 800mV while there is no
> frequency in table 2 at that voltage.
>
> I know this makes reading difficult but it provides flexibility,
>
> I hope it explains the implementation.
>
Does this explanation help?
Regards,
Prashant G
>> Rob
>>
>>> };
>>>
>>> Thanks& Regards,
>>> Prashant G
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
^ permalink raw reply
* dma-buf/fbdev: one-to-many support
From: David Herrmann @ 2012-07-14 14:10 UTC (permalink / raw)
To: dri-devel; +Cc: Sumit Semwal, linux-media, linux-fbdev
Hi
I am currently working on fblog [1] (a replacement for fbcon without
VT dependencies) but this questions does also apply to other fbdev
users. Is there a way to share framebuffers between fbdev devices? I
was thinking especially of USB devices like DisplayLink. If they share
the same screen dimensions it would increase performance a lot if I
could display a single buffer on all the devices instead of copying it
into each framebuffer.
I was told to have a look at the dma-buf framework to implement this.
However, looking at the fbdev dma-buf support I think that this isn't
currently possible. Each fbdev device takes the exporter-role and
provides a single dma-buf object. However, if I wanted to share the
buffers, I would need to be the exporter. Or there needs to be a way
for the fbdev devices to import a dma-buf from other fbdev devices.
I also took a short look at DRM prime support and noticed that it is
capable of importing buffers (or at least it looks like it is).
Therefore, I was wondering whether it does make sense to add an
"import dma-buf" callback to fbdev devices and if the fbdev driver
supports this, I can simply draw to a single dma-buf from one fbdev
device and push it to all other fbdev devices that share the same
dimensions.
It would also be nice to allow multiple buffer-owners or a way to
transfer ownership. That is, if the owner/exporter of the dma-buf
vanishes, I would pass it to another fbdev device which would pick it
up so I don't have to create a new one.
I think this is only interesting for DisplayLink-devices as they are
currently the only way to get a bunch of displays connected to a
single machine. Anyway, if you think that this isn't worth it, I will
probably drop this idea.
Regards
David
[1] fblog kernel driver: http://lwn.net/Articles/505965/
^ permalink raw reply
* [PATCH] fb: epson1355fb: Fix section mismatch
From: Alexander Shiyan @ 2012-07-15 7:32 UTC (permalink / raw)
To: linux-fbdev
This patch fixes "section mismatch" warning in the epson1355fb driver.
WARNING: vmlinux.o(.devinit.text+0x184): Section mismatch in reference from the function epson1355fb_probe() to the function .init.text:fetch_hw_state()
The function __devinit epson1355fb_probe() references
a function __init fetch_hw_state().
If fetch_hw_state is only used by epson1355fb_probe then
annotate fetch_hw_state with a matching annotation.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
drivers/video/epson1355fb.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index a268cbf..68b9b51 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -477,11 +477,11 @@ static __init unsigned int get_fb_size(struct fb_info *info)
return size;
}
-static int epson1355_width_tab[2][4] __initdata +static int epson1355_width_tab[2][4] __devinitdata { {4, 8, 16, -1}, {9, 12, 16, -1} };
-static int epson1355_bpp_tab[8] __initdata = { 1, 2, 4, 8, 15, 16 };
+static int epson1355_bpp_tab[8] __devinitdata = { 1, 2, 4, 8, 15, 16 };
-static void __init fetch_hw_state(struct fb_info *info, struct epson1355_par *par)
+static void __devinit fetch_hw_state(struct fb_info *info, struct epson1355_par *par)
{
struct fb_var_screeninfo *var = &info->var;
struct fb_fix_screeninfo *fix = &info->fix;
@@ -601,7 +601,7 @@ static int epson1355fb_remove(struct platform_device *dev)
return 0;
}
-int __devinit epson1355fb_probe(struct platform_device *dev)
+static int __devinit epson1355fb_probe(struct platform_device *dev)
{
struct epson1355_par *default_par;
struct fb_info *info;
--
1.7.3.4
^ permalink raw reply related
* [PATCH v3 00/11] fblog: Framebuffer kernel log driver v3
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
Hi
This is revision 3 of the fblog driver. This driver is a replacement for fbcon
for systems that do not want/need CONFIG_VT. It simply prints the kernel log to
all connected framebuffers. Previous versions are available here:
v2: http://thread.gmane.org/gmane.linux.serial/8133
v1: http://marc.info/?l=linux-kernel&m\x133988465602225&w=2
This patchset is against linux-next from last week (Wednesday or Thursday).
I've fixed all issues that were reported last week. They were all minor
nitpicks:
- Changed EXPORT_SYMBOL to EXPORT_SYMBOL_GPL for exported fbdev functions
- Removed FBLOG_STR
- Added pr_fmt()
- Fixed two minor coding-style issues
- Fixed one possible subtle deadlock in device registration (switched locking
order)
If you want to test it but don't want to disable CONFIG_VT, simply remove the
dependency to !VT of fblog. This will cause both fblog and fbcon to draw to the
framebuffers but both draw only on changes so it will still be possible to debug
and test fblog.
It would be nice if someone could tell me what tree this will go through or how
I can get it into linux-next as I have no idea who is maintaining fbcon. If
there are other major or minor issues, please tell me so I can work on them.
I am also working on improving the render-path by using dma-buf and partial
redraws like fbcon. Furthermore, I will add a panic-handler so fblog draws
oopses/panics to the framebuffers even though it is disabled. However, I want to
get this basic driver in before making it more complex and making review too
hard.
Thanks! Regards
David
David Herrmann (11):
fbcon: move update_attr() into separate source file
fbcon: move bit_putcs() into separate source file
fblog: new framebuffer kernel log dummy driver
fbdev: export get_fb_info()/put_fb_info()
fblog: register one fblog object per framebuffer
fblog: open fb on registration
fblog: allow selecting fbs via sysfs
fblog: cache framebuffer BLANK and SUSPEND states
fblog: register console driver
fblog: draw console to framebuffers
MAINTAINERS: add fblog entry
MAINTAINERS | 6 +
drivers/video/Kconfig | 5 +-
drivers/video/Makefile | 2 +-
drivers/video/console/Kconfig | 37 ++-
drivers/video/console/Makefile | 4 +-
drivers/video/console/bitblit.c | 149 +--------
drivers/video/console/fbcon.h | 5 +-
drivers/video/console/fbdraw.c | 171 ++++++++++
drivers/video/console/fbdraw.h | 30 ++
drivers/video/console/fblog.c | 675 ++++++++++++++++++++++++++++++++++++++++
drivers/video/fbmem.c | 6 +-
include/linux/fb.h | 3 +
12 files changed, 935 insertions(+), 158 deletions(-)
create mode 100644 drivers/video/console/fbdraw.c
create mode 100644 drivers/video/console/fbdraw.h
create mode 100644 drivers/video/console/fblog.c
--
1.7.11.2
^ permalink raw reply
* [PATCH v3 01/11] fbcon: move update_attr() into separate source file
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
If we want to use update_attr() independently from fbcon, we need to split
it off from bitblit.c and fbcon.h. Therefore, introduce a new header and
source file (fbdraw.[ch]) which does not depende on vc_* and fbcon_*
structures in any way.
This does not introduce any new code nor does it make the paths deeper,
it simply splits the function off.
The other update_attr() functions (inside the rotation sources) seem
similar but are significantly different and I haven't found a way to merge
them efficiently (which is probably the reason why they are split off
now). Furthermore, I do not intend to use them in the coming code so there
is no need to split them off.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/console/Makefile | 3 ++-
drivers/video/console/bitblit.c | 26 +++--------------------
drivers/video/console/fbcon.h | 5 +----
drivers/video/console/fbdraw.c | 46 +++++++++++++++++++++++++++++++++++++++++
drivers/video/console/fbdraw.h | 26 +++++++++++++++++++++++
5 files changed, 78 insertions(+), 28 deletions(-)
create mode 100644 drivers/video/console/fbdraw.c
create mode 100644 drivers/video/console/fbdraw.h
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index a862e91..9a52226 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -25,7 +25,8 @@ obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
-obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o
+obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o \
+ fbdraw.o
ifeq ($(CONFIG_FB_TILEBLITTING),y)
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o
endif
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 28b1a83..6ec2905 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -22,26 +22,6 @@
/*
* Accelerated handlers.
*/
-static void update_attr(u8 *dst, u8 *src, int attribute,
- struct vc_data *vc)
-{
- int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
- int width = DIV_ROUND_UP(vc->vc_font.width, 8);
- unsigned int cellsize = vc->vc_font.height * width;
- u8 c;
-
- offset = cellsize - (offset * width);
- for (i = 0; i < cellsize; i++) {
- c = src[i];
- if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset)
- c = 0xff;
- if (attribute & FBCON_ATTRIBUTE_BOLD)
- c |= c >> 1;
- if (attribute & FBCON_ATTRIBUTE_REVERSE)
- c = ~c;
- dst[i] = c;
- }
-}
static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
@@ -88,7 +68,7 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
charmask)*cellsize;
if (attr) {
- update_attr(buf, src, attr, vc);
+ fbdraw_update_attr(buf, src, attr, &vc->vc_font);
src = buf;
}
@@ -123,7 +103,7 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
charmask)*cellsize;
if (attr) {
- update_attr(buf, src, attr, vc);
+ fbdraw_update_attr(buf, src, attr, &vc->vc_font);
src = buf;
}
@@ -275,7 +255,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
return;
kfree(ops->cursor_data);
ops->cursor_data = dst;
- update_attr(dst, src, attribute, vc);
+ fbdraw_update_attr(dst, src, attribute, &vc->vc_font);
src = dst;
}
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 6bd2e0c..8623bac 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -16,6 +16,7 @@
#include <linux/vt_kern.h>
#include <asm/io.h>
+#include "fbdraw.h"
#define FBCON_FLAGS_INIT 1
#define FBCON_FLAGS_CURSOR_TIMER 2
@@ -219,10 +220,6 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
extern void fbcon_set_bitops(struct fbcon_ops *ops);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
-#define FBCON_ATTRIBUTE_UNDERLINE 1
-#define FBCON_ATTRIBUTE_REVERSE 2
-#define FBCON_ATTRIBUTE_BOLD 4
-
static inline int real_y(struct display *p, int ypos)
{
int rows = p->vrows;
diff --git a/drivers/video/console/fbdraw.c b/drivers/video/console/fbdraw.c
new file mode 100644
index 0000000..aa18f7e
--- /dev/null
+++ b/drivers/video/console/fbdraw.c
@@ -0,0 +1,46 @@
+/*
+ * Framebuffer helpers for image draw-operations
+ *
+ * Copyright (c) 2004 Antonino Daplas <adaplas @pol.net>
+ * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
+ *
+ * Originally from drivers/video/console/bitblit.c which itself originally is
+ * from the 'accel_*' routines in drivers/video/console/fbcon.c.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/kd.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "fbdraw.h"
+
+void fbdraw_update_attr(u8 *dst, const u8 *src, int attribute,
+ struct console_font *font)
+{
+ int i, offset = (font->height < 10) ? 1 : 2;
+ int width = DIV_ROUND_UP(font->width, 8);
+ unsigned int cellsize = font->height * width;
+ u8 c;
+
+ offset = cellsize - (offset * width);
+ for (i = 0; i < cellsize; i++) {
+ c = src[i];
+ if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset)
+ c = 0xff;
+ if (attribute & FBCON_ATTRIBUTE_BOLD)
+ c |= c >> 1;
+ if (attribute & FBCON_ATTRIBUTE_REVERSE)
+ c = ~c;
+ dst[i] = c;
+ }
+}
+EXPORT_SYMBOL_GPL(fbdraw_update_attr);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Herrmann <dh.herrmann@googlemail.com>");
+MODULE_DESCRIPTION("Framebuffer helpers for image draw-operations");
diff --git a/drivers/video/console/fbdraw.h b/drivers/video/console/fbdraw.h
new file mode 100644
index 0000000..77edd7f
--- /dev/null
+++ b/drivers/video/console/fbdraw.h
@@ -0,0 +1,26 @@
+/*
+ * Framebuffer helpers for image draw-operations
+ *
+ * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef _VIDEO_FBDRAW_H
+#define _VIDEO_FBDRAW_H
+
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/kd.h>
+
+/* fbcon character attributes */
+#define FBCON_ATTRIBUTE_UNDERLINE 1
+#define FBCON_ATTRIBUTE_REVERSE 2
+#define FBCON_ATTRIBUTE_BOLD 4
+
+void fbdraw_update_attr(u8 *dst, const u8 *src, int attribute,
+ struct console_font *font);
+
+#endif /* _VIDEO_FBDRAW_H */
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 02/11] fbcon: move bit_putcs() into separate source file
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
If we want to use font-draw-operations in other modules than fbcon, we
need to split this function off of fbcon headers and sources. This also
makes bit_putcs() totally independent of vc_* and fbcon_* structures.
As scr_read() cannot be called inside of non-fbcon/vt functions, we need
to assemble the buffer before passing it to fbdraw_font(). This slows down
this operations a little bit but my rough benchmark showed that it didn't
really matter. Anyway, if it does, we can still put it into VT_BUF_HAVE_RW
conditions so platforms that don't use it won't be affected. And for other
platforms we can add the buffer to the vc-struct so we can reuse it.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/console/bitblit.c | 127 ++++------------------------------------
drivers/video/console/fbdraw.c | 125 +++++++++++++++++++++++++++++++++++++++
drivers/video/console/fbdraw.h | 4 ++
3 files changed, 139 insertions(+), 117 deletions(-)
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 6ec2905..c5d897b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -54,132 +54,25 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
info->fbops->fb_fillrect(info, ®ion);
}
-static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
- const u16 *s, u32 attr, u32 cnt,
- u32 d_pitch, u32 s_pitch, u32 cellsize,
- struct fb_image *image, u8 *buf, u8 *dst)
-{
- u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
- u32 idx = vc->vc_font.width >> 3;
- u8 *src;
-
- while (cnt--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
-
- if (attr) {
- fbdraw_update_attr(buf, src, attr, &vc->vc_font);
- src = buf;
- }
-
- if (likely(idx = 1))
- __fb_pad_aligned_buffer(dst, d_pitch, src, idx,
- image->height);
- else
- fb_pad_aligned_buffer(dst, d_pitch, src, idx,
- image->height);
-
- dst += s_pitch;
- }
-
- info->fbops->fb_imageblit(info, image);
-}
-
-static inline void bit_putcs_unaligned(struct vc_data *vc,
- struct fb_info *info, const u16 *s,
- u32 attr, u32 cnt, u32 d_pitch,
- u32 s_pitch, u32 cellsize,
- struct fb_image *image, u8 *buf,
- u8 *dst)
-{
- u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
- u32 shift_low = 0, mod = vc->vc_font.width % 8;
- u32 shift_high = 8;
- u32 idx = vc->vc_font.width >> 3;
- u8 *src;
-
- while (cnt--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
-
- if (attr) {
- fbdraw_update_attr(buf, src, attr, &vc->vc_font);
- src = buf;
- }
-
- fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
- image->height, shift_high,
- shift_low, mod);
- shift_low += mod;
- dst += (shift_low >= 8) ? s_pitch : s_pitch - 1;
- shift_low &= 7;
- shift_high = 8 - shift_low;
- }
-
- info->fbops->fb_imageblit(info, image);
-
-}
-
static void bit_putcs(struct vc_data *vc, struct fb_info *info,
const unsigned short *s, int count, int yy, int xx,
int fg, int bg)
{
- struct fb_image image;
- u32 width = DIV_ROUND_UP(vc->vc_font.width, 8);
- u32 cellsize = width * vc->vc_font.height;
- u32 maxcnt = info->pixmap.size/cellsize;
- u32 scan_align = info->pixmap.scan_align - 1;
- u32 buf_align = info->pixmap.buf_align - 1;
- u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
+ u16 *buf;
+ int i;
u32 attribute = get_attribute(info, scr_readw(s));
- u8 *dst, *buf = NULL;
- image.fg_color = fg;
- image.bg_color = bg;
- image.dx = xx * vc->vc_font.width;
- image.dy = yy * vc->vc_font.height;
- image.height = vc->vc_font.height;
- image.depth = 1;
+ buf = kmalloc(sizeof(*buf) * count, GFP_KERNEL);
+ if (!buf)
+ return;
- if (attribute) {
- buf = kmalloc(cellsize, GFP_KERNEL);
- if (!buf)
- return;
- }
-
- while (count) {
- if (count > maxcnt)
- cnt = maxcnt;
- else
- cnt = count;
-
- image.width = vc->vc_font.width * cnt;
- pitch = DIV_ROUND_UP(image.width, 8) + scan_align;
- pitch &= ~scan_align;
- size = pitch * image.height + buf_align;
- size &= ~buf_align;
- dst = fb_get_buffer_offset(info, &info->pixmap, size);
- image.data = dst;
-
- if (!mod)
- bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
- width, cellsize, &image, buf, dst);
- else
- bit_putcs_unaligned(vc, info, s, attribute, cnt,
- pitch, width, cellsize, &image,
- buf, dst);
-
- image.dx += cnt * vc->vc_font.width;
- count -= cnt;
- s += cnt;
- }
+ for (i = 0; i < count; ++i)
+ buf[i] = scr_readw(s++);
- /* buf is always NULL except when in monochrome mode, so in this case
- it's a gain to check buf against NULL even though kfree() handles
- NULL pointers just fine */
- if (unlikely(buf))
- kfree(buf);
+ fbdraw_font(info, &vc->vc_font, vc->vc_hi_font_mask, xx, yy, fg, bg,
+ attribute, buf, count);
+ kfree(buf);
}
static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
diff --git a/drivers/video/console/fbdraw.c b/drivers/video/console/fbdraw.c
index aa18f7e..f7c3da7 100644
--- a/drivers/video/console/fbdraw.c
+++ b/drivers/video/console/fbdraw.c
@@ -41,6 +41,131 @@ void fbdraw_update_attr(u8 *dst, const u8 *src, int attribute,
}
EXPORT_SYMBOL_GPL(fbdraw_update_attr);
+static inline void bit_putcs_aligned(struct fb_info *info, bool hi_font,
+ struct console_font *font, u32 attribute,
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst,
+ const u16 *chars, size_t cnt)
+{
+ u16 charmask = hi_font ? 0x1ff : 0xff;
+ u32 idx = font->width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+ src = font->data + ((*chars++) & charmask) * cellsize;
+
+ if (attribute) {
+ fbdraw_update_attr(buf, src, attribute, font);
+ src = buf;
+ }
+
+ if (likely(idx = 1))
+ __fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+ image->height);
+ else
+ fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+ image->height);
+
+ dst += s_pitch;
+ }
+
+ info->fbops->fb_imageblit(info, image);
+}
+
+static inline void bit_putcs_unaligned(struct fb_info *info, bool hi_font,
+ struct console_font *font, u32 attribute,
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst,
+ const u16 *chars, size_t cnt)
+{
+ u16 charmask = hi_font ? 0x1ff : 0xff;
+ u32 shift_low = 0, mod = font->width % 8;
+ u32 shift_high = 8;
+ u32 idx = font->width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+ src = font->data + ((*chars++) & charmask) * cellsize;
+
+ if (attribute) {
+ fbdraw_update_attr(buf, src, attribute, font);
+ src = buf;
+ }
+
+ fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
+ image->height, shift_high,
+ shift_low, mod);
+ shift_low += mod;
+ dst += (shift_low >= 8) ? s_pitch : s_pitch - 1;
+ shift_low &= 7;
+ shift_high = 8 - shift_low;
+ }
+
+ info->fbops->fb_imageblit(info, image);
+}
+
+void fbdraw_font(struct fb_info *info, struct console_font *font, bool hi_font,
+ unsigned int xpos, unsigned int ypos, int fg, int bg,
+ u32 attribute, const u16 *chars, size_t count)
+{
+ struct fb_image image;
+ u32 width = DIV_ROUND_UP(font->width, 8);
+ u32 cellsize = width * font->height;
+ u32 maxcnt = info->pixmap.size / cellsize;
+ u32 scan_align = info->pixmap.scan_align - 1;
+ u32 buf_align = info->pixmap.buf_align - 1;
+ u32 mod = font->width % 8, cnt, pitch, size;
+ u8 *dst, *buf = NULL;
+
+ image.fg_color = fg;
+ image.bg_color = bg;
+ image.dx = xpos * font->width;
+ image.dy = ypos * font->height;
+ image.height = font->height;
+ image.depth = 1;
+
+ if (attribute) {
+ buf = kmalloc(cellsize, GFP_KERNEL);
+ if (!buf)
+ return;
+ }
+
+ while (count) {
+ if (count > maxcnt)
+ cnt = maxcnt;
+ else
+ cnt = count;
+
+ image.width = font->width * cnt;
+ pitch = DIV_ROUND_UP(image.width, 8) + scan_align;
+ pitch &= ~scan_align;
+ size = pitch * image.height + buf_align;
+ size &= ~buf_align;
+ dst = fb_get_buffer_offset(info, &info->pixmap, size);
+ image.data = dst;
+
+ if (!mod)
+ bit_putcs_aligned(info, hi_font, font, attribute,
+ pitch, width, cellsize, &image, buf,
+ dst, chars, cnt);
+ else
+ bit_putcs_unaligned(info, hi_font, font, attribute,
+ pitch, width, cellsize, &image, buf,
+ dst, chars, cnt);
+
+ image.dx += cnt * font->width;
+ count -= cnt;
+ chars += cnt;
+ }
+
+ /* buf is always NULL except when in monochrome mode, so in this case
+ it's a gain to check buf against NULL even though kfree() handles
+ NULL pointers just fine */
+ if (unlikely(buf))
+ kfree(buf);
+}
+EXPORT_SYMBOL_GPL(fbdraw_font);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Herrmann <dh.herrmann@googlemail.com>");
MODULE_DESCRIPTION("Framebuffer helpers for image draw-operations");
diff --git a/drivers/video/console/fbdraw.h b/drivers/video/console/fbdraw.h
index 77edd7f..b9f1ffa 100644
--- a/drivers/video/console/fbdraw.h
+++ b/drivers/video/console/fbdraw.h
@@ -23,4 +23,8 @@
void fbdraw_update_attr(u8 *dst, const u8 *src, int attribute,
struct console_font *font);
+void fbdraw_font(struct fb_info *info, struct console_font *font, bool hi_font,
+ unsigned int xpos, unsigned int ypos, int fg, int bg,
+ u32 attribute, const u16 *chars, size_t count);
+
#endif /* _VIDEO_FBDRAW_H */
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 03/11] fblog: new framebuffer kernel log dummy driver
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
Fblog displays all kernel log messages on all connected framebuffers. It
replaces fbcon when CONFIG_VT=n is selected. Its main purpose is to debug
boot problems by displaying the whole boot log on the screen. This patch
provides the first dummy module-init/deinit functions.
As it uses all the font and fb functions I placed it in
drivers/video/console. However, this means that we need to move the check
for CONFIG_VT in Makefile/Kconfig from drivers/video into
drivers/video/console as fblog does not depend on CONFIG_VT.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/Kconfig | 5 +----
drivers/video/Makefile | 2 +-
drivers/video/console/Kconfig | 37 +++++++++++++++++++++++++++++--------
drivers/video/console/Makefile | 1 +
drivers/video/console/fblog.c | 41 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 73 insertions(+), 13 deletions(-)
create mode 100644 drivers/video/console/fblog.c
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0217f74..e8fd53d 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2448,10 +2448,7 @@ source "drivers/video/omap/Kconfig"
source "drivers/video/omap2/Kconfig"
source "drivers/video/exynos/Kconfig"
source "drivers/video/backlight/Kconfig"
-
-if VT
- source "drivers/video/console/Kconfig"
-endif
+source "drivers/video/console/Kconfig"
if FB || SGI_NEWPORT_CONSOLE
source "drivers/video/logo/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ee8dafb..9f8a7f0 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -11,7 +11,7 @@ fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
modedb.o fbcvt.o
fb-objs := $(fb-y)
-obj-$(CONFIG_VT) += console/
+obj-y += console/
obj-$(CONFIG_LOGO) += logo/
obj-y += backlight/
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index e2c96d0..7374362 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
config VGA_CONSOLE
bool "VGA text console" if EXPERT || !X86
- depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER)
+ depends on VT && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER)
default y
help
Saying Y here will allow you to use Linux in text mode through a
@@ -45,7 +45,7 @@ config VGACON_SOFT_SCROLLBACK_SIZE
screenfuls of scrollback buffer
config MDA_CONSOLE
- depends on !M68K && !PARISC && ISA
+ depends on VT && !M68K && !PARISC && ISA
tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
---help---
Say Y here if you have an old MDA or monochrome Hercules graphics
@@ -61,14 +61,14 @@ config MDA_CONSOLE
config SGI_NEWPORT_CONSOLE
tristate "SGI Newport Console support"
- depends on SGI_IP22
+ depends on VT && SGI_IP22
help
Say Y here if you want the console on the Newport aka XL graphics
card of your Indy. Most people say Y here.
config DUMMY_CONSOLE
bool
- depends on VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
+ depends on VT && (VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y)
default y
config DUMMY_CONSOLE_COLUMNS
@@ -89,7 +89,7 @@ config DUMMY_CONSOLE_ROWS
config FRAMEBUFFER_CONSOLE
tristate "Framebuffer Console support"
- depends on FB
+ depends on VT && FB
select CRC32
help
Low-level framebuffer-based console driver.
@@ -122,16 +122,37 @@ config FRAMEBUFFER_CONSOLE_ROTATION
config STI_CONSOLE
bool "STI text console"
- depends on PARISC
+ depends on VT && PARISC
default y
help
The STI console is the builtin display/keyboard on HP-PARISC
machines. Say Y here to build support for it into your kernel.
The alternative is to use your primary serial port as a console.
+config FBLOG
+ tristate "Framebuffer Kernel Log Driver"
+ depends on !VT && FB
+ default n
+ help
+ This driver displays all kernel log messages on all connected
+ framebuffers. It is mutually exclusive with CONFIG_FRAMEBUFFER_CONSOLE
+ and CONFIG_VT. It was mainly created for debugging purposes when
+ CONFIG_VT is not selected but you still want kernel boot messages on
+ the screen.
+
+ This driver overwrites all other graphics output on the framebuffer as
+ long as it is active so the kernel log will always be visible. You
+ need to disable this driver via sysfs to be able to start another
+ graphics application.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module will
+ be called fblog.
+
config FONTS
bool "Select compiled-in fonts"
- depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE || FBLOG
help
Say Y here if you would like to use fonts other than the default
your frame buffer console usually use.
@@ -158,7 +179,7 @@ config FONT_8x8
config FONT_8x16
bool "VGA 8x16 font" if FONTS
- depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE || STI_CONSOLE || USB_SISUSBVGA_CON
+ depends on FRAMEBUFFER_CONSOLE || SGI_NEWPORT_CONSOLE || STI_CONSOLE || USB_SISUSBVGA_CON || FBLOG
default y if !SPARC && !FONTS
help
This is the "high resolution" font for the VGA frame buffer (the one
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 9a52226..ec0e155 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -20,6 +20,7 @@ font-objs += $(font-objs-y)
# Each configuration option enables a list of files.
+obj-$(CONFIG_FBLOG) += fblog.o font.o
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c
new file mode 100644
index 0000000..fb39737
--- /dev/null
+++ b/drivers/video/console/fblog.c
@@ -0,0 +1,41 @@
+/*
+ * Framebuffer Kernel Log Driver
+ * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ * Framebuffer Kernel Log
+ * This driver prints the kernel log to all connected display devices. It
+ * replaces CONFIG_VT and cannot run simultaneously with it. It does not provide
+ * any virtual-terminal, though. It should only be used to get kernel boot
+ * messages to debug kernel errors.
+ * Hence, this driver is neither optimized for speed, nor does it provide any
+ * fancy features like colored text output.
+ * This driver forcibly writes to the framebuffer while active, therefore, you
+ * cannot run other graphics applications simultaneously. You need to disable
+ * all fblog instances before running other graphics applications.
+ */
+
+#include <linux/module.h>
+
+static int __init fblog_init(void)
+{
+ return 0;
+}
+
+static void __exit fblog_exit(void)
+{
+}
+
+module_init(fblog_init);
+module_exit(fblog_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Herrmann <dh.herrmann@googlemail.com>");
+MODULE_DESCRIPTION("Framebuffer Kernel Log Driver");
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 04/11] fbdev: export get_fb_info()/put_fb_info()
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
When adding other internal users of the framebuffer subsystem, we need a
way to get references to framebuffers. These two functions already exist
so export them.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/fbmem.c | 6 ++++--
include/linux/fb.h | 3 +++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 0dff12a..1312ba2 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -46,7 +46,7 @@ static DEFINE_MUTEX(registration_lock);
struct fb_info *registered_fb[FB_MAX] __read_mostly;
int num_registered_fb __read_mostly;
-static struct fb_info *get_fb_info(unsigned int idx)
+struct fb_info *get_fb_info(unsigned int idx)
{
struct fb_info *fb_info;
@@ -61,14 +61,16 @@ static struct fb_info *get_fb_info(unsigned int idx)
return fb_info;
}
+EXPORT_SYMBOL_GPL(get_fb_info);
-static void put_fb_info(struct fb_info *fb_info)
+void put_fb_info(struct fb_info *fb_info)
{
if (!atomic_dec_and_test(&fb_info->count))
return;
if (fb_info->fbops->fb_destroy)
fb_info->fbops->fb_destroy(fb_info);
}
+EXPORT_SYMBOL_GPL(put_fb_info);
int lock_fb_info(struct fb_info *info)
{
diff --git a/include/linux/fb.h b/include/linux/fb.h
index ac3f1c6..2d51c0e 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1033,6 +1033,9 @@ static inline void unlock_fb_info(struct fb_info *info)
mutex_unlock(&info->lock);
}
+extern struct fb_info *get_fb_info(unsigned int idx);
+extern void put_fb_info(struct fb_info *fb_info);
+
static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
u8 *src, u32 s_pitch, u32 height)
{
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 05/11] fblog: register one fblog object per framebuffer
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
One fblog object is associated to each registered framebuffer. This way,
we can draw the console to each framebuffer. When a framebuffer driver
unregisters a framebuffer, we also unregister our fblog object. That is,
our lifetime is coupled to the lifetime of the framebuffer. However, this
does not mean that we are always active. On the contrary, we do not even
own a reference to the framebuffer. We don't need it as we are notified
_before_ the last reference is dropped.
However, if other users have a reference to our object, we simply mark it
as dead when the associated framebuffer dies and leave it alone. When the
last reference is dropped, it will be automatically freed.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/console/fblog.c | 195 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 195 insertions(+)
diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c
index fb39737..279f4d8 100644
--- a/drivers/video/console/fblog.c
+++ b/drivers/video/console/fblog.c
@@ -23,15 +23,210 @@
* all fblog instances before running other graphics applications.
*/
+#define pr_fmt(_fmt) KBUILD_MODNAME ": " _fmt
+
+#include <linux/device.h>
+#include <linux/fb.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+
+enum fblog_flags {
+ FBLOG_KILLED,
+};
+
+struct fblog_fb {
+ unsigned long flags;
+ struct fb_info *info;
+ struct device dev;
+};
+
+static DEFINE_MUTEX(fblog_registration_lock);
+static struct fblog_fb *fblog_fbs[FB_MAX];
+
+#define to_fblog_dev(_d) container_of(_d, struct fblog_fb, dev)
+
+/*
+ * fblog framebuffer list
+ * The fblog_fbs[] array contains all currently registered framebuffers. If a
+ * framebuffer is in that list, we always must make sure that we own a reference
+ * to it. If it is added through the notifier callbacks, then this is always
+ * guaranteed.
+ * We are only interested in registered framebuffers. That is, if a driver calls
+ * unregister_framebuffer() we directly unlink it from our list. This guarantees
+ * that the associated fb_info is always valid. However, we might still have
+ * pending users so we mark it as dead so no further framebuffer actions are
+ * done. If the last user then drops a reference, the memory gets freed
+ * automatically.
+ */
+
+static void fblog_release(struct device *dev)
+{
+ struct fblog_fb *fb = to_fblog_dev(dev);
+
+ kfree(fb);
+ module_put(THIS_MODULE);
+}
+
+static void fblog_do_unregister(struct fb_info *info)
+{
+ struct fblog_fb *fb;
+
+ fb = fblog_fbs[info->node];
+ if (!fb || fb->info != info)
+ return;
+
+ fblog_fbs[info->node] = NULL;
+
+ device_del(&fb->dev);
+ put_device(&fb->dev);
+}
+
+static void fblog_do_register(struct fb_info *info, bool force)
+{
+ struct fblog_fb *fb;
+ int ret;
+
+ fb = fblog_fbs[info->node];
+ if (fb && fb->info != info) {
+ if (!force)
+ return;
+
+ fblog_do_unregister(fb->info);
+ }
+
+ fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+ if (!fb)
+ return;
+
+ fb->info = info;
+ __module_get(THIS_MODULE);
+ device_initialize(&fb->dev);
+ fb->dev.class = fb_class;
+ fb->dev.release = fblog_release;
+ dev_set_name(&fb->dev, "fblog%d", info->node);
+ fblog_fbs[info->node] = fb;
+
+ ret = device_add(&fb->dev);
+ if (ret) {
+ fblog_fbs[info->node] = NULL;
+ set_bit(FBLOG_KILLED, &fb->flags);
+ put_device(&fb->dev);
+ return;
+ }
+}
+
+static void fblog_register(struct fb_info *info, bool force)
+{
+ mutex_lock(&fblog_registration_lock);
+ fblog_do_register(info, force);
+ mutex_unlock(&fblog_registration_lock);
+}
+
+static void fblog_unregister(struct fb_info *info)
+{
+ mutex_lock(&fblog_registration_lock);
+ fblog_do_unregister(info);
+ mutex_unlock(&fblog_registration_lock);
+}
+
+static int fblog_event(struct notifier_block *self, unsigned long action,
+ void *data)
+{
+ struct fb_event *event = data;
+ struct fb_info *info = event->info;
+
+ switch(action) {
+ case FB_EVENT_FB_REGISTERED:
+ /* This is called when a low-level system driver registers a new
+ * framebuffer. The registration lock is held but the console
+ * lock might not be held when this is called. */
+ fblog_register(info, true);
+ break;
+ case FB_EVENT_FB_UNREGISTERED:
+ /* This is called when a low-level system driver unregisters a
+ * framebuffer. The registration lock is held but the console
+ * lock might not be held. */
+ fblog_unregister(info);
+ break;
+ }
+
+ return 0;
+}
+
+static void fblog_scan(void)
+{
+ unsigned int i;
+ struct fb_info *info, *tmp;
+
+ for (i = 0; i < FB_MAX; ++i) {
+ info = get_fb_info(i);
+ if (!info || IS_ERR(info))
+ continue;
+
+ fblog_register(info, false);
+
+ /* There is a very subtle race-condition. Even though we might
+ * own a reference to the fb, it may still get unregistered
+ * between our call from get_fb_info() and fblog_register().
+ * Therefore, we simply check whether the same fb still is
+ * registered by calling get_fb_info() again. Only if they
+ * differ we know that it got unregistered, therefore, we
+ * call fblog_unregister() with the old pointer. */
+
+ tmp = get_fb_info(i);
+ if (tmp && !IS_ERR(tmp))
+ put_fb_info(tmp);
+ if (tmp != info)
+ fblog_unregister(info);
+
+ /* Here we either called fblog_unregister() and therefore do not
+ * need any reference to the fb, or we can be sure that the FB
+ * is registered and FB_EVENT_FB_UNREGISTERED will be called
+ * before the last reference is dropped. Hence, we can drop our
+ * reference here. */
+
+ put_fb_info(info);
+ }
+}
+
+static struct notifier_block fblog_notifier = {
+ .notifier_call = fblog_event,
+};
static int __init fblog_init(void)
{
+ int ret;
+
+ ret = fb_register_client(&fblog_notifier);
+ if (ret) {
+ pr_err("cannot register framebuffer notifier\n");
+ return ret;
+ }
+
+ fblog_scan();
+
return 0;
}
static void __exit fblog_exit(void)
{
+ unsigned int i;
+ struct fb_info *info;
+
+ fb_unregister_client(&fblog_notifier);
+
+ /* We scan through the whole registered_fb array here instead of
+ * fblog_fbs because we need to get the device lock _before_ the
+ * fblog-registration-lock. */
+
+ for (i = 0; i < FB_MAX; ++i) {
+ info = get_fb_info(i);
+ if (!info || IS_ERR(info))
+ continue;
+
+ fblog_unregister(info);
+ put_fb_info(info);
+ }
}
module_init(fblog_init);
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 06/11] fblog: open fb on registration
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
This opens the framebuffer upon registration so we can use it for
drawing-operations. On unregistration we close it again.
While opening/closing or accessing the fb in any other way, we must hold
the fb-mutex. However, since the notifiers are often called with the mutex
already held, we cannot lock it _after_ taking the
fblog_registration_lock. Therefore, we require the caller to make sure the
fb-mutex is held.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/console/fblog.c | 94 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 93 insertions(+), 1 deletion(-)
diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c
index 279f4d8..1c526c5 100644
--- a/drivers/video/console/fblog.c
+++ b/drivers/video/console/fblog.c
@@ -32,12 +32,14 @@
enum fblog_flags {
FBLOG_KILLED,
+ FBLOG_OPEN,
};
struct fblog_fb {
unsigned long flags;
struct fb_info *info;
struct device dev;
+ struct mutex lock;
};
static DEFINE_MUTEX(fblog_registration_lock);
@@ -46,6 +48,74 @@ static struct fblog_fb *fblog_fbs[FB_MAX];
#define to_fblog_dev(_d) container_of(_d, struct fblog_fb, dev)
/*
+ * fblog_open/close()
+ * These functions manage access to the underlying framebuffer. While opened, we
+ * have a valid reference to the fb and can use it for drawing operations. When
+ * the fb is unregistered, we drop our reference and close the fb so it can get
+ * deleted properly. We also mark it as dead so no further fblog_open() call
+ * will succeed.
+ * Both functions must be called with the fb->info->lock mutex held! But make
+ * sure to lock it _before_ locking the fblog-registration-lock. Otherwise, we
+ * will dead-lock with fb-registration.
+ */
+
+static int fblog_open(struct fblog_fb *fb)
+{
+ int ret;
+
+ mutex_lock(&fb->lock);
+
+ if (test_bit(FBLOG_KILLED, &fb->flags)) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
+ if (test_bit(FBLOG_OPEN, &fb->flags)) {
+ ret = 0;
+ goto unlock;
+ }
+
+ if (!try_module_get(fb->info->fbops->owner)) {
+ ret = -ENODEV;
+ goto out_killed;
+ }
+
+ if (fb->info->fbops->fb_open && fb->info->fbops->fb_open(fb->info, 0)) {
+ ret = -EIO;
+ goto out_unref;
+ }
+
+ set_bit(FBLOG_OPEN, &fb->flags);
+ mutex_unlock(&fb->lock);
+ return 0;
+
+out_unref:
+ module_put(fb->info->fbops->owner);
+out_killed:
+ set_bit(FBLOG_KILLED, &fb->flags);
+unlock:
+ mutex_unlock(&fb->lock);
+ return ret;
+}
+
+static void fblog_close(struct fblog_fb *fb, bool kill_dev)
+{
+ mutex_lock(&fb->lock);
+
+ if (test_bit(FBLOG_OPEN, &fb->flags)) {
+ if (fb->info->fbops->fb_release)
+ fb->info->fbops->fb_release(fb->info, 0);
+ module_put(fb->info->fbops->owner);
+ clear_bit(FBLOG_OPEN, &fb->flags);
+ }
+
+ if (kill_dev)
+ set_bit(FBLOG_KILLED, &fb->flags);
+
+ mutex_unlock(&fb->lock);
+}
+
+/*
* fblog framebuffer list
* The fblog_fbs[] array contains all currently registered framebuffers. If a
* framebuffer is in that list, we always must make sure that we own a reference
@@ -77,6 +147,7 @@ static void fblog_do_unregister(struct fb_info *info)
fblog_fbs[info->node] = NULL;
+ fblog_close(fb, true);
device_del(&fb->dev);
put_device(&fb->dev);
}
@@ -99,6 +170,7 @@ static void fblog_do_register(struct fb_info *info, bool force)
return;
fb->info = info;
+ mutex_init(&fb->lock);
__module_get(THIS_MODULE);
device_initialize(&fb->dev);
fb->dev.class = fb_class;
@@ -113,6 +185,8 @@ static void fblog_do_register(struct fb_info *info, bool force)
put_device(&fb->dev);
return;
}
+
+ fblog_open(fb);
}
static void fblog_register(struct fb_info *info, bool force)
@@ -134,6 +208,7 @@ static int fblog_event(struct notifier_block *self, unsigned long action,
{
struct fb_event *event = data;
struct fb_info *info = event->info;
+ struct fblog_fb *fb;
switch(action) {
case FB_EVENT_FB_REGISTERED:
@@ -145,8 +220,21 @@ static int fblog_event(struct notifier_block *self, unsigned long action,
case FB_EVENT_FB_UNREGISTERED:
/* This is called when a low-level system driver unregisters a
* framebuffer. The registration lock is held but the console
- * lock might not be held. */
+ * lock might not be held. The fb-lock is not held, either! */
+ mutex_lock(&info->lock);
fblog_unregister(info);
+ mutex_unlock(&info->lock);
+ break;
+ case FB_EVENT_FB_UNBIND:
+ /* Called directly before unregistering an FB. The FB is still
+ * valid here and the registration lock is held but the console
+ * lock might not be held (really?). */
+ mutex_lock(&fblog_registration_lock);
+ fb = fblog_fbs[info->node];
+ mutex_unlock(&fblog_registration_lock);
+
+ if (fb)
+ fblog_close(fb, true);
break;
}
@@ -163,7 +251,9 @@ static void fblog_scan(void)
if (!info || IS_ERR(info))
continue;
+ mutex_lock(&info->lock);
fblog_register(info, false);
+ mutex_unlock(&info->lock);
/* There is a very subtle race-condition. Even though we might
* own a reference to the fb, it may still get unregistered
@@ -224,7 +314,9 @@ static void __exit fblog_exit(void)
if (!info || IS_ERR(info))
continue;
+ mutex_lock(&info->lock);
fblog_unregister(info);
+ mutex_unlock(&info->lock);
put_fb_info(info);
}
}
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 07/11] fblog: allow selecting fbs via sysfs
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
fblog is mainly useful during boot, reboot, panics and maintenance. In all
cases you often want to control which monitors are used for console
output. Moreover, in multi-seat environments it is desireable to reduce
system-overhead by not drawing the console to all framebuffers. Two
mechanisms to select framebuffers for fblog are added:
1) "active" module parameter: This parameter selects whether new
framebuffers are opened automatically. By default this is on, that is, all
framebuffers are automatically used by fblog during boot. By passing
fblog.active=0 you can deactivate this.
The init process can set this to 0 via
/sys/modules/fblog/parameters/active, too. However, this does not affect
already available and used framebuffers in any way.
2) "active" sysfs attribute for each fblog object. Reading this value
returns whether a framebuffer is currently active. Writing it opens/closes
the framebuffer. This allows runtime control which fbs are used. For
instance, init can set these to 0 after bootup.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/console/fblog.c | 53 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c
index 1c526c5..5519f91 100644
--- a/drivers/video/console/fblog.c
+++ b/drivers/video/console/fblog.c
@@ -44,6 +44,7 @@ struct fblog_fb {
static DEFINE_MUTEX(fblog_registration_lock);
static struct fblog_fb *fblog_fbs[FB_MAX];
+static bool active = 1;
#define to_fblog_dev(_d) container_of(_d, struct fblog_fb, dev)
@@ -115,6 +116,40 @@ static void fblog_close(struct fblog_fb *fb, bool kill_dev)
mutex_unlock(&fb->lock);
}
+static ssize_t fblog_dev_active_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct fblog_fb *fb = to_fblog_dev(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ !!test_bit(FBLOG_OPEN, &fb->flags));
+}
+
+static ssize_t fblog_dev_active_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct fblog_fb *fb = to_fblog_dev(dev);
+ unsigned long num;
+ int ret = 0;
+
+ num = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&fb->info->lock);
+ if (num)
+ ret = fblog_open(fb);
+ else
+ fblog_close(fb, false);
+ mutex_unlock(&fb->info->lock);
+
+ return ret ? ret : count;
+}
+
+static DEVICE_ATTR(active, S_IRUGO | S_IWUSR | S_IWGRP, fblog_dev_active_show,
+ fblog_dev_active_store);
+
/*
* fblog framebuffer list
* The fblog_fbs[] array contains all currently registered framebuffers. If a
@@ -148,6 +183,7 @@ static void fblog_do_unregister(struct fb_info *info)
fblog_fbs[info->node] = NULL;
fblog_close(fb, true);
+ device_remove_file(&fb->dev, &dev_attr_active);
device_del(&fb->dev);
put_device(&fb->dev);
}
@@ -156,6 +192,7 @@ static void fblog_do_register(struct fb_info *info, bool force)
{
struct fblog_fb *fb;
int ret;
+ bool do_open = true;
fb = fblog_fbs[info->node];
if (fb && fb->info != info) {
@@ -186,7 +223,18 @@ static void fblog_do_register(struct fb_info *info, bool force)
return;
}
- fblog_open(fb);
+ ret = device_create_file(&fb->dev, &dev_attr_active);
+ if (ret) {
+ pr_err("fblog: cannot create sysfs entry");
+ /* do not open fb if we cannot create control file */
+ do_open = false;
+ }
+
+ if (!active)
+ do_open = false;
+
+ if (do_open)
+ fblog_open(fb);
}
static void fblog_register(struct fb_info *info, bool force)
@@ -321,6 +369,9 @@ static void __exit fblog_exit(void)
}
}
+module_param(active, bool, S_IRUGO | S_IWUSR | S_IWGRP);
+MODULE_PARM_DESC(active, "Activate fblog by default");
+
module_init(fblog_init);
module_exit(fblog_exit);
MODULE_LICENSE("GPL");
--
1.7.11.2
^ permalink raw reply related
* [PATCH v3 08/11] fblog: cache framebuffer BLANK and SUSPEND states
From: David Herrmann @ 2012-07-15 19:04 UTC (permalink / raw)
To: linux-kernel
Cc: Florian Tobias Schandinat, Andrew Morton, Greg Kroah-Hartman,
linux-fbdev, linux-serial, Alan Cox, David Herrmann
In-Reply-To: <1342379086-7583-1-git-send-email-dh.herrmann@googlemail.com>
We must cache these states so we will never draw to the framebuffer while
it is suspended or blanked.
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
---
drivers/video/console/fblog.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c
index 5519f91..9b975bc 100644
--- a/drivers/video/console/fblog.c
+++ b/drivers/video/console/fblog.c
@@ -33,6 +33,8 @@
enum fblog_flags {
FBLOG_KILLED,
FBLOG_OPEN,
+ FBLOG_SUSPENDED,
+ FBLOG_BLANKED,
};
struct fblog_fb {
@@ -257,6 +259,7 @@ static int fblog_event(struct notifier_block *self, unsigned long action,
struct fb_event *event = data;
struct fb_info *info = event->info;
struct fblog_fb *fb;
+ int *blank;
switch(action) {
case FB_EVENT_FB_REGISTERED:
@@ -284,6 +287,44 @@ static int fblog_event(struct notifier_block *self, unsigned long action,
if (fb)
fblog_close(fb, true);
break;
+ case FB_EVENT_SUSPEND:
+ /* This is called when the low-level display driver suspends the
+ * video system. We should not access the video system while it
+ * is suspended. This is called with the console lock held. */
+ mutex_lock(&fblog_registration_lock);
+ fb = fblog_fbs[info->node];
+ mutex_unlock(&fblog_registration_lock);
+
+ if (fb)
+ set_bit(FBLOG_SUSPENDED, &fb->flags);
+ break;
+ case FB_EVENT_RESUME:
+ /* This is called when the low-level display driver resumes
+ * operating. It is called with the console lock held. */
+ mutex_lock(&fblog_registration_lock);
+ fb = fblog_fbs[info->node];
+ mutex_unlock(&fblog_registration_lock);
+
+ if (fb)
+ clear_bit(FBLOG_SUSPENDED, &fb->flags);
+ break;
+ case FB_EVENT_BLANK:
+ /* This gets called _after_ the framebuffer was successfully
+ * blanked. The console-lock is always held while fb_blank is
+ * called and during this callback. */
+ mutex_lock(&fblog_registration_lock);
+ fb = fblog_fbs[info->node];
+ mutex_unlock(&fblog_registration_lock);
+
+ if (!fb)
+ break;
+
+ blank = (int*)event->data;
+ if (*blank = FB_BLANK_UNBLANK)
+ clear_bit(FBLOG_BLANKED, &fb->flags);
+ else
+ set_bit(FBLOG_BLANKED, &fb->flags);
+ break;
}
return 0;
--
1.7.11.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox