* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Archit Taneja @ 2012-02-15 12:13 UTC (permalink / raw)
To: Cousson, Benoit; +Cc: Tomi Valkeinen, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3A809E.3070508@ti.com>
On Tuesday 14 February 2012 09:11 PM, Cousson, Benoit wrote:
> On 2/14/2012 2:30 PM, Archit Taneja wrote:
>> Hi,
>>
>> On Tuesday 14 February 2012 06:45 PM, Tomi Valkeinen wrote:
>>> On Tue, 2012-02-14 at 13:58 +0100, Cousson, Benoit wrote:
>>>> Hi Tomi,
>>>
>>>>> Benoit, do you think we'll get the MODULEMODE mess cleaned up in the
>>>>> hwmod/clk framework at some point, and the drivers could do without
>>>>> these kinds of hacks? =)
>>>>
>>>> The best way to fix that for my point of view is to go to device tree
>>>> or/and to consider the DSS as the parent of all the DSS modules.
>>>> pm_runtime will then always ensure that the parent is enabled before
>>>> any
>>>> of the child are used.
>>>
>>> Ah, right. Sounds fine to me.
>>>
>>> But is that a proper "fix"? Are we sure the MODULEMODE will then always
>>> be handled correctly? Isn't the core problem still there, it just
>>> doesn't happen with the setup anymore?
>>>
>>> I mean, if we have these special requirements regarding MODULEMODE, and
>>> the code doesn't really know about it, would it get broken easily with
>>> restructuring/changes?
>>>
>>> And no, I don't have any clear idea why/how it would break, but I have
>>> just gotten the impression that the MODULEMODE is not handled quite
>>> properly (and so we have these current problems), and having dss_core as
>>> the parent of other dss modules doesn't really fix that in any way.
>>
>> I agree with that.
>>
>> In the current approach, we have multiple platform devices for DSS, and
>> all of them belong to the same clock domain, and the clock domain has
>> just one MODULEMODE bit field.
>>
>> When shutting off a platform device(by calling pm_runtime_put()), hwmod
>> enables/disables MODULEMODE without taking into mind that other active
>> platform devices may still need it. So, for example, if we have 2
>> platform devices, say dss and dispc, and we have code like:
>>
>> dispc_foo()
>> {
>> pm_runtime_get(dispc_pdev);
>> ...
>> ...
>> pm_runtime_put(dispc_pdev);
>> }
>>
>> dss_foo()
>> {
>> pm_runtime_get(dss_pdev);
>> ...
>> ...
>> dispc_foo(); /* MODULEMODE off after this */
>> ...
>> ...
>> pm_runtime_put(dss_pdev);
>> }
>>
>> This will lead to the situation of one platform device disabling
>> MODULEMODE even though other platform devices need it.
>>
>> This may not be resolved in device tree either. We would need to have
>> some use count mechanism for these bits, or attach MODULEMODE only to
>> one platform device, and don't give others control to enable/disable it.
>
> And this is exactly what the pm_runtime will provide. The fmwk already
> handles reference counting.
> Moreover the dev->parent will increment the power.child_count and thus
> ensure that the parent is always enabled if at least one child is active.
>
> By initializing the dev->parent of each DSS modules to the dss_core, it
> will ensure that the power dependency is managed properly.
Yes, a parent/child relation will ensure the required dependencies. It
sounds good!
How do we take care of things in the meanwhile? With the current way of
representing modulemode as a slave clock, the disabling sequence gets
messed up. In arch/arm/mach-omap2/omap_hwmod.c:
static int _disable_clocks(struct omap_hwmod *oh)
{
...
disable mainclk;
disable slave clocks;
...
}
For DSS, mainclk is the DSS_FCLK opt clock, and slave clock is
modulemode bits. We need the opposite sequence to happen here to cleanly
disable DSS.
Any suggestions?
Thanks,
Archit
>
> Regards,
> Benoit
>
>
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Cousson, Benoit @ 2012-02-15 12:35 UTC (permalink / raw)
To: Archit Taneja; +Cc: Tomi Valkeinen, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3B9E8F.1020002@ti.com>
On 2/15/2012 1:01 PM, Archit Taneja wrote:
> On Tuesday 14 February 2012 09:11 PM, Cousson, Benoit wrote:
>> On 2/14/2012 2:30 PM, Archit Taneja wrote:
>>> Hi,
>>>
>>> On Tuesday 14 February 2012 06:45 PM, Tomi Valkeinen wrote:
>>>> On Tue, 2012-02-14 at 13:58 +0100, Cousson, Benoit wrote:
>>>>> Hi Tomi,
>>>>
>>>>>> Benoit, do you think we'll get the MODULEMODE mess cleaned up in the
>>>>>> hwmod/clk framework at some point, and the drivers could do without
>>>>>> these kinds of hacks? =)
>>>>>
>>>>> The best way to fix that for my point of view is to go to device tree
>>>>> or/and to consider the DSS as the parent of all the DSS modules.
>>>>> pm_runtime will then always ensure that the parent is enabled before
>>>>> any
>>>>> of the child are used.
>>>>
>>>> Ah, right. Sounds fine to me.
>>>>
>>>> But is that a proper "fix"? Are we sure the MODULEMODE will then always
>>>> be handled correctly? Isn't the core problem still there, it just
>>>> doesn't happen with the setup anymore?
>>>>
>>>> I mean, if we have these special requirements regarding MODULEMODE, and
>>>> the code doesn't really know about it, would it get broken easily with
>>>> restructuring/changes?
>>>>
>>>> And no, I don't have any clear idea why/how it would break, but I have
>>>> just gotten the impression that the MODULEMODE is not handled quite
>>>> properly (and so we have these current problems), and having
>>>> dss_core as
>>>> the parent of other dss modules doesn't really fix that in any way.
>>>
>>> I agree with that.
>>>
>>> In the current approach, we have multiple platform devices for DSS, and
>>> all of them belong to the same clock domain, and the clock domain has
>>> just one MODULEMODE bit field.
>>>
>>> When shutting off a platform device(by calling pm_runtime_put()), hwmod
>>> enables/disables MODULEMODE without taking into mind that other active
>>> platform devices may still need it. So, for example, if we have 2
>>> platform devices, say dss and dispc, and we have code like:
>>>
>>> dispc_foo()
>>> {
>>> pm_runtime_get(dispc_pdev);
>>> ...
>>> ...
>>> pm_runtime_put(dispc_pdev);
>>> }
>>>
>>> dss_foo()
>>> {
>>> pm_runtime_get(dss_pdev);
>>> ...
>>> ...
>>> dispc_foo(); /* MODULEMODE off after this */
>>> ...
>>> ...
>>> pm_runtime_put(dss_pdev);
>>> }
>>>
>>> This will lead to the situation of one platform device disabling
>>> MODULEMODE even though other platform devices need it.
>>>
>>> This may not be resolved in device tree either. We would need to have
>>> some use count mechanism for these bits, or attach MODULEMODE only to
>>> one platform device, and don't give others control to enable/disable it.
>>
>> And this is exactly what the pm_runtime will provide. The fmwk already
>> handles reference counting.
>> Moreover the dev->parent will increment the power.child_count and thus
>> ensure that the parent is always enabled if at least one child is active.
>>
>> By initializing the dev->parent of each DSS modules to the dss_core, it
>> will ensure that the power dependency is managed properly.
>
> Yes, a parent/child relation will ensure the required dependencies. It
> sounds good!
>
> How do we take care of things in the meanwhile? With the current way of
> representing modulemode as a slave clock, the disabling sequence gets
> messed up. In arch/arm/mach-omap2/omap_hwmod.c:
>
> static int _disable_clocks(struct omap_hwmod *oh)
> {
> ...
> disable mainclk;
> disable slave clocks;
> ...
> }
>
> For DSS, mainclk is the DSS_FCLK opt clock, and slave clock is
> modulemode bits. We need the opposite sequence to happen here to cleanly
> disable DSS.
Yes, but as you pointed out the current clocks mapping in the DSS is a
hack that should not be done like that in theory.
As soon as the devices can handle the dependency, we will be able to fix
the clock mapping in the hwmod data and handle properly the module mode
only from the dss_core hwmod only.
But I think you have to change the driver first, otherwise it will break
the DSS. We did that hack previously because it was the only way to
enable the DSS properly, knowing that disabling it with that method will
be impossible.
I think that changing the device creation to change the dev->parent
should be pretty straightforward.
Regards,
Benoit
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Tomi Valkeinen @ 2012-02-15 12:51 UTC (permalink / raw)
To: Cousson, Benoit; +Cc: Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3BA6A2.60604@ti.com>
[-- Attachment #1: Type: text/plain, Size: 759 bytes --]
On Wed, 2012-02-15 at 13:35 +0100, Cousson, Benoit wrote:
> I think that changing the device creation to change the dev->parent
> should be pretty straightforward.
That's not possible with the current kernel, right?
We are now using omap_device_build() (in arch/arm/mach-omap2/display.c)
to build the dss devices. Looking at the omap_device.c, the parent will
always forcibly set to omap_device_parent. It'd be nice to be able to
construct the device child-parent relationship the same way with both DT
and non-DT cases.
Or can I create only the dss_core with omap_device_build(), and create
the rest normally with platform device functions, and make dss_core the
parent of the rest? But are the hwmods then handled correctly?
Tomi
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Cousson, Benoit @ 2012-02-15 13:04 UTC (permalink / raw)
To: Tomi Valkeinen, Hilman, Kevin
Cc: Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <1329310317.1892.60.camel@deskari>
+ Kevin
On 2/15/2012 1:51 PM, Tomi Valkeinen wrote:
> On Wed, 2012-02-15 at 13:35 +0100, Cousson, Benoit wrote:
>
>> I think that changing the device creation to change the dev->parent
>> should be pretty straightforward.
>
> That's not possible with the current kernel, right?
>
> We are now using omap_device_build() (in arch/arm/mach-omap2/display.c)
> to build the dss devices. Looking at the omap_device.c, the parent will
> always forcibly set to omap_device_parent. It'd be nice to be able to
> construct the device child-parent relationship the same way with both DT
> and non-DT cases.
I guess this should not be needed anymore since now the whole PM runtime
stuff is handled using pm_domain.
int omap_device_register(struct platform_device *pdev)
{
pr_debug("omap_device: %s: registering\n", pdev->name);
pdev->dev.parent = &omap_device_parent;
pdev->dev.pm_domain = &omap_device_pm_domain;
return platform_device_add(pdev);
}
Kevin,
Do we still need to set the dev.parent to omap_device_parent?
I guess the default &platform_bus parent is good enough and potentially
the DSS children should be able to overwrite that.
> Or can I create only the dss_core with omap_device_build(), and create
> the rest normally with platform device functions, and make dss_core the
> parent of the rest? But are the hwmods then handled correctly?
You can, the only issue if you create a regular platform device is that
you will miss the automatic pm_runtime support along with the hwmod
device creation mechanism + clock / PM.
I think we can add an extra parameter to allow changing the omap_device
parent during omap_device_build.
Regards,
Benoit
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Kevin Hilman @ 2012-02-15 19:59 UTC (permalink / raw)
To: Cousson, Benoit
Cc: Tomi Valkeinen, Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3BAD41.1020102@ti.com>
"Cousson, Benoit" <b-cousson@ti.com> writes:
> + Kevin
>
> On 2/15/2012 1:51 PM, Tomi Valkeinen wrote:
>> On Wed, 2012-02-15 at 13:35 +0100, Cousson, Benoit wrote:
>>
>>> I think that changing the device creation to change the dev->parent
>>> should be pretty straightforward.
>>
>> That's not possible with the current kernel, right?
>>
>> We are now using omap_device_build() (in arch/arm/mach-omap2/display.c)
>> to build the dss devices. Looking at the omap_device.c, the parent will
>> always forcibly set to omap_device_parent. It'd be nice to be able to
>> construct the device child-parent relationship the same way with both DT
>> and non-DT cases.
>
> I guess this should not be needed anymore since now the whole PM
> runtime stuff is handled using pm_domain.
>
> int omap_device_register(struct platform_device *pdev)
> {
> pr_debug("omap_device: %s: registering\n", pdev->name);
>
> pdev->dev.parent = &omap_device_parent;
> pdev->dev.pm_domain = &omap_device_pm_domain;
> return platform_device_add(pdev);
> }
>
>
> Kevin,
>
> Do we still need to set the dev.parent to omap_device_parent?
Nope.
> I guess the default &platform_bus parent is good enough and
> potentially the DSS children should be able to overwrite that.
Yes, now that we use PM domains, we don't need it. I just sent a patch
to remove omap_device_parent.
Kevin
>> Or can I create only the dss_core with omap_device_build(), and create
>> the rest normally with platform device functions, and make dss_core the
>> parent of the rest? But are the hwmods then handled correctly?
>
> You can, the only issue if you create a regular platform device is
> that you will miss the automatic pm_runtime support along with the
> hwmod device creation mechanism + clock / PM.
>
> I think we can add an extra parameter to allow changing the
> omap_device parent during omap_device_build.
^ permalink raw reply
* Re: [PATCH v5] [resend] Resurrect Intel740 driver: i740fb
From: Florian Tobias Schandinat @ 2012-02-16 1:23 UTC (permalink / raw)
To: Ondrej Zary
Cc: linux-fbdev, Andrey Ulanov, Paul Mundt, Kernel development list
In-Reply-To: <201202101859.27975.linux@rainbow-software.org>
On 02/10/2012 05:59 PM, Ondrej Zary wrote:
> This is a resurrection of an old (like 2.4.19) out-of-tree driver for
> Intel740 graphics cards and adaptation for recent kernels. The old driver by
> Andrey Ulanov is located at: http://sourceforge.net/projects/i740fbdev/files/
>
> This is a new driver based on skeletonfb, using most of the low level HW code
> from the old driver. The DDC code is completely new.
>
> The driver was tested on two 8MB cards: Protac AG240D and Diamond Stealth II
> G460.
>
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Applied. Just for the record, checkpatch complained about
WARNING: simple_strtoul is obsolete, use kstrtoul instead
#1384: FILE: drivers/video/i740fb.c:1296:
+ mtrr = simple_strtoul(opt + 5, NULL, 0);
Feel free to send another patch to fix it, if you like.
Thanks,
Florian Tobias Schandinat
> ---
> Changes in v5:
> - fixed checkpatch problems
> - added Kconfig dependency on FB_DDC
> - cleaned up i740_calc_vclk()
> - fixed SDRAM/SGRAM detection
> - fixed wrong colors in 16bpp mode when neither 555 nor 565 specified
>
> --- linux-3.2.1-orig/drivers/video/Kconfig 2012-01-12 20:42:45.000000000 +0100
> +++ linux-3.2.1/drivers/video/Kconfig 2012-01-23 20:52:32.000000000 +0100
> @@ -1123,6 +1123,18 @@ config FB_RIVA_BACKLIGHT
> help
> Say Y here if you want to control the backlight of your display.
>
> +config FB_I740
> + tristate "Intel740 support (EXPERIMENTAL)"
> + depends on EXPERIMENTAL && FB && PCI
> + select FB_MODE_HELPERS
> + select FB_CFB_FILLRECT
> + select FB_CFB_COPYAREA
> + select FB_CFB_IMAGEBLIT
> + select VGASTATE
> + select FB_DDC
> + help
> + This driver supports graphics cards based on Intel740 chip.
> +
> config FB_I810
> tristate "Intel 810/815 support (EXPERIMENTAL)"
> depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
> --- linux-3.2.1-orig/drivers/video/Makefile 2012-01-12 20:42:45.000000000 +0100
> +++ linux-3.2.1/drivers/video/Makefile 2012-01-23 20:52:32.000000000 +0100
> @@ -37,6 +37,7 @@ obj-$(CONFIG_FB_GRVGA) += grv
> obj-$(CONFIG_FB_PM2) += pm2fb.o
> obj-$(CONFIG_FB_PM3) += pm3fb.o
>
> +obj-$(CONFIG_FB_I740) += i740fb.o
> obj-$(CONFIG_FB_MATROX) += matrox/
> obj-$(CONFIG_FB_RIVA) += riva/
> obj-$(CONFIG_FB_NVIDIA) += nvidia/
> --- /dev/null 2012-01-24 00:06:39.330222901 +0100
> +++ linux-3.2.1/drivers/video/i740fb.c 2012-01-24 00:01:54.000000000 +0100
> @@ -0,0 +1,1337 @@
> +/*
> + * i740fb - framebuffer driver for Intel740
> + * Copyright (c) 2011 Ondrej Zary
> + *
> + * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
> + * which was partially based on:
> + * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
> + * and Petr Vandrovec <VANDROVE@vc.cvut.cz>
> + * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
> + * Texas.
> + * i740fb by Patrick LERDA, v0.9
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/fb.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/pci_ids.h>
> +#include <linux/i2c.h>
> +#include <linux/i2c-algo-bit.h>
> +#include <linux/console.h>
> +#include <video/vga.h>
> +
> +#ifdef CONFIG_MTRR
> +#include <asm/mtrr.h>
> +#endif
> +
> +#include "i740_reg.h"
> +
> +static char *mode_option __devinitdata;
> +
> +#ifdef CONFIG_MTRR
> +static int mtrr __devinitdata = 1;
> +#endif
> +
> +struct i740fb_par {
> + unsigned char __iomem *regs;
> + bool has_sgram;
> +#ifdef CONFIG_MTRR
> + int mtrr_reg;
> +#endif
> + bool ddc_registered;
> + struct i2c_adapter ddc_adapter;
> + struct i2c_algo_bit_data ddc_algo;
> + u32 pseudo_palette[16];
> + struct mutex open_lock;
> + unsigned int ref_count;
> +
> + u8 crtc[VGA_CRT_C];
> + u8 atc[VGA_ATT_C];
> + u8 gdc[VGA_GFX_C];
> + u8 seq[VGA_SEQ_C];
> + u8 misc;
> + u8 vss;
> +
> + /* i740 specific registers */
> + u8 display_cntl;
> + u8 pixelpipe_cfg0;
> + u8 pixelpipe_cfg1;
> + u8 pixelpipe_cfg2;
> + u8 video_clk2_m;
> + u8 video_clk2_n;
> + u8 video_clk2_mn_msbs;
> + u8 video_clk2_div_sel;
> + u8 pll_cntl;
> + u8 address_mapping;
> + u8 io_cntl;
> + u8 bitblt_cntl;
> + u8 ext_vert_total;
> + u8 ext_vert_disp_end;
> + u8 ext_vert_sync_start;
> + u8 ext_vert_blank_start;
> + u8 ext_horiz_total;
> + u8 ext_horiz_blank;
> + u8 ext_offset;
> + u8 interlace_cntl;
> + u32 lmi_fifo_watermark;
> + u8 ext_start_addr;
> + u8 ext_start_addr_hi;
> +};
> +
> +#define DACSPEED8 203
> +#define DACSPEED16 163
> +#define DACSPEED24_SG 136
> +#define DACSPEED24_SD 128
> +#define DACSPEED32 86
> +
> +static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
> + .id = "i740fb",
> + .type = FB_TYPE_PACKED_PIXELS,
> + .visual = FB_VISUAL_TRUECOLOR,
> + .xpanstep = 8,
> + .ypanstep = 1,
> + .accel = FB_ACCEL_NONE,
> +};
> +
> +static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
> +{
> + vga_mm_w(par->regs, port, val);
> +}
> +static inline u8 i740inb(struct i740fb_par *par, u16 port)
> +{
> + return vga_mm_r(par->regs, port);
> +}
> +static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
> +{
> + vga_mm_w_fast(par->regs, port, reg, val);
> +}
> +static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
> +{
> + vga_mm_w(par->regs, port, reg);
> + return vga_mm_r(par->regs, port+1);
> +}
> +static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
> + u8 val, u8 mask)
> +{
> + vga_mm_w_fast(par->regs, port, reg, (val & mask)
> + | (i740inreg(par, port, reg) & ~mask));
> +}
> +
> +#define REG_DDC_DRIVE 0x62
> +#define REG_DDC_STATE 0x63
> +#define DDC_SCL (1 << 3)
> +#define DDC_SDA (1 << 2)
> +
> +static void i740fb_ddc_setscl(void *data, int val)
> +{
> + struct i740fb_par *par = data;
> +
> + i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
> + i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
> +}
> +
> +static void i740fb_ddc_setsda(void *data, int val)
> +{
> + struct i740fb_par *par = data;
> +
> + i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
> + i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
> +}
> +
> +static int i740fb_ddc_getscl(void *data)
> +{
> + struct i740fb_par *par = data;
> +
> + i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
> +
> + return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
> +}
> +
> +static int i740fb_ddc_getsda(void *data)
> +{
> + struct i740fb_par *par = data;
> +
> + i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
> +
> + return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
> +}
> +
> +static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
> +{
> + struct i740fb_par *par = info->par;
> +
> + strlcpy(par->ddc_adapter.name, info->fix.id,
> + sizeof(par->ddc_adapter.name));
> + par->ddc_adapter.owner = THIS_MODULE;
> + par->ddc_adapter.class = I2C_CLASS_DDC;
> + par->ddc_adapter.algo_data = &par->ddc_algo;
> + par->ddc_adapter.dev.parent = info->device;
> + par->ddc_algo.setsda = i740fb_ddc_setsda;
> + par->ddc_algo.setscl = i740fb_ddc_setscl;
> + par->ddc_algo.getsda = i740fb_ddc_getsda;
> + par->ddc_algo.getscl = i740fb_ddc_getscl;
> + par->ddc_algo.udelay = 10;
> + par->ddc_algo.timeout = 20;
> + par->ddc_algo.data = par;
> +
> + i2c_set_adapdata(&par->ddc_adapter, par);
> +
> + return i2c_bit_add_bus(&par->ddc_adapter);
> +}
> +
> +static int i740fb_open(struct fb_info *info, int user)
> +{
> + struct i740fb_par *par = info->par;
> +
> + mutex_lock(&(par->open_lock));
> + par->ref_count++;
> + mutex_unlock(&(par->open_lock));
> +
> + return 0;
> +}
> +
> +static int i740fb_release(struct fb_info *info, int user)
> +{
> + struct i740fb_par *par = info->par;
> +
> + mutex_lock(&(par->open_lock));
> + if (par->ref_count = 0) {
> + printk(KERN_ERR "fb%d: release called with zero refcount\n",
> + info->node);
> + mutex_unlock(&(par->open_lock));
> + return -EINVAL;
> + }
> +
> + par->ref_count--;
> + mutex_unlock(&(par->open_lock));
> +
> + return 0;
> +}
> +
> +static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
> +{
> + /*
> + * Would like to calculate these values automatically, but a generic
> + * algorithm does not seem possible. Note: These FIFO water mark
> + * values were tested on several cards and seem to eliminate the
> + * all of the snow and vertical banding, but fine adjustments will
> + * probably be required for other cards.
> + */
> +
> + u32 wm;
> +
> + switch (bpp) {
> + case 8:
> + if (freq > 200)
> + wm = 0x18120000;
> + else if (freq > 175)
> + wm = 0x16110000;
> + else if (freq > 135)
> + wm = 0x120E0000;
> + else
> + wm = 0x100D0000;
> + break;
> + case 15:
> + case 16:
> + if (par->has_sgram) {
> + if (freq > 140)
> + wm = 0x2C1D0000;
> + else if (freq > 120)
> + wm = 0x2C180000;
> + else if (freq > 100)
> + wm = 0x24160000;
> + else if (freq > 90)
> + wm = 0x18120000;
> + else if (freq > 50)
> + wm = 0x16110000;
> + else if (freq > 32)
> + wm = 0x13100000;
> + else
> + wm = 0x120E0000;
> + } else {
> + if (freq > 160)
> + wm = 0x28200000;
> + else if (freq > 140)
> + wm = 0x2A1E0000;
> + else if (freq > 130)
> + wm = 0x2B1A0000;
> + else if (freq > 120)
> + wm = 0x2C180000;
> + else if (freq > 100)
> + wm = 0x24180000;
> + else if (freq > 90)
> + wm = 0x18120000;
> + else if (freq > 50)
> + wm = 0x16110000;
> + else if (freq > 32)
> + wm = 0x13100000;
> + else
> + wm = 0x120E0000;
> + }
> + break;
> + case 24:
> + if (par->has_sgram) {
> + if (freq > 130)
> + wm = 0x31200000;
> + else if (freq > 120)
> + wm = 0x2E200000;
> + else if (freq > 100)
> + wm = 0x2C1D0000;
> + else if (freq > 80)
> + wm = 0x25180000;
> + else if (freq > 64)
> + wm = 0x24160000;
> + else if (freq > 49)
> + wm = 0x18120000;
> + else if (freq > 32)
> + wm = 0x16110000;
> + else
> + wm = 0x13100000;
> + } else {
> + if (freq > 120)
> + wm = 0x311F0000;
> + else if (freq > 100)
> + wm = 0x2C1D0000;
> + else if (freq > 80)
> + wm = 0x25180000;
> + else if (freq > 64)
> + wm = 0x24160000;
> + else if (freq > 49)
> + wm = 0x18120000;
> + else if (freq > 32)
> + wm = 0x16110000;
> + else
> + wm = 0x13100000;
> + }
> + break;
> + case 32:
> + if (par->has_sgram) {
> + if (freq > 80)
> + wm = 0x2A200000;
> + else if (freq > 60)
> + wm = 0x281A0000;
> + else if (freq > 49)
> + wm = 0x25180000;
> + else if (freq > 32)
> + wm = 0x18120000;
> + else
> + wm = 0x16110000;
> + } else {
> + if (freq > 80)
> + wm = 0x29200000;
> + else if (freq > 60)
> + wm = 0x281A0000;
> + else if (freq > 49)
> + wm = 0x25180000;
> + else if (freq > 32)
> + wm = 0x18120000;
> + else
> + wm = 0x16110000;
> + }
> + break;
> + }
> +
> + return wm;
> +}
> +
> +/* clock calculation from i740fb by Patrick LERDA */
> +
> +#define I740_RFREQ 1000000
> +#define TARGET_MAX_N 30
> +#define I740_FFIX (1 << 8)
> +#define I740_RFREQ_FIX (I740_RFREQ / I740_FFIX)
> +#define I740_REF_FREQ (6667 * I740_FFIX / 100) /* 66.67 MHz */
> +#define I740_MAX_VCO_FREQ (450 * I740_FFIX) /* 450 MHz */
> +
> +static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
> +{
> + const u32 err_max = freq / (200 * I740_RFREQ / I740_FFIX);
> + const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
> + u32 err_best = 512 * I740_FFIX;
> + u32 f_err, f_vco;
> + int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
> + int m, n;
> +
> + p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
> + d_best = 0;
> + f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
> + freq = freq / I740_RFREQ_FIX;
> +
> + n = 2;
> + do {
> + n++;
> + m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
> +
> + if (m < 3)
> + m = 3;
> +
> + {
> + u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
> + / n) + ((1 << p_best) / 2)) / (1 << p_best);
> +
> + f_err = (freq - f_out);
> +
> + if (abs(f_err) < err_max) {
> + m_best = m;
> + n_best = n;
> + err_best = f_err;
> + }
> + }
> + } while ((abs(f_err) >= err_target) &&
> + ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
> +
> + if (abs(f_err) < err_target) {
> + m_best = m;
> + n_best = n;
> + }
> +
> + par->video_clk2_m = (m_best - 2) & 0xFF;
> + par->video_clk2_n = (n_best - 2) & 0xFF;
> + par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
> + | (((m_best - 2) >> 8) & VCO_M_MSBS));
> + par->video_clk2_div_sel > + ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
> +}
> +
> +static int i740fb_decode_var(const struct fb_var_screeninfo *var,
> + struct i740fb_par *par, struct fb_info *info)
> +{
> + /*
> + * Get the video params out of 'var'.
> + * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
> + */
> +
> + u32 xres, right, hslen, left, xtotal;
> + u32 yres, lower, vslen, upper, ytotal;
> + u32 vxres, xoffset, vyres, yoffset;
> + u32 bpp, base, dacspeed24, mem;
> + u8 r7;
> + int i;
> +
> + dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
> + var->xres, var->yres, var->xres_virtual, var->xres_virtual);
> + dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
> + var->xoffset, var->yoffset, var->bits_per_pixel,
> + var->grayscale);
> + dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
> + var->activate, var->nonstd, var->vmode);
> + dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
> + var->pixclock, var->hsync_len, var->vsync_len);
> + dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
> + var->left_margin, var->right_margin, var->upper_margin,
> + var->lower_margin);
> +
> +
> + bpp = var->bits_per_pixel;
> + switch (bpp) {
> + case 1 ... 8:
> + bpp = 8;
> + if ((1000000 / var->pixclock) > DACSPEED8) {
> + dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
> + 1000000 / var->pixclock, DACSPEED8);
> + return -EINVAL;
> + }
> + break;
> + case 9 ... 15:
> + bpp = 15;
> + case 16:
> + if ((1000000 / var->pixclock) > DACSPEED16) {
> + dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
> + 1000000 / var->pixclock, DACSPEED16);
> + return -EINVAL;
> + }
> + break;
> + case 17 ... 24:
> + bpp = 24;
> + dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
> + if ((1000000 / var->pixclock) > dacspeed24) {
> + dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
> + 1000000 / var->pixclock, dacspeed24);
> + return -EINVAL;
> + }
> + break;
> + case 25 ... 32:
> + bpp = 32;
> + if ((1000000 / var->pixclock) > DACSPEED32) {
> + dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
> + 1000000 / var->pixclock, DACSPEED32);
> + return -EINVAL;
> + }
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + xres = ALIGN(var->xres, 8);
> + vxres = ALIGN(var->xres_virtual, 16);
> + if (vxres < xres)
> + vxres = xres;
> +
> + xoffset = ALIGN(var->xoffset, 8);
> + if (xres + xoffset > vxres)
> + xoffset = vxres - xres;
> +
> + left = ALIGN(var->left_margin, 8);
> + right = ALIGN(var->right_margin, 8);
> + hslen = ALIGN(var->hsync_len, 8);
> +
> + yres = var->yres;
> + vyres = var->yres_virtual;
> + if (yres > vyres)
> + vyres = yres;
> +
> + yoffset = var->yoffset;
> + if (yres + yoffset > vyres)
> + yoffset = vyres - yres;
> +
> + lower = var->lower_margin;
> + vslen = var->vsync_len;
> + upper = var->upper_margin;
> +
> + mem = vxres * vyres * ((bpp + 1) / 8);
> + if (mem > info->screen_size) {
> + dev_err(info->device, "not enough video memory (%d KB requested, %ld KB avaliable)\n",
> + mem >> 10, info->screen_size >> 10);
> + return -ENOMEM;
> + }
> +
> + if (yoffset + yres > vyres)
> + yoffset = vyres - yres;
> +
> + xtotal = xres + right + hslen + left;
> + ytotal = yres + lower + vslen + upper;
> +
> + par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
> + par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
> + par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
> + par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
> + par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
> + | ((((xres + right + hslen) >> 3) & 0x20) << 2);
> + par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
> + | 0x80;
> +
> + par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
> +
> + r7 = 0x10; /* disable linecompare */
> + if (ytotal & 0x100)
> + r7 |= 0x01;
> + if (ytotal & 0x200)
> + r7 |= 0x20;
> +
> + par->crtc[VGA_CRTC_PRESET_ROW] = 0;
> + par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
> + if (var->vmode & FB_VMODE_DOUBLE)
> + par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
> + par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
> + par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
> + par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
> + par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
> + par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
> + if ((yres-1) & 0x100)
> + r7 |= 0x02;
> + if ((yres-1) & 0x200)
> + r7 |= 0x40;
> +
> + par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
> + par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
> + if ((yres + lower - 1) & 0x100)
> + r7 |= 0x0C;
> + if ((yres + lower - 1) & 0x200) {
> + par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
> + r7 |= 0x80;
> + }
> +
> + /* disabled IRQ */
> + par->crtc[VGA_CRTC_V_SYNC_END] > + ((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
> + /* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
> + par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
> +
> + par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
> + par->crtc[VGA_CRTC_MODE] = 0xC3 ;
> + par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
> + par->crtc[VGA_CRTC_OVERFLOW] = r7;
> +
> + par->vss = 0x00; /* 3DA */
> +
> + for (i = 0x00; i < 0x10; i++)
> + par->atc[i] = i;
> + par->atc[VGA_ATC_MODE] = 0x81;
> + par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
> + par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
> + par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
> +
> + par->misc = 0xC3;
> + if (var->sync & FB_SYNC_HOR_HIGH_ACT)
> + par->misc &= ~0x40;
> + if (var->sync & FB_SYNC_VERT_HIGH_ACT)
> + par->misc &= ~0x80;
> +
> + par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
> + par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
> + par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
> + par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
> +
> + par->gdc[VGA_GFX_SR_VALUE] = 0x00;
> + par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
> + par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
> + par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
> + par->gdc[VGA_GFX_PLANE_READ] = 0;
> + par->gdc[VGA_GFX_MODE] = 0x02;
> + par->gdc[VGA_GFX_MISC] = 0x05;
> + par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
> + par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
> +
> + base = (yoffset * vxres + (xoffset & ~7)) >> 2;
> + switch (bpp) {
> + case 8:
> + par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
> + par->ext_offset = vxres >> 11;
> + par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
> + par->bitblt_cntl = COLEXP_8BPP;
> + break;
> + case 15: /* 0rrrrrgg gggbbbbb */
> + case 16: /* rrrrrggg gggbbbbb */
> + par->pixelpipe_cfg1 = (var->green.length = 6) ?
> + DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
> + par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
> + par->ext_offset = vxres >> 10;
> + par->bitblt_cntl = COLEXP_16BPP;
> + base *= 2;
> + break;
> + case 24:
> + par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
> + par->ext_offset = (vxres * 3) >> 11;
> + par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
> + par->bitblt_cntl = COLEXP_24BPP;
> + base &= 0xFFFFFFFE; /* ...ignore the last bit. */
> + base *= 3;
> + break;
> + case 32:
> + par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
> + par->ext_offset = vxres >> 9;
> + par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
> + par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
> + base *= 4;
> + break;
> + }
> +
> + par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
> + par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
> + par->ext_start_addr > + ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
> + par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
> +
> + par->pixelpipe_cfg0 = DAC_8_BIT;
> +
> + par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
> + par->io_cntl = EXTENDED_CRTC_CNTL;
> + par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
> + par->display_cntl = HIRES_MODE;
> +
> + /* Set the MCLK freq */
> + par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
> +
> + /* Calculate the extended CRTC regs */
> + par->ext_vert_total = (ytotal - 2) >> 8;
> + par->ext_vert_disp_end = (yres - 1) >> 8;
> + par->ext_vert_sync_start = (yres + lower) >> 8;
> + par->ext_vert_blank_start = (yres + lower) >> 8;
> + par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
> + par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
> +
> + par->interlace_cntl = INTERLACE_DISABLE;
> +
> + /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
> + par->atc[VGA_ATC_OVERSCAN] = 0;
> +
> + /* Calculate VCLK that most closely matches the requested dot clock */
> + i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
> +
> + /* Since we program the clocks ourselves, always use VCLK2. */
> + par->misc |= 0x0C;
> +
> + /* Calculate the FIFO Watermark and Burst Length. */
> + par->lmi_fifo_watermark > + i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
> +
> + return 0;
> +}
> +
> +static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
> +{
> + switch (var->bits_per_pixel) {
> + case 8:
> + var->red.offset = var->green.offset = var->blue.offset = 0;
> + var->red.length = var->green.length = var->blue.length = 8;
> + break;
> + case 16:
> + switch (var->green.length) {
> + default:
> + case 5:
> + var->red.offset = 10;
> + var->green.offset = 5;
> + var->blue.offset = 0;
> + var->red.length = 5;
> + var->green.length = 5;
> + var->blue.length = 5;
> + break;
> + case 6:
> + var->red.offset = 11;
> + var->green.offset = 5;
> + var->blue.offset = 0;
> + var->red.length = var->blue.length = 5;
> + break;
> + }
> + break;
> + case 24:
> + var->red.offset = 16;
> + var->green.offset = 8;
> + var->blue.offset = 0;
> + var->red.length = var->green.length = var->blue.length = 8;
> + break;
> + case 32:
> + var->transp.offset = 24;
> + var->red.offset = 16;
> + var->green.offset = 8;
> + var->blue.offset = 0;
> + var->transp.length = 8;
> + var->red.length = var->green.length = var->blue.length = 8;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + if (var->xres > var->xres_virtual)
> + var->xres_virtual = var->xres;
> +
> + if (var->yres > var->yres_virtual)
> + var->yres_virtual = var->yres;
> +
> + if (info->monspecs.hfmax && info->monspecs.vfmax &&
> + info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static void vga_protect(struct i740fb_par *par)
> +{
> + /* disable the display */
> + i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
> +
> + i740inb(par, 0x3DA);
> + i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
> +}
> +
> +static void vga_unprotect(struct i740fb_par *par)
> +{
> + /* reenable display */
> + i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
> +
> + i740inb(par, 0x3DA);
> + i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
> +}
> +
> +static int i740fb_set_par(struct fb_info *info)
> +{
> + struct i740fb_par *par = info->par;
> + u32 itemp;
> + int i;
> +
> + i = i740fb_decode_var(&info->var, par, info);
> + if (i)
> + return i;
> +
> + memset(info->screen_base, 0, info->screen_size);
> +
> + vga_protect(par);
> +
> + i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
> +
> + mdelay(1);
> +
> + i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
> + i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
> + i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
> + i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
> +
> + i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
> + par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
> +
> + i740inb(par, 0x3DA);
> + i740outb(par, 0x3C0, 0x00);
> +
> + /* update misc output register */
> + i740outb(par, VGA_MIS_W, par->misc | 0x01);
> +
> + /* synchronous reset on */
> + i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
> + /* write sequencer registers */
> + i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
> + par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
> + for (i = 2; i < VGA_SEQ_C; i++)
> + i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
> +
> + /* synchronous reset off */
> + i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
> +
> + /* deprotect CRT registers 0-7 */
> + i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
> + par->crtc[VGA_CRTC_V_SYNC_END]);
> +
> + /* write CRT registers */
> + for (i = 0; i < VGA_CRT_C; i++)
> + i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
> +
> + /* write graphics controller registers */
> + for (i = 0; i < VGA_GFX_C; i++)
> + i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
> +
> + /* write attribute controller registers */
> + for (i = 0; i < VGA_ATT_C; i++) {
> + i740inb(par, VGA_IS1_RC); /* reset flip-flop */
> + i740outb(par, VGA_ATT_IW, i);
> + i740outb(par, VGA_ATT_IW, par->atc[i]);
> + }
> +
> + i740inb(par, VGA_IS1_RC);
> + i740outb(par, VGA_ATT_IW, 0x20);
> +
> + i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
> + i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
> + i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
> + par->ext_vert_sync_start);
> + i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
> + par->ext_vert_blank_start);
> + i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
> + i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
> + i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
> + i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
> + i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
> +
> + i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
> + par->interlace_cntl, INTERLACE_ENABLE);
> + i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
> + i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
> + i740outreg_mask(par, XRX, DISPLAY_CNTL,
> + par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
> + i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
> + i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
> +
> + i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
> +
> + i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
> + par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
> +
> + itemp = readl(par->regs + FWATER_BLC);
> + itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
> + itemp |= par->lmi_fifo_watermark;
> + writel(itemp, par->regs + FWATER_BLC);
> +
> + i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
> +
> + i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
> + i740outreg_mask(par, XRX, IO_CTNL,
> + par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
> +
> + if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
> + i740outb(par, VGA_PEL_MSK, 0xFF);
> + i740outb(par, VGA_PEL_IW, 0x00);
> + for (i = 0; i < 256; i++) {
> + itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
> + i740outb(par, VGA_PEL_D, itemp);
> + i740outb(par, VGA_PEL_D, itemp);
> + i740outb(par, VGA_PEL_D, itemp);
> + }
> + }
> +
> + /* Wait for screen to stabilize. */
> + mdelay(50);
> + vga_unprotect(par);
> +
> + info->fix.line_length > + info->var.xres_virtual * info->var.bits_per_pixel / 8;
> + if (info->var.bits_per_pixel = 8)
> + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
> + else
> + info->fix.visual = FB_VISUAL_TRUECOLOR;
> +
> + return 0;
> +}
> +
> +static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
> + unsigned blue, unsigned transp,
> + struct fb_info *info)
> +{
> + u32 r, g, b;
> +
> + dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
> + regno, red, green, blue, transp, info->var.bits_per_pixel);
> +
> + switch (info->fix.visual) {
> + case FB_VISUAL_PSEUDOCOLOR:
> + if (regno >= 256)
> + return -EINVAL;
> + i740outb(info->par, VGA_PEL_IW, regno);
> + i740outb(info->par, VGA_PEL_D, red >> 8);
> + i740outb(info->par, VGA_PEL_D, green >> 8);
> + i740outb(info->par, VGA_PEL_D, blue >> 8);
> + break;
> + case FB_VISUAL_TRUECOLOR:
> + if (regno >= 16)
> + return -EINVAL;
> + r = (red >> (16 - info->var.red.length))
> + << info->var.red.offset;
> + b = (blue >> (16 - info->var.blue.length))
> + << info->var.blue.offset;
> + g = (green >> (16 - info->var.green.length))
> + << info->var.green.offset;
> + ((u32 *) info->pseudo_palette)[regno] = r | g | b;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int i740fb_pan_display(struct fb_var_screeninfo *var,
> + struct fb_info *info)
> +{
> + struct i740fb_par *par = info->par;
> + u32 base = (var->yoffset * info->var.xres_virtual
> + + (var->xoffset & ~7)) >> 2;
> +
> + dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
> + var->xoffset, var->yoffset, base);
> +
> + switch (info->var.bits_per_pixel) {
> + case 8:
> + break;
> + case 15:
> + case 16:
> + base *= 2;
> + break;
> + case 24:
> + /*
> + * The last bit does not seem to have any effect on the start
> + * address register in 24bpp mode, so...
> + */
> + base &= 0xFFFFFFFE; /* ...ignore the last bit. */
> + base *= 3;
> + break;
> + case 32:
> + base *= 4;
> + break;
> + }
> +
> + par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
> + par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
> + par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
> + par->ext_start_addr > + ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
> +
> + i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
> + i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
> + (base & 0x0000FF00) >> 8);
> + i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
> + (base & 0x3FC00000) >> 22);
> + i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
> + ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
> +
> + return 0;
> +}
> +
> +static int i740fb_blank(int blank_mode, struct fb_info *info)
> +{
> + struct i740fb_par *par = info->par;
> +
> + unsigned char SEQ01;
> + int DPMSSyncSelect;
> +
> + switch (blank_mode) {
> + case FB_BLANK_UNBLANK:
> + case FB_BLANK_NORMAL:
> + SEQ01 = 0x00;
> + DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
> + break;
> + case FB_BLANK_VSYNC_SUSPEND:
> + SEQ01 = 0x20;
> + DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
> + break;
> + case FB_BLANK_HSYNC_SUSPEND:
> + SEQ01 = 0x20;
> + DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
> + break;
> + case FB_BLANK_POWERDOWN:
> + SEQ01 = 0x20;
> + DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
> + break;
> + default:
> + return -EINVAL;
> + }
> + /* Turn the screen on/off */
> + i740outb(par, SRX, 0x01);
> + SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
> + i740outb(par, SRX, 0x01);
> + i740outb(par, SRX + 1, SEQ01);
> +
> + /* Set the DPMS mode */
> + i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
> +
> + /* Let fbcon do a soft blank for us */
> + return (blank_mode = FB_BLANK_NORMAL) ? 1 : 0;
> +}
> +
> +static struct fb_ops i740fb_ops = {
> + .owner = THIS_MODULE,
> + .fb_open = i740fb_open,
> + .fb_release = i740fb_release,
> + .fb_check_var = i740fb_check_var,
> + .fb_set_par = i740fb_set_par,
> + .fb_setcolreg = i740fb_setcolreg,
> + .fb_blank = i740fb_blank,
> + .fb_pan_display = i740fb_pan_display,
> + .fb_fillrect = cfb_fillrect,
> + .fb_copyarea = cfb_copyarea,
> + .fb_imageblit = cfb_imageblit,
> +};
> +
> +/* ------------------------------------------------------------------------- */
> +
> +static int __devinit i740fb_probe(struct pci_dev *dev,
> + const struct pci_device_id *ent)
> +{
> + struct fb_info *info;
> + struct i740fb_par *par;
> + int ret, tmp;
> + bool found = false;
> + u8 *edid;
> +
> + info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
> + if (!info) {
> + dev_err(&(dev->dev), "cannot allocate framebuffer\n");
> + return -ENOMEM;
> + }
> +
> + par = info->par;
> + mutex_init(&par->open_lock);
> +
> + info->var.activate = FB_ACTIVATE_NOW;
> + info->var.bits_per_pixel = 8;
> + info->fbops = &i740fb_ops;
> + info->pseudo_palette = par->pseudo_palette;
> +
> + ret = pci_enable_device(dev);
> + if (ret) {
> + dev_err(info->device, "cannot enable PCI device\n");
> + goto err_enable_device;
> + }
> +
> + ret = pci_request_regions(dev, info->fix.id);
> + if (ret) {
> + dev_err(info->device, "error requesting regions\n");
> + goto err_request_regions;
> + }
> +
> + info->screen_base = pci_ioremap_bar(dev, 0);
> + if (!info->screen_base) {
> + dev_err(info->device, "error remapping base\n");
> + ret = -ENOMEM;
> + goto err_ioremap_1;
> + }
> +
> + par->regs = pci_ioremap_bar(dev, 1);
> + if (!par->regs) {
> + dev_err(info->device, "error remapping MMIO\n");
> + ret = -ENOMEM;
> + goto err_ioremap_2;
> + }
> +
> + /* detect memory size */
> + if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
> + = DRAM_ROW_1_SDRAM)
> + i740outb(par, XRX, DRAM_ROW_BNDRY_1);
> + else
> + i740outb(par, XRX, DRAM_ROW_BNDRY_0);
> + info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
> + /* detect memory type */
> + tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
> + par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
> + (tmp & DRAM_RAS_PRECHARGE));
> +
> + printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
> + pci_name(dev), info->screen_size >> 10,
> + par->has_sgram ? "SGRAM" : "SDRAM");
> +
> + info->fix = i740fb_fix;
> + info->fix.mmio_start = pci_resource_start(dev, 1);
> + info->fix.mmio_len = pci_resource_len(dev, 1);
> + info->fix.smem_start = pci_resource_start(dev, 0);
> + info->fix.smem_len = info->screen_size;
> + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
> +
> + if (i740fb_setup_ddc_bus(info) = 0) {
> + par->ddc_registered = true;
> + edid = fb_ddc_read(&par->ddc_adapter);
> + if (edid) {
> + fb_edid_to_monspecs(edid, &info->monspecs);
> + kfree(edid);
> + if (!info->monspecs.modedb)
> + dev_err(info->device,
> + "error getting mode database\n");
> + else {
> + const struct fb_videomode *m;
> +
> + fb_videomode_to_modelist(
> + info->monspecs.modedb,
> + info->monspecs.modedb_len,
> + &info->modelist);
> + m = fb_find_best_display(&info->monspecs,
> + &info->modelist);
> + if (m) {
> + fb_videomode_to_var(&info->var, m);
> + /* fill all other info->var's fields */
> + if (!i740fb_check_var(&info->var, info))
> + found = true;
> + }
> + }
> + }
> + }
> +
> + if (!mode_option && !found)
> + mode_option = "640x480-8@60";
> +
> + if (mode_option) {
> + ret = fb_find_mode(&info->var, info, mode_option,
> + info->monspecs.modedb,
> + info->monspecs.modedb_len,
> + NULL, info->var.bits_per_pixel);
> + if (!ret || ret = 4) {
> + dev_err(info->device, "mode %s not found\n",
> + mode_option);
> + ret = -EINVAL;
> + }
> + }
> +
> + fb_destroy_modedb(info->monspecs.modedb);
> + info->monspecs.modedb = NULL;
> +
> + /* maximize virtual vertical size for fast scrolling */
> + info->var.yres_virtual = info->fix.smem_len * 8 /
> + (info->var.bits_per_pixel * info->var.xres_virtual);
> +
> + if (ret = -EINVAL)
> + goto err_find_mode;
> +
> + ret = fb_alloc_cmap(&info->cmap, 256, 0);
> + if (ret) {
> + dev_err(info->device, "cannot allocate colormap\n");
> + goto err_alloc_cmap;
> + }
> +
> + ret = register_framebuffer(info);
> + if (ret) {
> + dev_err(info->device, "error registering framebuffer\n");
> + goto err_reg_framebuffer;
> + }
> +
> + printk(KERN_INFO "fb%d: %s frame buffer device\n",
> + info->node, info->fix.id);
> + pci_set_drvdata(dev, info);
> +#ifdef CONFIG_MTRR
> + if (mtrr) {
> + par->mtrr_reg = -1;
> + par->mtrr_reg = mtrr_add(info->fix.smem_start,
> + info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
> + }
> +#endif
> + return 0;
> +
> +err_reg_framebuffer:
> + fb_dealloc_cmap(&info->cmap);
> +err_alloc_cmap:
> +err_find_mode:
> + if (par->ddc_registered)
> + i2c_del_adapter(&par->ddc_adapter);
> + pci_iounmap(dev, par->regs);
> +err_ioremap_2:
> + pci_iounmap(dev, info->screen_base);
> +err_ioremap_1:
> + pci_release_regions(dev);
> +err_request_regions:
> +/* pci_disable_device(dev); */
> +err_enable_device:
> + framebuffer_release(info);
> + return ret;
> +}
> +
> +static void __devexit i740fb_remove(struct pci_dev *dev)
> +{
> + struct fb_info *info = pci_get_drvdata(dev);
> +
> + if (info) {
> +#ifdef CONFIG_MTRR
> + struct i740fb_par *par = info->par;
> +
> + if (par->mtrr_reg >= 0) {
> + mtrr_del(par->mtrr_reg, 0, 0);
> + par->mtrr_reg = -1;
> + }
> +#endif
> + unregister_framebuffer(info);
> + fb_dealloc_cmap(&info->cmap);
> + if (par->ddc_registered)
> + i2c_del_adapter(&par->ddc_adapter);
> + pci_iounmap(dev, par->regs);
> + pci_iounmap(dev, info->screen_base);
> + pci_release_regions(dev);
> +/* pci_disable_device(dev); */
> + pci_set_drvdata(dev, NULL);
> + framebuffer_release(info);
> + }
> +}
> +
> +#ifdef CONFIG_PM
> +static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
> +{
> + struct fb_info *info = pci_get_drvdata(dev);
> + struct i740fb_par *par = info->par;
> +
> + /* don't disable console during hibernation and wakeup from it */
> + if (state.event = PM_EVENT_FREEZE || state.event = PM_EVENT_PRETHAW)
> + return 0;
> +
> + console_lock();
> + mutex_lock(&(par->open_lock));
> +
> + /* do nothing if framebuffer is not active */
> + if (par->ref_count = 0) {
> + mutex_unlock(&(par->open_lock));
> + console_unlock();
> + return 0;
> + }
> +
> + fb_set_suspend(info, 1);
> +
> + pci_save_state(dev);
> + pci_disable_device(dev);
> + pci_set_power_state(dev, pci_choose_state(dev, state));
> +
> + mutex_unlock(&(par->open_lock));
> + console_unlock();
> +
> + return 0;
> +}
> +
> +static int i740fb_resume(struct pci_dev *dev)
> +{
> + struct fb_info *info = pci_get_drvdata(dev);
> + struct i740fb_par *par = info->par;
> +
> + console_lock();
> + mutex_lock(&(par->open_lock));
> +
> + if (par->ref_count = 0)
> + goto fail;
> +
> + pci_set_power_state(dev, PCI_D0);
> + pci_restore_state(dev);
> + if (pci_enable_device(dev))
> + goto fail;
> +
> + i740fb_set_par(info);
> + fb_set_suspend(info, 0);
> +
> +fail:
> + mutex_unlock(&(par->open_lock));
> + console_unlock();
> + return 0;
> +}
> +#else
> +#define i740fb_suspend NULL
> +#define i740fb_resume NULL
> +#endif /* CONFIG_PM */
> +
> +#define I740_ID_PCI 0x00d1
> +#define I740_ID_AGP 0x7800
> +
> +static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
> + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
> + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
> + { 0 }
> +};
> +MODULE_DEVICE_TABLE(pci, i740fb_id_table);
> +
> +static struct pci_driver i740fb_driver = {
> + .name = "i740fb",
> + .id_table = i740fb_id_table,
> + .probe = i740fb_probe,
> + .remove = __devexit_p(i740fb_remove),
> + .suspend = i740fb_suspend,
> + .resume = i740fb_resume,
> +};
> +
> +#ifndef MODULE
> +static int __init i740fb_setup(char *options)
> +{
> + char *opt;
> +
> + if (!options || !*options)
> + return 0;
> +
> + while ((opt = strsep(&options, ",")) != NULL) {
> + if (!*opt)
> + continue;
> +#ifdef CONFIG_MTRR
> + else if (!strncmp(opt, "mtrr:", 5))
> + mtrr = simple_strtoul(opt + 5, NULL, 0);
> +#endif
> + else
> + mode_option = opt;
> + }
> +
> + return 0;
> +}
> +#endif
> +
> +int __init i740fb_init(void)
> +{
> +#ifndef MODULE
> + char *option = NULL;
> +
> + if (fb_get_options("i740fb", &option))
> + return -ENODEV;
> + i740fb_setup(option);
> +#endif
> +
> + return pci_register_driver(&i740fb_driver);
> +}
> +
> +static void __exit i740fb_exit(void)
> +{
> + pci_unregister_driver(&i740fb_driver);
> +}
> +
> +module_init(i740fb_init);
> +module_exit(i740fb_exit);
> +
> +MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("fbdev driver for Intel740");
> +
> +module_param(mode_option, charp, 0444);
> +MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
> +
> +#ifdef CONFIG_MTRR
> +module_param(mtrr, int, 0444);
> +MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
> +#endif
> --- /dev/null 2012-01-24 00:06:39.330222901 +0100
> +++ linux-3.2.1/drivers/video/i740_reg.h 2012-01-23 22:55:57.000000000 +0100
> @@ -0,0 +1,309 @@
> +/**************************************************************************
> +
> +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
> +All Rights Reserved.
> +
> +Permission is hereby granted, free of charge, to any person obtaining a
> +copy of this software and associated documentation files (the
> +"Software"), to deal in the Software without restriction, including
> +without limitation the rights to use, copy, modify, merge, publish,
> +distribute, sub license, and/or sell copies of the Software, and to
> +permit persons to whom the Software is furnished to do so, subject to
> +the following conditions:
> +
> +The above copyright notice and this permission notice (including the
> +next paragraph) shall be included in all copies or substantial portions
> +of the Software.
> +
> +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
> +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> +
> +**************************************************************************/
> +
> +/*
> + * Authors:
> + * Kevin E. Martin <kevin@precisioninsight.com>
> + */
> +
> +/* I/O register offsets */
> +#define SRX VGA_SEQ_I
> +#define GRX VGA_GFX_I
> +#define ARX VGA_ATT_IW
> +#define XRX 0x3D6
> +#define MRX 0x3D2
> +
> +/* VGA Color Palette Registers */
> +#define DACMASK 0x3C6
> +#define DACSTATE 0x3C7
> +#define DACRX 0x3C7
> +#define DACWX 0x3C8
> +#define DACDATA 0x3C9
> +
> +/* CRT Controller Registers (CRX) */
> +#define START_ADDR_HI 0x0C
> +#define START_ADDR_LO 0x0D
> +#define VERT_SYNC_END 0x11
> +#define EXT_VERT_TOTAL 0x30
> +#define EXT_VERT_DISPLAY 0x31
> +#define EXT_VERT_SYNC_START 0x32
> +#define EXT_VERT_BLANK_START 0x33
> +#define EXT_HORIZ_TOTAL 0x35
> +#define EXT_HORIZ_BLANK 0x39
> +#define EXT_START_ADDR 0x40
> +#define EXT_START_ADDR_ENABLE 0x80
> +#define EXT_OFFSET 0x41
> +#define EXT_START_ADDR_HI 0x42
> +#define INTERLACE_CNTL 0x70
> +#define INTERLACE_ENABLE 0x80
> +#define INTERLACE_DISABLE 0x00
> +
> +/* Miscellaneous Output Register */
> +#define MSR_R 0x3CC
> +#define MSR_W 0x3C2
> +#define IO_ADDR_SELECT 0x01
> +
> +#define MDA_BASE 0x3B0
> +#define CGA_BASE 0x3D0
> +
> +/* System Configuration Extension Registers (XRX) */
> +#define IO_CTNL 0x09
> +#define EXTENDED_ATTR_CNTL 0x02
> +#define EXTENDED_CRTC_CNTL 0x01
> +
> +#define ADDRESS_MAPPING 0x0A
> +#define PACKED_MODE_ENABLE 0x04
> +#define LINEAR_MODE_ENABLE 0x02
> +#define PAGE_MAPPING_ENABLE 0x01
> +
> +#define BITBLT_CNTL 0x20
> +#define COLEXP_MODE 0x30
> +#define COLEXP_8BPP 0x00
> +#define COLEXP_16BPP 0x10
> +#define COLEXP_24BPP 0x20
> +#define COLEXP_RESERVED 0x30
> +#define CHIP_RESET 0x02
> +#define BITBLT_STATUS 0x01
> +
> +#define DISPLAY_CNTL 0x40
> +#define VGA_WRAP_MODE 0x02
> +#define VGA_WRAP_AT_256KB 0x00
> +#define VGA_NO_WRAP 0x02
> +#define GUI_MODE 0x01
> +#define STANDARD_VGA_MODE 0x00
> +#define HIRES_MODE 0x01
> +
> +#define DRAM_ROW_TYPE 0x50
> +#define DRAM_ROW_0 0x07
> +#define DRAM_ROW_0_SDRAM 0x00
> +#define DRAM_ROW_0_EMPTY 0x07
> +#define DRAM_ROW_1 0x38
> +#define DRAM_ROW_1_SDRAM 0x00
> +#define DRAM_ROW_1_EMPTY 0x38
> +#define DRAM_ROW_CNTL_LO 0x51
> +#define DRAM_CAS_LATENCY 0x10
> +#define DRAM_RAS_TIMING 0x08
> +#define DRAM_RAS_PRECHARGE 0x04
> +#define DRAM_ROW_CNTL_HI 0x52
> +#define DRAM_EXT_CNTL 0x53
> +#define DRAM_REFRESH_RATE 0x03
> +#define DRAM_REFRESH_DISABLE 0x00
> +#define DRAM_REFRESH_60HZ 0x01
> +#define DRAM_REFRESH_FAST_TEST 0x02
> +#define DRAM_REFRESH_RESERVED 0x03
> +#define DRAM_TIMING 0x54
> +#define DRAM_ROW_BNDRY_0 0x55
> +#define DRAM_ROW_BNDRY_1 0x56
> +
> +#define DPMS_SYNC_SELECT 0x61
> +#define VSYNC_CNTL 0x08
> +#define VSYNC_ON 0x00
> +#define VSYNC_OFF 0x08
> +#define HSYNC_CNTL 0x02
> +#define HSYNC_ON 0x00
> +#define HSYNC_OFF 0x02
> +
> +#define PIXPIPE_CONFIG_0 0x80
> +#define DAC_8_BIT 0x80
> +#define DAC_6_BIT 0x00
> +#define HW_CURSOR_ENABLE 0x10
> +#define EXTENDED_PALETTE 0x01
> +
> +#define PIXPIPE_CONFIG_1 0x81
> +#define DISPLAY_COLOR_MODE 0x0F
> +#define DISPLAY_VGA_MODE 0x00
> +#define DISPLAY_8BPP_MODE 0x02
> +#define DISPLAY_15BPP_MODE 0x04
> +#define DISPLAY_16BPP_MODE 0x05
> +#define DISPLAY_24BPP_MODE 0x06
> +#define DISPLAY_32BPP_MODE 0x07
> +
> +#define PIXPIPE_CONFIG_2 0x82
> +#define DISPLAY_GAMMA_ENABLE 0x08
> +#define DISPLAY_GAMMA_DISABLE 0x00
> +#define OVERLAY_GAMMA_ENABLE 0x04
> +#define OVERLAY_GAMMA_DISABLE 0x00
> +
> +#define CURSOR_CONTROL 0xA0
> +#define CURSOR_ORIGIN_SCREEN 0x00
> +#define CURSOR_ORIGIN_DISPLAY 0x10
> +#define CURSOR_MODE 0x07
> +#define CURSOR_MODE_DISABLE 0x00
> +#define CURSOR_MODE_32_4C_AX 0x01
> +#define CURSOR_MODE_128_2C 0x02
> +#define CURSOR_MODE_128_1C 0x03
> +#define CURSOR_MODE_64_3C 0x04
> +#define CURSOR_MODE_64_4C_AX 0x05
> +#define CURSOR_MODE_64_4C 0x06
> +#define CURSOR_MODE_RESERVED 0x07
> +#define CURSOR_BASEADDR_LO 0xA2
> +#define CURSOR_BASEADDR_HI 0xA3
> +#define CURSOR_X_LO 0xA4
> +#define CURSOR_X_HI 0xA5
> +#define CURSOR_X_POS 0x00
> +#define CURSOR_X_NEG 0x80
> +#define CURSOR_Y_LO 0xA6
> +#define CURSOR_Y_HI 0xA7
> +#define CURSOR_Y_POS 0x00
> +#define CURSOR_Y_NEG 0x80
> +
> +#define VCLK2_VCO_M 0xC8
> +#define VCLK2_VCO_N 0xC9
> +#define VCLK2_VCO_MN_MSBS 0xCA
> +#define VCO_N_MSBS 0x30
> +#define VCO_M_MSBS 0x03
> +#define VCLK2_VCO_DIV_SEL 0xCB
> +#define POST_DIV_SELECT 0x70
> +#define POST_DIV_1 0x00
> +#define POST_DIV_2 0x10
> +#define POST_DIV_4 0x20
> +#define POST_DIV_8 0x30
> +#define POST_DIV_16 0x40
> +#define POST_DIV_32 0x50
> +#define VCO_LOOP_DIV_BY_4M 0x00
> +#define VCO_LOOP_DIV_BY_16M 0x04
> +#define REF_CLK_DIV_BY_5 0x02
> +#define REF_DIV_4 0x00
> +#define REF_DIV_1 0x01
> +
> +#define PLL_CNTL 0xCE
> +#define PLL_MEMCLK_SEL 0x03
> +#define PLL_MEMCLK__66667KHZ 0x00
> +#define PLL_MEMCLK__75000KHZ 0x01
> +#define PLL_MEMCLK__88889KHZ 0x02
> +#define PLL_MEMCLK_100000KHZ 0x03
> +
> +/* Multimedia Extension Registers (MRX) */
> +#define ACQ_CNTL_1 0x02
> +#define ACQ_CNTL_2 0x03
> +#define FRAME_CAP_MODE 0x01
> +#define CONT_CAP_MODE 0x00
> +#define SINGLE_CAP_MODE 0x01
> +#define ACQ_CNTL_3 0x04
> +#define COL_KEY_CNTL_1 0x3C
> +#define BLANK_DISP_OVERLAY 0x20
> +
> +/* FIFOs */
> +#define LP_FIFO 0x1000
> +#define HP_FIFO 0x2000
> +#define INSTPNT 0x3040
> +#define LP_FIFO_COUNT 0x3040
> +#define HP_FIFO_COUNT 0x3041
> +
> +/* FIFO Commands */
> +#define CLIENT 0xE0000000
> +#define CLIENT_2D 0x60000000
> +
> +/* Command Parser Mode Register */
> +#define COMPARS 0x3038
> +#define TWO_D_INST_DISABLE 0x08
> +#define THREE_D_INST_DISABLE 0x04
> +#define STATE_VAR_UPDATE_DISABLE 0x02
> +#define PAL_STIP_DISABLE 0x01
> +
> +/* Interrupt Control Registers */
> +#define IER 0x3030
> +#define IIR 0x3032
> +#define IMR 0x3034
> +#define ISR 0x3036
> +#define VMIINTB_EVENT 0x2000
> +#define GPIO4_INT 0x1000
> +#define DISP_FLIP_EVENT 0x0800
> +#define DVD_PORT_DMA 0x0400
> +#define DISP_VBLANK 0x0200
> +#define FIFO_EMPTY_DMA_DONE 0x0100
> +#define INST_PARSER_ERROR 0x0080
> +#define USER_DEFINED 0x0040
> +#define BREAKPOINT 0x0020
> +#define DISP_HORIZ_COUNT 0x0010
> +#define DISP_VSYNC 0x0008
> +#define CAPTURE_HORIZ_COUNT 0x0004
> +#define CAPTURE_VSYNC 0x0002
> +#define THREE_D_PIPE_FLUSHED 0x0001
> +
> +/* FIFO Watermark and Burst Length Control Register */
> +#define FWATER_BLC 0x00006000
> +#define LMI_BURST_LENGTH 0x7F000000
> +#define LMI_FIFO_WATERMARK 0x003F0000
> +#define AGP_BURST_LENGTH 0x00007F00
> +#define AGP_FIFO_WATERMARK 0x0000003F
> +
> +/* BitBLT Registers */
> +#define SRC_DST_PITCH 0x00040000
> +#define DST_PITCH 0x1FFF0000
> +#define SRC_PITCH 0x00001FFF
> +#define COLEXP_BG_COLOR 0x00040004
> +#define COLEXP_FG_COLOR 0x00040008
> +#define MONO_SRC_CNTL 0x0004000C
> +#define MONO_USE_COLEXP 0x00000000
> +#define MONO_USE_SRCEXP 0x08000000
> +#define MONO_DATA_ALIGN 0x07000000
> +#define MONO_BIT_ALIGN 0x01000000
> +#define MONO_BYTE_ALIGN 0x02000000
> +#define MONO_WORD_ALIGN 0x03000000
> +#define MONO_DWORD_ALIGN 0x04000000
> +#define MONO_QWORD_ALIGN 0x05000000
> +#define MONO_SRC_INIT_DSCRD 0x003F0000
> +#define MONO_SRC_RIGHT_CLIP 0x00003F00
> +#define MONO_SRC_LEFT_CLIP 0x0000003F
> +#define BITBLT_CONTROL 0x00040010
> +#define BLTR_STATUS 0x80000000
> +#define DYN_DEPTH 0x03000000
> +#define DYN_DEPTH_8BPP 0x00000000
> +#define DYN_DEPTH_16BPP 0x01000000
> +#define DYN_DEPTH_24BPP 0x02000000
> +#define DYN_DEPTH_32BPP 0x03000000 /* Unimplemented on the i740 */
> +#define DYN_DEPTH_ENABLE 0x00800000
> +#define PAT_VERT_ALIGN 0x00700000
> +#define SOLID_PAT_SELECT 0x00080000
> +#define PAT_IS_IN_COLOR 0x00000000
> +#define PAT_IS_MONO 0x00040000
> +#define MONO_PAT_TRANSP 0x00020000
> +#define COLOR_TRANSP_ROP 0x00000000
> +#define COLOR_TRANSP_DST 0x00008000
> +#define COLOR_TRANSP_EQ 0x00000000
> +#define COLOR_TRANSP_NOT_EQ 0x00010000
> +#define COLOR_TRANSP_ENABLE 0x00004000
> +#define MONO_SRC_TRANSP 0x00002000
> +#define SRC_IS_IN_COLOR 0x00000000
> +#define SRC_IS_MONO 0x00001000
> +#define SRC_USE_SRC_ADDR 0x00000000
> +#define SRC_USE_BLTDATA 0x00000400
> +#define BLT_TOP_TO_BOT 0x00000000
> +#define BLT_BOT_TO_TOP 0x00000200
> +#define BLT_LEFT_TO_RIGHT 0x00000000
> +#define BLT_RIGHT_TO_LEFT 0x00000100
> +#define BLT_ROP 0x000000FF
> +#define BLT_PAT_ADDR 0x00040014
> +#define BLT_SRC_ADDR 0x00040018
> +#define BLT_DST_ADDR 0x0004001C
> +#define BLT_DST_H_W 0x00040020
> +#define BLT_DST_HEIGHT 0x1FFF0000
> +#define BLT_DST_WIDTH 0x00001FFF
> +#define SRCEXP_BG_COLOR 0x00040024
> +#define SRCEXP_FG_COLOR 0x00040028
> +#define BLTDATA 0x00050000
>
>
>
^ permalink raw reply
* Re: [PATCH] fb_defio: add first_io callback
From: Florian Tobias Schandinat @ 2012-02-16 2:27 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201112311145.47717.heiko@sntech.de>
Hi Heiko,
sorry for the long delay.
On 12/31/2011 10:45 AM, Heiko Stübner wrote:
> With this optional callback the driver is notified when the first page
> is entered into the pagelist and a new deferred_io call is scheduled.
>
> A possible use-case for this is runtime-pm. In the first_io call
> pm_runtime_get()
> could be called, which starts an asynchronous runtime_resume of the
> device. In the deferred_io callback a call to
> pm_runtime_barrier()
> makes the sure, the device is resumed by then and a
> pm_runtime_put()
> may put the device back to sleep.
>
> Also, some SoCs may use the runtime-pm system to determine if they
> are able to enter deeper idle states. Therefore it is necessary to
> keep the use-count from the first written page until the conclusion
> of the screen update, to prevent the system from going to sleep before
> completing the pending update.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
while I consider this patch acceptable, I don't see any reason to apply it as
long as there is no driver actually using it.
Best regards,
Florian Tobias Schandinat
> ---
> drivers/video/fb_defio.c | 4 ++++
> include/linux/fb.h | 1 +
> 2 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
> index c27e153..070f26f 100644
> --- a/drivers/video/fb_defio.c
> +++ b/drivers/video/fb_defio.c
> @@ -107,6 +107,10 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
> /* protect against the workqueue changing the page list */
> mutex_lock(&fbdefio->lock);
>
> + /* first write in this cycle, notify the driver */
> + if (fbdefio->first_io && list_empty(&fbdefio->pagelist))
> + fbdefio->first_io(info);
> +
> /*
> * We want the page to remain locked from ->page_mkwrite until
> * the PTE is marked dirty to avoid page_mkclean() being called
> diff --git a/include/linux/fb.h b/include/linux/fb.h
> index 1d6836c..b86cd41 100644
> --- a/include/linux/fb.h
> +++ b/include/linux/fb.h
> @@ -602,6 +602,7 @@ struct fb_deferred_io {
> struct mutex lock; /* mutex that protects the page list */
> struct list_head pagelist; /* list of touched pages */
> /* callback */
> + void (*first_io)(struct fb_info *info);
> void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
> };
> #endif
^ permalink raw reply
* linux-next: build failure after merge of the final tree (fbdev tree related)
From: Stephen Rothwell @ 2012-02-16 5:29 UTC (permalink / raw)
To: Florian Tobias Schandinat, linux-fbdev
Cc: linux-next, linux-kernel, Ondrej Zary
In-Reply-To: <20110520163233.abcabd67.sfr@canb.auug.org.au>
[-- Attachment #1: Type: text/plain, Size: 504 bytes --]
Hi all,
After merging the final tree, today's linux-next build (powerpc
allyesconfig) failed like this:
drivers/video/i740fb.c: In function 'i740fb_remove':
drivers/video/i740fb.c:1192:7: error: 'par' undeclared (first use in this function)
Caused by commit 5350c65f4f15 ("Resurrect Intel740 driver: i740fb") from
the fbdev tree. CONFIG_MTRR is not defined for this build ...
I have reverted that commit for today.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] fb_defio: add first_io callback
From: Heiko Stübner @ 2012-02-16 7:34 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201112311145.47717.heiko@sntech.de>
Hi Florian,
Am Donnerstag, 16. Februar 2012, 03:27:25 schrieb Florian Tobias Schandinat:
> Hi Heiko,
>
> sorry for the long delay.
no problem
> On 12/31/2011 10:45 AM, Heiko Stübner wrote:
> > With this optional callback the driver is notified when the first page
> > is entered into the pagelist and a new deferred_io call is scheduled.
> >
> > A possible use-case for this is runtime-pm. In the first_io call
> >
> > pm_runtime_get()
> >
> > could be called, which starts an asynchronous runtime_resume of the
> > device. In the deferred_io callback a call to
> >
> > pm_runtime_barrier()
> >
> > makes the sure, the device is resumed by then and a
> >
> > pm_runtime_put()
> >
> > may put the device back to sleep.
> >
> > Also, some SoCs may use the runtime-pm system to determine if they
> > are able to enter deeper idle states. Therefore it is necessary to
> > keep the use-count from the first written page until the conclusion
> > of the screen update, to prevent the system from going to sleep before
> > completing the pending update.
> >
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>
> while I consider this patch acceptable, I don't see any reason to apply it
> as long as there is no driver actually using it.
ok, so I will keep sitting on it until my driver for the AUO-K190x epd
controller is ready for primetime and resubmit this patch in conjunction with
it.
Heiko
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Tomi Valkeinen @ 2012-02-16 8:22 UTC (permalink / raw)
To: Kevin Hilman
Cc: Cousson, Benoit, Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <87fweb98bs.fsf@ti.com>
[-- Attachment #1: Type: text/plain, Size: 673 bytes --]
On Wed, 2012-02-15 at 11:59 -0800, Kevin Hilman wrote:
> "Cousson, Benoit" <b-cousson@ti.com> writes:
> > Kevin,
> >
> > Do we still need to set the dev.parent to omap_device_parent?
>
> Nope.
>
> > I guess the default &platform_bus parent is good enough and
> > potentially the DSS children should be able to overwrite that.
>
> Yes, now that we use PM domains, we don't need it. I just sent a patch
> to remove omap_device_parent.
But it's still not possible to create a custom parent-child hierarchy
with omap_devices. Or can I change the parent of a platform_device after
it has been created? (doesn't sound very clean even if I can)
Tomi
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Cousson, Benoit @ 2012-02-16 10:16 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Kevin Hilman, Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <1329380536.1951.26.camel@deskari>
On 2/16/2012 9:22 AM, Tomi Valkeinen wrote:
> On Wed, 2012-02-15 at 11:59 -0800, Kevin Hilman wrote:
>> "Cousson, Benoit"<b-cousson@ti.com> writes:
>
>>> Kevin,
>>>
>>> Do we still need to set the dev.parent to omap_device_parent?
>>
>> Nope.
>>
>>> I guess the default&platform_bus parent is good enough and
>>> potentially the DSS children should be able to overwrite that.
>>
>> Yes, now that we use PM domains, we don't need it. I just sent a patch
>> to remove omap_device_parent.
>
> But it's still not possible to create a custom parent-child hierarchy
> with omap_devices. Or can I change the parent of a platform_device after
> it has been created? (doesn't sound very clean even if I can)
Nope, it has to be done before platform_device_add.
Thanks to Ohad patch [1] that Tony has just resent, you can use the
internal omap_device API and thus will be able to change the parent
before the registration.
Benoit
[1] ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}
^ permalink raw reply
* Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Laurent Pinchart @ 2012-02-16 23:25 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Sumit Semwal, Jesse Barker, Jesse Barnes, Rob Clark,
Pawel Osciak, Marek Szyprowski, Tomasz Stanislawski, Magnus Damm,
Marcus Lorentzon, Alexander Deucher, linux-media, dri-devel,
linux-fbdev
In-Reply-To: <1654816.MX2JJ87BEo@avalon>
Hello everybody,
First of all, I would like to thank all the attendees for their participation
in the mini-summit that helped make the meeting a success.
Here are my consolidated notes that cover both the Linaro Connect meeting and
the ELC meeting. They're also available at
http://www.ideasonboard.org/media/meetings/.
Kernel Display and Video API Consolidation mini-summit at ELC 2012
------------------------------------------------------------------
*** Video Transmitter Drivers ***
Goal: Sharing video transmitter drivers (i2c or 'IP block') between V4L and
DRM.
This is mostly useful for embedded systems. Transmitters can be used by both
GPUs and direct video outputs. Having a single driver for external (or even
internal) HDMI transmitters is desired to avoid code duplication between
subsystems.
- DRM/KMS implements support for transmitters as DRM encoders. Code is
embedded in the main DRM/KMS driver.
- V4L2 implements transmitter drivers as generic kernel objects called
v4l2_subdev that implement a set of abstract operations.
v4l2_subdev already solves (most of ?) the problem, but is specific to V4L2.
The proposed approach is to create a media_video_entity (exact name to be
defined) object similar to v4l2_subdev.
Using that API should not be mandatory, especially on hardware where the
transmitter and the display controller are deeply cross-dependent.
How to instantiate the transmitter device and how to handle probe order
needs to be solved, especially when DT binding come into play. The problem
already exists to some extend in V4L2.
The subdev API takes mbus formats as arguments, which is not handled by
DRM/KMS. V4L2 media bus codes will then need to be shared.
Action points:
- Initially, mostly FBDEV (HDMI-on-DSI, Renesas) and V4L2 (TI hardware,
Cisco). Hans + Laurent to work on a proposal.
*** Display Panel Drivers ***
Goal: Sharing display panel drivers between display controllers from
different vendors.
Panels are connected to the display controller through a standard bus with a
control channel (DSI and eDP are two major such buses). Various vendors have
created proprietary interfaces for panel drivers:
- TI on OMAP (drivers/video/omap2/displays).
- Samsung on Exynos (drivers/video/exynos).
- ST-Ericsson on MCDE (http://www.igloocommunity.org/gitweb/?p=kernel/igloo-
kernel.git;a=tree;f=drivers/video/mcde)
- Renesas is working on a similar interface for SH Mobile.
HDMI-on-DSI transmitters, while not panels per-se, can be supported through
the same API.
A Low level Linux Display Framework (https://lkml.org/lkml/2011/9/15/107)
has been proposed and overlaps with this topic.
For DSI, a possible abstraction level would be a DCS (Display Command Set)
bus. Panels and/or HDMI-on-DSI transmitter drivers would be implemented as
DCS drivers.
Action points:
- Marcus to work on a proposal for DCS-based panels (with Tomi Valkeinen and
Morimoto-san).
*** Common video mode data structure and EDID parser ***
Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
The DRM EDID parser is currently the most advanced implementation and will
be taken as a starting point.
Different subsystems use different data structures to describe video
mode/timing information:
- struct drm_mode_modeinfo in DRM/KMS
- struct fb_videomode in FBDEV
- struct v4l2_bt_timings in V4L2
A new common video mode/timing data structure (struct media_video_mode_info,
exact name is to be defined), not tied to any specific subsystem, is
required to share the EDID parser. That structure won't be exported to
userspace.
Helper functions will be implemented in the subsystems to convert between
that generic structure and the various subsystem-specific structures.
The mode list is stored in the DRM connector in the EDID parser. A new mode
list data structure can be added, or a callback function can be used by the
parser to give modes one at a time to the caller.
3D needs to be taken into account (this is similar to interlacing).
Action points:
- Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.
*** Shared in-kernel image/framebuffer object type ***
Goal: Describe dma-buf content in a generic cross-subsystem way.
Most formats can be described by 4CC, width, height and pitch. Strange
hardware-specific formats might not be possible to describes completely
generically.
However, format negotiation goes through userspace anyway, so there should
be no need for passing format information directly between drivers.
Action points:
- None, this task will not be worked on.
*** Central 4CC Documentation ***
Goal: Define and document 4CCs in a central location to make sure 4CCs won't
overlap or have different meanings for different subsystems.
DRM and V4L2 define their own 4CCs:
- include/drm/drm-fourccs.h
- include/linux/videodev2.h
A new header file will centralize the definitions, with a new
cross-subsystem prefix. DRM and V4L2 4CCs will be redefined as aliases for
the new centralized 4CCs.
Colorspace (including both color matrix and Y/U/V ranges) should be shared
as well. VDPAU (and VAAPI ?) pass the color matrix to userspace. The kernel
API should not be more restrictive, but we just need a couple of presets in
most cases. We can define a list of common presets, with a way to upload a
custom matrix.
Action points:
- Start with the V4L2 documentation, create a shared header file. Sakari to
work on a proposal.
*** Split KMS and GPU Drivers ***
Goal: Split KMS and GPU drivers with in kernel API inbetween.
In most (all ?) SoCs, the GPU and the display controller are separate
devices. Splitting them into separate drivers would allow reusing the GPU
driver with different devices (e.g. using a single common PowerVR kernel
module with different display controller drivers). The same approach can be
used on the desktop for the multi-GPU case and the USB display case.
- OMAP already separates the GPU and DSS drivers, but the GPU driver is some
kind of DSS plugin. This isn't a long-term approach.
- Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
into display subsystem since UMP, GPU has own memory management codes.
One of the biggest challenges would be to get GPU vendors to use this new
model. ARM could help here, by making the Mali kernel driver split from the
display controller drivers. Once one vendor jumps onboard, others could have
a bigger incentive to follow.
Action points:
- Rob planning to work on a reference implementation, as part of the sync
object case. This is a pretty long term plan.
- Jesse will handle the coordination with ARM for Mali.
*** HDMI CEC Support ***
Goal: Support HDMI CEC and offer a userspace API for applications.
A new kernel API is needed and must be usable by KMS, V4L2 and possibly
LIRC. There's ongoing effort from Cisco to implement HDMI CEC support. Given
their background, V4L2 is their initial target. A proposal is available at
http://www.mail-archive.com/linux-media@vger.kernel.org/msg29241.html with a
sample implementation at
http://git.linuxtv.org/hverkuil/cisco.git/shortlog/refs/heads/cobalt-
mainline
(drivers/media/video/adv7604.c and ad9389b.c.
In order to avoid API duplication, a new CEC subsystem is probably needed.
CEC could be modeled as a bus, or as a network device. With the network
device approach, we could have both kernel and userspace protocol handlers.
CEC devices need to be associated with HDMI connectors. The Media Controller
API is a good candidate.
Action points:
- Hans is planning to push CEC support to mainline this year. Marcus can
provide contact information for Per Persson (ST Ericsson).
*** Hardware Pipeline Configuration ***
Goal: Create a central shared API to configure hardware pipelines on any
display- or video-related device.
Hardware pipeline configuration includes both link and format configuration.
To handle complex pipelines, V4L2 created a userspace V4L2 subdev API that
works in cooperation with the Media Controller API. Such an approach could
be generalized to support DRM/KMS, FB and V4L2 devices with a single
pipeline configuration API.
However, DRM/KMS can configure a complete display pipeline directly, without
any need for userspace to access formats on specific pads directly. There is
thus no direct need (at least for today's hardware) to expose low-level
pipeline configuration to userspace.
For display devices, DRM/KMS is going to support configuration of multiple
overlays/planes. fbdev support will be available "for free" on top of
DRM/KMS for legacy applications and for fbcon. fbdev should probably not be
extended to support multiple overlays/planes explicitly. Drivers and
applications should implement and use KMS instead, and no new FB or V4L2
frontend should be implemented in new display drivers.
Implementing the Media Controller API in DRM/KMS is still useful to
associate connectors with HDMI audio/CEC devices. More than that would
probably be overkill.
Action points:
- Laurent to check the DRM/KMS API to make sure it fulfills all the V4L2
needs. dma-buf importer role in DRM/KMS is one of the required features to
implement use cases currently supported by V4L2 USERPTR.
- Implement a proof-of-concept media controller API in DRM to expose the
pipeline topology to userspace. Sumit is working on dma-buf, could maybe
help on this. Laurent will coordinate the effort.
*** Synchronous pipeline changes ***
Goal: Create an API to apply complex changes to a video pipeline atomically.
Needed for complex camera use cases. On the DRM/KMS side, the approach is to
use one big ioctl to configure the whole pipeline.
One solution is a commit ioctl, through the media controller device, that
would be dispatched to entities internally with a prepare step and a commit
step.
Parameters to be committed need to be stored in a context. We can either use
one cross-device context, or per-device contexts that would then need to be
associated with the commit operation.
Action points:
- Sakari will provide a proof-of-concept and/or proposal if needed.
*** Sync objects ***
Goal: Implement in-kernel support for buffer swapping, dependency system,
sync objects, queue/dequeue userspace API (think EGLstream & EGLsync)
This can be implemented in kernel-space (with direct communication between
drivers to schedule buffers around), user-space (with ioctls to
queue/dequeue buffers), or a mix of both. SoCs with direct sync object
support at the hardware level between different IP blocks can be foreseen in
the (near ?) future. A kernel-space API would then be needed.
Sharing sync objects between subsystems could result in the creation of a
cross-subsystem queue/dequeue API. Integration with dma_buf would make
sense, a dma_buf_pool object would then likely be needed.
If the SoC supports direct signaling between IP blocks, this could be
considered (and implemented) as a pipeline configurable through the Media
Controller API. However, applications will then need to be link-aware. Using
sync/stream objects would offer a single API to userspace, regardless of
whether the synchronization is handled by the CPU in kernel space or by the
IP blocks directly.
Sync objects are not always tied to buffers, they need to be implemented as
stand-alone objects on the kernel side. However, when exposing the sync
object to userspace in order to share it between devices, all current use
cases involve dma-buf. The first implementation will thus not expose the
sync objects explicitly to userspace, but associate them with a dma-buf. If
sync objects with no associated dma-buf are later needed, an explicit
userspace API can be added.
eventfd is a possible candidate for sync object implementation.
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=include/linux/eventfd.h
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/cgroups.txt
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/memory.txt
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/virtual/kvm/api.txt
Action points:
- TBD, will be on the agenda for the Graphics Summit @ELC2012.
*** dma-buf Implementation in V4L2 ***
Goal: Implement the dma-buf API in V4L2.
Sumit Semwal has submitted patches to implement the dma-buf importer role in
videobuf2. Tomasz Stanislawski has then submitted incremental patches to add
exporter role support.
Action points:
- Create a git branch to host all the latest patches. Sumit will provide
that.
Other points that have been briefly discussed
---------------------------------------------
*** Device Tree Aware 'Subdevice' Instantiation ***
Goal: Design standard device tree bindings to instantiate "subdevices"
(including the generic subdev-like video transmitters).
U-Boot developers are working on automatic configuration using the device
tree and want to support LCDs. Proposed patches are available at
http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/122864/focus\x122881
On a related note, kernel PWM proposed DT binding patches for backlight
control are available at
http://www.spinics.net/lists/linux-tegra/msg03988.html.
*** HDMI audio output ***
Goal: Give applications a way to associate an HDMI connector with an ALSA
HDMI audio device.
This should be implemented with the Media Controller API.
*** 2D Kernel APIs ***
Goal: Expose a 2D acceleration API to userspace for devices that support
hardware-accelerated 2D rendering.
If the hardware is based on a command stream, a userspace library is needed
anyway to build the command stream. A 2D kernel API would then not be very
useful. This could be split to a DRM device without a KMS interface.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [patch] viafb: NULL dereference on allocation failure in query_edid()
From: Dan Carpenter @ 2012-02-17 6:45 UTC (permalink / raw)
To: linux-fbdev
We should handle the allocation here, if only to keep the static
checkers happy.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
index 03f7a41..754d450 100644
--- a/drivers/video/via/via_aux_edid.c
+++ b/drivers/video/via/via_aux_edid.c
@@ -36,10 +36,13 @@ static void query_edid(struct via_aux_drv *drv)
unsigned char edid[EDID_LENGTH];
bool valid = false;
- if (spec)
+ if (spec) {
fb_destroy_modedb(spec->modedb);
- else
+ } else {
spec = kmalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return;
+ }
spec->version = spec->revision = 0;
if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
^ permalink raw reply related
* Re: [patch] viafb: NULL dereference on allocation failure in query_edid()
From: Florian Tobias Schandinat @ 2012-02-17 7:30 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20120217064501.GD3666@elgon.mountain>
On 02/17/2012 06:45 AM, Dan Carpenter wrote:
> We should handle the allocation here, if only to keep the static
> checkers happy.
>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Ah, thanks for noticing it and sorry that I introduced it in the first place.
Applied.
Thanks,
Florian Tobias Schandinat
>
> diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
> index 03f7a41..754d450 100644
> --- a/drivers/video/via/via_aux_edid.c
> +++ b/drivers/video/via/via_aux_edid.c
> @@ -36,10 +36,13 @@ static void query_edid(struct via_aux_drv *drv)
> unsigned char edid[EDID_LENGTH];
> bool valid = false;
>
> - if (spec)
> + if (spec) {
> fb_destroy_modedb(spec->modedb);
> - else
> + } else {
> spec = kmalloc(sizeof(*spec), GFP_KERNEL);
> + if (!spec)
> + return;
> + }
>
> spec->version = spec->revision = 0;
> if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
>
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Daniel Vetter @ 2012-02-17 9:55 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
Magnus Damm, Marcus Lorentzon, dri-devel, Alexander Deucher,
Rob Clark, linux-media, Marek Szyprowski
In-Reply-To: <1775349.d0yvHiVdjB@avalon>
On Fri, Feb 17, 2012 at 12:25:51AM +0100, Laurent Pinchart wrote:
> Hello everybody,
>
> First of all, I would like to thank all the attendees for their participation
> in the mini-summit that helped make the meeting a success.
>
> Here are my consolidated notes that cover both the Linaro Connect meeting and
> the ELC meeting. They're also available at
> http://www.ideasonboard.org/media/meetings/.
Looks like you've been all really busy ;-) A few quick comments below.
> Kernel Display and Video API Consolidation mini-summit at ELC 2012
> ------------------------------------------------------------------
[snip]
> *** Common video mode data structure and EDID parser ***
>
> Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
>
> The DRM EDID parser is currently the most advanced implementation and will
> be taken as a starting point.
>
> Different subsystems use different data structures to describe video
> mode/timing information:
>
> - struct drm_mode_modeinfo in DRM/KMS
> - struct fb_videomode in FBDEV
> - struct v4l2_bt_timings in V4L2
>
> A new common video mode/timing data structure (struct media_video_mode_info,
> exact name is to be defined), not tied to any specific subsystem, is
> required to share the EDID parser. That structure won't be exported to
> userspace.
>
> Helper functions will be implemented in the subsystems to convert between
> that generic structure and the various subsystem-specific structures.
>
> The mode list is stored in the DRM connector in the EDID parser. A new mode
> list data structure can be added, or a callback function can be used by the
> parser to give modes one at a time to the caller.
>
> 3D needs to be taken into account (this is similar to interlacing).
>
> Action points:
> - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.
I think we should include kernel cmdline video mode parsing here, afaik
kms and fbdev are rather similar (won't work if they're too different,
obviously).
[snip]
> *** Central 4CC Documentation ***
>
> Goal: Define and document 4CCs in a central location to make sure 4CCs won't
> overlap or have different meanings for different subsystems.
>
> DRM and V4L2 define their own 4CCs:
>
> - include/drm/drm-fourccs.h
> - include/linux/videodev2.h
>
> A new header file will centralize the definitions, with a new
> cross-subsystem prefix. DRM and V4L2 4CCs will be redefined as aliases for
> the new centralized 4CCs.
>
> Colorspace (including both color matrix and Y/U/V ranges) should be shared
> as well. VDPAU (and VAAPI ?) pass the color matrix to userspace. The kernel
> API should not be more restrictive, but we just need a couple of presets in
> most cases. We can define a list of common presets, with a way to upload a
> custom matrix.
>
> Action points:
> - Start with the V4L2 documentation, create a shared header file. Sakari to
> work on a proposal.
I'm looking forward to the bikeshed discussion here ;-)
</snide-remark>
> *** Split KMS and GPU Drivers ***
>
> Goal: Split KMS and GPU drivers with in kernel API inbetween.
>
> In most (all ?) SoCs, the GPU and the display controller are separate
> devices. Splitting them into separate drivers would allow reusing the GPU
> driver with different devices (e.g. using a single common PowerVR kernel
> module with different display controller drivers). The same approach can be
> used on the desktop for the multi-GPU case and the USB display case.
>
> - OMAP already separates the GPU and DSS drivers, but the GPU driver is some
> kind of DSS plugin. This isn't a long-term approach.
> - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
> into display subsystem since UMP, GPU has own memory management codes.
>
> One of the biggest challenges would be to get GPU vendors to use this new
> model. ARM could help here, by making the Mali kernel driver split from the
> display controller drivers. Once one vendor jumps onboard, others could have
> a bigger incentive to follow.
>
> Action points:
> - Rob planning to work on a reference implementation, as part of the sync
> object case. This is a pretty long term plan.
> - Jesse will handle the coordination with ARM for Mali.
Imo splitting up SoC drm drivers into separate drivers for the different
blocks makes tons of sense. The one controlling the display subsystem
would then also support kms, all the others would just support gem and
share buffers with dma_buf (and maybe synchronize with some new-fangled
sync objects). Otoh it doesn't make much sense to push this if we don't
have at least one of the SoC ip block verndors on board. We can dream ...
[snip]
> *** Sync objects ***
>
> Goal: Implement in-kernel support for buffer swapping, dependency system,
> sync objects, queue/dequeue userspace API (think EGLstream & EGLsync)
>
> This can be implemented in kernel-space (with direct communication between
> drivers to schedule buffers around), user-space (with ioctls to
> queue/dequeue buffers), or a mix of both. SoCs with direct sync object
> support at the hardware level between different IP blocks can be foreseen in
> the (near ?) future. A kernel-space API would then be needed.
>
> Sharing sync objects between subsystems could result in the creation of a
> cross-subsystem queue/dequeue API. Integration with dma_buf would make
> sense, a dma_buf_pool object would then likely be needed.
>
> If the SoC supports direct signaling between IP blocks, this could be
> considered (and implemented) as a pipeline configurable through the Media
> Controller API. However, applications will then need to be link-aware. Using
> sync/stream objects would offer a single API to userspace, regardless of
> whether the synchronization is handled by the CPU in kernel space or by the
> IP blocks directly.
>
> Sync objects are not always tied to buffers, they need to be implemented as
> stand-alone objects on the kernel side. However, when exposing the sync
> object to userspace in order to share it between devices, all current use
> cases involve dma-buf. The first implementation will thus not expose the
> sync objects explicitly to userspace, but associate them with a dma-buf. If
> sync objects with no associated dma-buf are later needed, an explicit
> userspace API can be added.
>
> eventfd is a possible candidate for sync object implementation.
>
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=include/linux/eventfd.h
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/cgroups.txt
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/memory.txt
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/virtual/kvm/api.txt
>
> Action points:
> - TBD, will be on the agenda for the Graphics Summit @ELC2012.
I've already started discussing this a bit with Rob. I'm not sure whether
implicitly associating a sync object with a dma_buf makes sense, afaik
sync objects can be used rather independently from buffers. But this is a
long-term feature, so we still have plenty of time to discuss this.
[snip]
> *** 2D Kernel APIs ***
>
> Goal: Expose a 2D acceleration API to userspace for devices that support
> hardware-accelerated 2D rendering.
>
> If the hardware is based on a command stream, a userspace library is needed
> anyway to build the command stream. A 2D kernel API would then not be very
> useful. This could be split to a DRM device without a KMS interface.
Imo we should ditch this - fb accel doesn't belong into the kernel. Even
on hw that still has a blitter for easy 2d accel without a complete 3d
state setup necessary, it's not worth it. Chris Wilson from our team once
played around with implementing fb accel in the kernel (i915 hw still has
a blitter engine in the latest generations). He quickly noticed that to
have decent speed, competitive with s/w rendering by the cpu he needs the
entire batch and buffer management stuff from userspace. And to really
beat the cpu, you need even more magic.
If you want fast 2d accel, use something like cairo.
Cheers, Daniel
--
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Semwal, Sumit @ 2012-02-17 11:19 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Sakari Ailus, Jesse Barker, Jesse Barnes, Rob Clark, Pawel Osciak,
Marek Szyprowski, Tomasz Stanislawski, Magnus Damm,
Marcus Lorentzon, Alexander Deucher, linux-media, dri-devel,
linux-fbdev
In-Reply-To: <1775349.d0yvHiVdjB@avalon>
Hello Laurent, Everyone:
On Fri, Feb 17, 2012 at 4:55 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hello everybody,
>
> First of all, I would like to thank all the attendees for their participation
> in the mini-summit that helped make the meeting a success.
>
<snip>
> *** dma-buf Implementation in V4L2 ***
>
> Goal: Implement the dma-buf API in V4L2.
>
> Sumit Semwal has submitted patches to implement the dma-buf importer role in
> videobuf2. Tomasz Stanislawski has then submitted incremental patches to add
> exporter role support.
>
> Action points:
> - Create a git branch to host all the latest patches. Sumit will provide
> that.
>
>
Against my Action Item: I have created the following branch at my
github (obviously, it is an RFC branch only)
tree: git://github.com/sumitsemwal/kernel-omap4.git
branch: 3.3rc3-v4l2-dmabuf-RFCv1
As the name partially suggests, it is based out of:
3.3-rc3 +
dmav6 [1] +
some minor dma-buf updates [2] +
my v4l2-as-importer RFC [3] +
Tomasz' RFC for v4l2-as-exporter (and related patches) [4]
Since Tomasz' RFC had a patch-pair which first removed and then added
drivers/media/video/videobuf2-dma-contig.c file, I 'combined' these
into one - but since the patch-pair heavily refactored the file, I am
not able to take responsibility of completeness / correctness of the
same.
[1]: http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/3.3-rc2-dma-v6
[2]: git://git.linaro.org/people/sumitsemwal/linux-3.x.git 'dev' branch
[3]: http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/42966/focusB968
[4]: http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/43793
Best regards,
~Sumit.
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Laurent Pinchart @ 2012-02-17 18:46 UTC (permalink / raw)
To: Daniel Vetter
Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
Magnus Damm, Marcus Lorentzon, dri-devel, Alexander Deucher,
Rob Clark, linux-media, Marek Szyprowski
In-Reply-To: <20120217095554.GA5511@phenom.ffwll.local>
Hi Daniel,
On Friday 17 February 2012 10:55:54 Daniel Vetter wrote:
> On Fri, Feb 17, 2012 at 12:25:51AM +0100, Laurent Pinchart wrote:
> > Hello everybody,
> >
> > First of all, I would like to thank all the attendees for their
> > participation in the mini-summit that helped make the meeting a success.
> >
> > Here are my consolidated notes that cover both the Linaro Connect meeting
> > and the ELC meeting. They're also available at
> > http://www.ideasonboard.org/media/meetings/.
>
> Looks like you've been all really busy ;-)
I like to think so :-)
> A few quick comments below.
Thanks for your feedback.
> > Kernel Display and Video API Consolidation mini-summit at ELC 2012
> > ------------------------------------------------------------------
>
> [snip]
>
> > *** Common video mode data structure and EDID parser ***
> >
> > Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
> >
> > The DRM EDID parser is currently the most advanced implementation and
> > will
> > be taken as a starting point.
> >
> > Different subsystems use different data structures to describe video
> > mode/timing information:
> >
> > - struct drm_mode_modeinfo in DRM/KMS
> > - struct fb_videomode in FBDEV
> > - struct v4l2_bt_timings in V4L2
> >
> > A new common video mode/timing data structure (struct
> > media_video_mode_info, exact name is to be defined), not tied to any
> > specific subsystem, is required to share the EDID parser. That
> > structure won't be exported to userspace.
> >
> > Helper functions will be implemented in the subsystems to convert
> > between
> > that generic structure and the various subsystem-specific structures.
> >
> > The mode list is stored in the DRM connector in the EDID parser. A new
> > mode
> > list data structure can be added, or a callback function can be used by
> > the
> > parser to give modes one at a time to the caller.
> >
> > 3D needs to be taken into account (this is similar to interlacing).
> >
> > Action points:
> > - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.
>
> I think we should include kernel cmdline video mode parsing here, afaik
> kms and fbdev are rather similar (won't work if they're too different,
> obviously).
Good point. I'll add that to the notes and will look into it.
> [snip]
>
> > *** Central 4CC Documentation ***
> >
> > Goal: Define and document 4CCs in a central location to make sure 4CCs
> > won't overlap or have different meanings for different subsystems.
> >
> > DRM and V4L2 define their own 4CCs:
> >
> > - include/drm/drm-fourccs.h
> > - include/linux/videodev2.h
> >
> > A new header file will centralize the definitions, with a new
> > cross-subsystem prefix. DRM and V4L2 4CCs will be redefined as aliases
> > for
> > the new centralized 4CCs.
> >
> > Colorspace (including both color matrix and Y/U/V ranges) should be
> > shared as well. VDPAU (and VAAPI ?) pass the color matrix to userspace.
> > The kernel API should not be more restrictive, but we just need a couple
> > of presets in most cases. We can define a list of common presets, with a
> > way to upload a custom matrix.
> >
> > Action points:
> > - Start with the V4L2 documentation, create a shared header file. Sakari
> > to work on a proposal.
>
> I'm looking forward to the bikeshed discussion here ;-)
> </snide-remark>
I'm certainly going to NACK if we try to paint 4CCs in the wrong colorspace
;-)
> > *** Split KMS and GPU Drivers ***
> >
> > Goal: Split KMS and GPU drivers with in kernel API inbetween.
> >
> > In most (all ?) SoCs, the GPU and the display controller are separate
> > devices. Splitting them into separate drivers would allow reusing the
> > GPU driver with different devices (e.g. using a single common PowerVR
> > kernel module with different display controller drivers). The same
> > approach can be used on the desktop for the multi-GPU case and the USB
> > display case.
> >
> > - OMAP already separates the GPU and DSS drivers, but the GPU driver is
> > some kind of DSS plugin. This isn't a long-term approach.
> > - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
> > into display subsystem since UMP, GPU has own memory management codes.
> >
> > One of the biggest challenges would be to get GPU vendors to use this
> > new model. ARM could help here, by making the Mali kernel driver split
> > from the display controller drivers. Once one vendor jumps onboard,
> > others could have a bigger incentive to follow.
> >
> > Action points:
> > - Rob planning to work on a reference implementation, as part of the
> > sync object case. This is a pretty long term plan.
> >
> > - Jesse will handle the coordination with ARM for Mali.
>
> Imo splitting up SoC drm drivers into separate drivers for the different
> blocks makes tons of sense. The one controlling the display subsystem
> would then also support kms, all the others would just support gem and
> share buffers with dma_buf (and maybe synchronize with some new-fangled
> sync objects). Otoh it doesn't make much sense to push this if we don't
> have at least one of the SoC ip block verndors on board. We can dream ...
That's the conclusion we came up to. ARM might be able to help here with Mali,
and we could then try to sell the idea to other vendors when a reference
implementation will be complete (or at least usable enough).
> [snip]
>
> > *** Sync objects ***
> >
> > Goal: Implement in-kernel support for buffer swapping, dependency
> > system, sync objects, queue/dequeue userspace API (think EGLstream &
> > EGLsync)
> >
> > This can be implemented in kernel-space (with direct communication
> > between drivers to schedule buffers around), user-space (with ioctls to
> > queue/dequeue buffers), or a mix of both. SoCs with direct sync object
> > support at the hardware level between different IP blocks can be
> > foreseen in the (near ?) future. A kernel-space API would then be
> > needed.
> >
> > Sharing sync objects between subsystems could result in the creation of
> > a cross-subsystem queue/dequeue API. Integration with dma_buf would make
> > sense, a dma_buf_pool object would then likely be needed.
> >
> > If the SoC supports direct signaling between IP blocks, this could be
> > considered (and implemented) as a pipeline configurable through the
> > Media Controller API. However, applications will then need to be link-
> > aware. Using sync/stream objects would offer a single API to userspace,
> > regardless of whether the synchronization is handled by the CPU in
> > kernel space or by the IP blocks directly.
> >
> > Sync objects are not always tied to buffers, they need to be implemented
> > as stand-alone objects on the kernel side. However, when exposing the
> > sync object to userspace in order to share it between devices, all
> > current use cases involve dma-buf. The first implementation will thus not
> > expose the sync objects explicitly to userspace, but associate them with
> > a dma-buf. If sync objects with no associated dma-buf are later needed,
> > an explicit userspace API can be added.
> >
> > eventfd is a possible candidate for sync object implementation.
> >
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=in
> > clude/linux/eventfd.h
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=D
> > ocumentation/cgroups/cgroups.txt
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=D
> > ocumentation/cgroups/memory.txt
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=D
> > ocumentation/virtual/kvm/api.txt
> >
> > Action points:
> > - TBD, will be on the agenda for the Graphics Summit @ELC2012.
>
> I've already started discussing this a bit with Rob. I'm not sure whether
> implicitly associating a sync object with a dma_buf makes sense, afaik
> sync objects can be used rather independently from buffers. But this is a
> long-term feature, so we still have plenty of time to discuss this.
I think we need to work on this one step at a time. Associating a sync object
with a dma_buf is probably not going to solve all our problems in the long
term, but it might provide us with a first solution that doesn't require
exposing the sync object API to userspace. I'm not saying we need to do this,
but it could be a reasonable first step that would buy us some time while we
sort out the sync object userspace API.
> [snip]
>
> > *** 2D Kernel APIs ***
> >
> > Goal: Expose a 2D acceleration API to userspace for devices that support
> > hardware-accelerated 2D rendering.
> >
> > If the hardware is based on a command stream, a userspace library is
> > needed anyway to build the command stream. A 2D kernel API would then
> > not be very useful. This could be split to a DRM device without a KMS
> > interface.
>
> Imo we should ditch this - fb accel doesn't belong into the kernel. Even
> on hw that still has a blitter for easy 2d accel without a complete 3d
> state setup necessary, it's not worth it. Chris Wilson from our team once
> played around with implementing fb accel in the kernel (i915 hw still has
> a blitter engine in the latest generations). He quickly noticed that to
> have decent speed, competitive with s/w rendering by the cpu he needs the
> entire batch and buffer management stuff from userspace. And to really
> beat the cpu, you need even more magic.
>
> If you want fast 2d accel, use something like cairo.
Our conclusion on this is that we should not expose an explicit 2D
acceleration API at the kernel level. If really needed, hardware 2D
acceleration could be implemented as a DRM device to handle memory management,
commands ring setup, synchronization, ... but I'm not even sure if that's
worth it. I might not have conveyed it well in my notes.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Laurent Pinchart @ 2012-02-17 18:49 UTC (permalink / raw)
To: Semwal, Sumit
Cc: Sakari Ailus, Jesse Barker, Jesse Barnes, Rob Clark, Pawel Osciak,
Marek Szyprowski, Tomasz Stanislawski, Magnus Damm,
Marcus Lorentzon, Alexander Deucher, linux-media, dri-devel,
linux-fbdev
In-Reply-To: <CAB2ybb_-ULCsfS48u7HQiRDLG5y-X2rmyXvHBcCRtc=m-732hQ@mail.gmail.com>
Hi Sumit,
On Friday 17 February 2012 16:37:35 Semwal, Sumit wrote:
> On Fri, Feb 17, 2012 at 4:55 AM, Laurent Pinchart wrote:
> > Hello everybody,
> >
> > First of all, I would like to thank all the attendees for their
> > participation in the mini-summit that helped make the meeting a success.
>
> <snip>
>
> > *** dma-buf Implementation in V4L2 ***
> >
> > Goal: Implement the dma-buf API in V4L2.
> >
> > Sumit Semwal has submitted patches to implement the dma-buf importer role
> > in videobuf2. Tomasz Stanislawski has then submitted incremental patches
> > to add exporter role support.
> >
> > Action points:
> > - Create a git branch to host all the latest patches. Sumit will provide
> > that.
>
> Against my Action Item: I have created the following branch at my
> github (obviously, it is an RFC branch only)
That was very fast :-) Thank you for your work on this.
> tree: git://github.com/sumitsemwal/kernel-omap4.git
> branch: 3.3rc3-v4l2-dmabuf-RFCv1
>
> As the name partially suggests, it is based out of:
> 3.3-rc3 +
> dmav6 [1] +
> some minor dma-buf updates [2] +
> my v4l2-as-importer RFC [3] +
> Tomasz' RFC for v4l2-as-exporter (and related patches) [4]
>
> Since Tomasz' RFC had a patch-pair which first removed and then added
> drivers/media/video/videobuf2-dma-contig.c file, I 'combined' these
> into one - but since the patch-pair heavily refactored the file, I am
> not able to take responsibility of completeness / correctness of the
> same.
No worries. The branch's main purpose is to provide people with a starting
point to use dma-buf, patch review will go through mailing lists anyway.
> [1]:
> http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/3.3
> -rc2-dma-v6 [2]: git://git.linaro.org/people/sumitsemwal/linux-3.x.git 'dev'
> branch [3]:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/4296
> 6/focusB968 [4]:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/4379
> 3
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Adam Jackson @ 2012-02-17 19:42 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
Magnus Damm, Marcus Lorentzon, dri-devel, Alexander Deucher,
Rob Clark, linux-media, Marek Szyprowski
In-Reply-To: <1775349.d0yvHiVdjB@avalon>
On 2/16/12 6:25 PM, Laurent Pinchart wrote:
> *** Common video mode data structure and EDID parser ***
>
> Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
>
> The DRM EDID parser is currently the most advanced implementation and will
> be taken as a starting point.
>
> Different subsystems use different data structures to describe video
> mode/timing information:
>
> - struct drm_mode_modeinfo in DRM/KMS
> - struct fb_videomode in FBDEV
> - struct v4l2_bt_timings in V4L2
>
> A new common video mode/timing data structure (struct media_video_mode_info,
> exact name is to be defined), not tied to any specific subsystem, is
> required to share the EDID parser. That structure won't be exported to
> userspace.
>
> Helper functions will be implemented in the subsystems to convert between
> that generic structure and the various subsystem-specific structures.
I guess. I don't really see a reason not to unify the structs too, but
then I don't have binary blobs to pretend to be ABI-compatible with.
> The mode list is stored in the DRM connector in the EDID parser. A new mode
> list data structure can be added, or a callback function can be used by the
> parser to give modes one at a time to the caller.
>
> 3D needs to be taken into account (this is similar to interlacing).
Would also be pleasant if the new mode structure had a reasonable way of
representing borders, we copied that mistake from xserver and have been
regretting it.
> Action points:
> - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.
I'm totally in favor of this. I've long loathed fbdev having such a
broken parser, I just never got around to fixing it since we don't use
fbdev in any real way.
The existing drm_edid.c needs a little detangling, DDC fetch and EDID
parse should be better split. Shouldn't be too terrible though.
Has the embedded world seen any adoption of DisplayID? I wrote a fair
bit of a parser for it at one point [1] but I've yet to find a machine
that's required it.
> *** Split KMS and GPU Drivers ***
>
> Goal: Split KMS and GPU drivers with in kernel API inbetween.
>
> In most (all ?) SoCs, the GPU and the display controller are separate
> devices. Splitting them into separate drivers would allow reusing the GPU
> driver with different devices (e.g. using a single common PowerVR kernel
> module with different display controller drivers). The same approach can be
> used on the desktop for the multi-GPU case and the USB display case.
>
> - OMAP already separates the GPU and DSS drivers, but the GPU driver is some
> kind of DSS plugin. This isn't a long-term approach.
> - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
> into display subsystem since UMP, GPU has own memory management codes.
>
> One of the biggest challenges would be to get GPU vendors to use this new
> model. ARM could help here, by making the Mali kernel driver split from the
> display controller drivers. Once one vendor jumps onboard, others could have
> a bigger incentive to follow.
Honestly I want this for Intel already, given how identical Poulsbo's
display block is to gen3.
> *** HDMI CEC Support ***
>
> Goal: Support HDMI CEC and offer a userspace API for applications.
>
> A new kernel API is needed and must be usable by KMS, V4L2 and possibly
> LIRC. There's ongoing effort from Cisco to implement HDMI CEC support. Given
> their background, V4L2 is their initial target. A proposal is available at
> http://www.mail-archive.com/linux-media@vger.kernel.org/msg29241.html with a
> sample implementation at
> http://git.linuxtv.org/hverkuil/cisco.git/shortlog/refs/heads/cobalt-
> mainline
> (drivers/media/video/adv7604.c and ad9389b.c.
>
> In order to avoid API duplication, a new CEC subsystem is probably needed.
> CEC could be modeled as a bus, or as a network device. With the network
> device approach, we could have both kernel and userspace protocol handlers.
I'm not a huge fan of userspace protocol for this. Seems like it'd just
give people more license to do their own subtly-incompatible things that
only work between devices of the same vendor. Interoperability is the
_whole_ point of CEC. (Yes I know every vendor tries to spin it as
their own magical branded thing, but I'd appreciate it if they grew up.)
[1] -
http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/modes/xf86DisplayIDModes.c
- ajax
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Keith Packard @ 2012-02-18 0:56 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
Marcus Lorentzon, Magnus Damm, dri-devel, Alexander Deucher,
Rob Clark, Marek Szyprowski, linux-media
In-Reply-To: <1775349.d0yvHiVdjB@avalon>
<#part sign=pgpmime>
On Fri, 17 Feb 2012 00:25:51 +0100, Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:
> *** Synchronous pipeline changes ***
>
> Goal: Create an API to apply complex changes to a video pipeline atomically.
>
> Needed for complex camera use cases. On the DRM/KMS side, the approach is to
> use one big ioctl to configure the whole pipeline.
This is the only credible approach for most desktop chips -- you must
have the whole configuration available before you can make any
commitment to supporting the requested modes.
> One solution is a commit ioctl, through the media controller device, that
> would be dispatched to entities internally with a prepare step and a commit
> step.
The current plan for the i915 KMS code is to use a single ioctl -- the
application sends a buffer full of configuration commands down to the
kernel which can then figure out whether it can be supported or not.
The kernel will have to store the intermediate data until the commit
arrives anyways, and you still need a central authority in the kernel
controlling the final commit decision.
--
keith.packard@intel.com
^ permalink raw reply
* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Clark, Rob @ 2012-02-18 17:53 UTC (permalink / raw)
To: Adam Jackson
Cc: Laurent Pinchart, Tomasz Stanislawski, linux-fbdev, Sakari Ailus,
Pawel Osciak, Magnus Damm, Marcus Lorentzon, dri-devel,
Alexander Deucher, linux-media, Marek Szyprowski
In-Reply-To: <4F3EADAA.9090702@redhat.com>
On Fri, Feb 17, 2012 at 1:42 PM, Adam Jackson <ajax@redhat.com> wrote:
> On 2/16/12 6:25 PM, Laurent Pinchart wrote:
>
>> Helper functions will be implemented in the subsystems to convert
>> between
>> that generic structure and the various subsystem-specific structures.
>
>
> I guess. I don't really see a reason not to unify the structs too, but then
> I don't have binary blobs to pretend to be ABI-compatible with.
>
this is just for where timing struct is exposed to userspace
BR,
-R
^ permalink raw reply
* [PATCH] drivers/video/pxa168fb.c: use devm_ functions
From: Julia Lawall @ 2012-02-18 18:19 UTC (permalink / raw)
To: Florian Tobias Schandinat; +Cc: kernel-janitors, linux-fbdev, linux-kernel
From: Julia Lawall <Julia.Lawall@lip6.fr>
The various devm_ functions allocate memory that is released when a driver
detaches. This patch uses these functions for data that is allocated in
the probe function of a platform device and is only freed in the remove
function.
By using devm_ioremap, it also removes a potential memory leak, because
there was no call to iounmap in the probe function.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/video/pxa168fb.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 8384b94..f146089 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -21,6 +21,7 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
@@ -670,7 +671,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
/*
* Map LCD controller registers.
*/
- fbi->reg_base = ioremap_nocache(res->start, resource_size(res));
+ fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start,
+ resource_size(res));
if (fbi->reg_base = NULL) {
ret = -ENOMEM;
goto failed_free_info;
@@ -739,8 +741,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
/*
* Register irq handler.
*/
- ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED,
- info->fix.id, fbi);
+ ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
+ IRQF_SHARED, info->fix.id, fbi);
if (ret < 0) {
dev_err(&pdev->dev, "unable to request IRQ\n");
ret = -ENXIO;
@@ -759,14 +761,12 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
ret = -ENXIO;
- goto failed_free_irq;
+ goto failed_free_cmap;
}
platform_set_drvdata(pdev, fbi);
return 0;
-failed_free_irq:
- free_irq(irq, fbi);
failed_free_cmap:
fb_dealloc_cmap(&info->cmap);
failed_free_clk:
@@ -808,13 +808,10 @@ static int __devexit pxa168fb_remove(struct platform_device *pdev)
fb_dealloc_cmap(&info->cmap);
irq = platform_get_irq(pdev, 0);
- free_irq(irq, fbi);
dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
info->screen_base, info->fix.smem_start);
- iounmap(fbi->reg_base);
-
clk_disable(fbi->clk);
clk_put(fbi->clk);
^ permalink raw reply related
* [PATCH 5/5] fbdev: s/#if CONFIG/#ifdef CONFIG/
From: Geert Uytterhoeven @ 2012-02-19 15:11 UTC (permalink / raw)
To: Jiri Kosina
Cc: linux-kernel, Geert Uytterhoeven, Florian Tobias Schandinat,
linux-fbdev
In-Reply-To: <1329664319-3128-1-git-send-email-geert@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: linux-fbdev@vger.kernel.org
---
drivers/video/au1100fb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index de9da67..4da1895 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -532,7 +532,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
for (page = (unsigned long)fbdev->fb_mem;
page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
page += PAGE_SIZE) {
-#if CONFIG_DMA_NONCOHERENT
+#ifdef CONFIG_DMA_NONCOHERENT
SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
#else
SetPageReserved(virt_to_page(page));
--
1.7.0.4
^ permalink raw reply related
* [PATCH] i740fb: fix compile error when CONFIG_MTRR is not selected
From: Florian Tobias Schandinat @ 2012-02-19 21:33 UTC (permalink / raw)
To: linux-fbdev
Cc: linux-kernel, Florian Tobias Schandinat, Ondrej Zary,
Stephen Rothwell, linux-next
In-Reply-To: <20120216162900.e2dd164732084f48e5b239f0@canb.auug.org.au>
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
drivers/video/i740fb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c
index 8be0302..fe574d8 100644
--- a/drivers/video/i740fb.c
+++ b/drivers/video/i740fb.c
@@ -1179,9 +1179,9 @@ static void __devexit i740fb_remove(struct pci_dev *dev)
struct fb_info *info = pci_get_drvdata(dev);
if (info) {
-#ifdef CONFIG_MTRR
struct i740fb_par *par = info->par;
+#ifdef CONFIG_MTRR
if (par->mtrr_reg >= 0) {
mtrr_del(par->mtrr_reg, 0, 0);
par->mtrr_reg = -1;
--
1.7.2.5
^ permalink raw reply related
* Re: [PATCH 00/13] sa1100fb cleanups
From: Florian Tobias Schandinat @ 2012-02-19 22:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20120204093744.GQ889@n2100.arm.linux.org.uk>
Hi Russell,
On 02/04/2012 09:37 AM, Russell King - ARM Linux wrote:
> Here's another bunch of SA11x0 stuff - its framebuffer driver. This
> set of patches fixes some section mismatch warnings, moves the board
> configuration out to the board files, converts the Shannon stuff to
> use gpiolib rather than poking at GPDR/GPSR/GPCR directly.
>
> The function hooks for LCD and backlight power control are moved into
> the platform data passed from the board, eliminating the global function
> pointers.
This series looks good to me.
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> This series will conflict with the previous series (in the case of
> Assabet, the conflict is quite large) so I'd prefer to keep this in my
> tree for the next merge window.
Sure, feel free to proceed with this series as you like.
Best regards,
Florian Tobias Schandinat
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox