[PATCH 2/3] acpi_video: Intel video is not always i915
On Tue, 24 Apr 2012 22:02:18 +0100 Matthew Garrett wrote: > On Tue, Apr 24, 2012 at 04:45:01PM +0100, Alan Cox wrote: > > From: Alan Cox > > > > Handle the GMA500/600/36x0 cases. Also stop it poking at random registers on > > the i740 cards that may be out there still. > > The PowerVR Intels I'd seen had the opregion address in the 0xfc > register as well. Is this no longer true on the latest? PowerVR does - i740 never did. The PowerVR 0xfc poking also doesn't currently work once the driver takes over because it isn't yet implementing the driver end of the weird ACPI messaging/event stuff. Once it does the GMA500 will be able to do an ACPI video register, but we will still need the check to get the ifdeffery right for what drivers are compiled for the kernel. Alan
[PATCH 2/3] acpi_video: Intel video is not always i915
On Tue, Apr 24, 2012 at 11:31:17PM +0100, Alan Cox wrote: > On Tue, 24 Apr 2012 22:02:18 +0100 > Matthew Garrett wrote: > > The PowerVR Intels I'd seen had the opregion address in the 0xfc > > register as well. Is this no longer true on the latest? > > PowerVR does - i740 never did. > > The PowerVR 0xfc poking also doesn't currently work once the driver takes > over because it isn't yet implementing the driver end of the weird ACPI > messaging/event stuff. > > Once it does the GMA500 will be able to do an ACPI video register, but we > will still need the check to get the ifdeffery right for what drivers are > compiled for the kernel. Right now you seem to set opregion unconditionally on PVR, which seems to be equivalent to the 0xfc check that was there before - I can understand excluding i740, but the PVR check could be left with the gen hardware one? -- Matthew Garrett | mjg59 at srcf.ucam.org
[Bug 49110] AMDILCFGStructurizer.cpp:1751:3: error: 'isCurrentDebugType' was not declared in this scope
https://bugs.freedesktop.org/show_bug.cgi?id=49110 --- Comment #1 from Tom Stellard 2012-04-24 16:04:18 PDT --- I think this happens when you build Mesa with debugging enabled and LLVM without it enabled. It's still a bug though. For now, you could try building a debug version of both Mesa and LLVM. I think that will fix it. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
[PATCH 2/3] acpi_video: Intel video is not always i915
On Tue, Apr 24, 2012 at 04:45:01PM +0100, Alan Cox wrote: > From: Alan Cox > > Handle the GMA500/600/36x0 cases. Also stop it poking at random registers on > the i740 cards that may be out there still. The PowerVR Intels I'd seen had the opregion address in the 0xfc register as well. Is this no longer true on the latest? -- Matthew Garrett | mjg59 at srcf.ucam.org
Linux 3.4-rc4
On 2012-04-23 21:03 -0400, Nick Bowler wrote: > On 2012-04-22 22:45 -0400, Konrad Rzeszutek Wilk wrote: > > On Sun, Apr 22, 2012 at 08:05:54PM -0400, Nick Bowler wrote: > > > Following up on the above, the commit which introduces the panics during > > > boot is this one: > > > > > > commit 8e7e70522d760c4ccd4cd370ebfa0ba69e006c6e > > > Author: Jerome Glisse > > > Date: Wed Nov 9 17:15:26 2011 -0500 > > > > > > drm/ttm: isolate dma data from ttm_tt V4 [...] > > dea7e0a ttm: fix agp since ttm tt rework > > > > fixed that. > > Yes, I just tested this commit and the one immediately before it. The > one before crashes in the usual way, and dea7e0a boots (with the VGA > output black as in the original report). So this fixed the crash. OK, here's what I did: - Since dea7e0a is the first commit that both (a) boots and (b) has broken VGA, I checked it out on a new branch: git checkout -b crazy dea7e0a - Next, I reverted *all* (well, I missed one by accident) the remaining nouveau-specific commits between 3230cfc34 ("drm/nouveau: enable the ttm dma pool when swiotlb is active V3") (i.e., the last commit that (a) boots and (b) has non-broken VGA) and dea7e0a: git revert --no-edit 0c101461e267..f7b24c42da1a - Amazingly, the resulting kernel booted and had working VGA, so I did a "backwards" bisect on this branch of reverts. In a strange twist of fate, this actually managed to produce bootable kernels the entire time. The bisection pinpointed the following commit as the culprit: commit a0b25635515ef5049f93b032a1e37f18b16e0f6f Author: Ben Skeggs Date: Mon Nov 21 16:41:48 2011 +1000 drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues - moves out of nouveau_bios.c and demagics the logical state definitions - simplifies chipset-specific driver interface - makes most of gpio irq handling common, will use for nv4x hpd later - api extended to allow both direct gpio access, and access using the logical function states - api extended to allow for future use of gpio extender chips - pre-nv50 was handled very badly, the main issue being that all GPIOs were being treated as output-only. - fixes nvd0 so gpio changes actually stick, magic reg needs bashing Signed-off-by: Ben Skeggs Unfortunately, there are a number of seemingly non-trivial conflicts trying to revert just this one gigantic commit. So to avoid any conflicts, I reverted all of the following (in this order) on top of 3.3.3 (there are even more conflicts trying to revert on top of Linus' master): 7df898b1a70b ("drm/nouveau/disp: check that panel power gpio is enabled at init time") 52c4d767437b ("drm/nouveau: move hpd enable/disable to common code") 47e5d5cb83d4 ("drm/nv40/disp: implement support for hotplug irq") a0b25635515e ("drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues") and my VGA is working again! Cheers, -- Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)
[RFC PATCH 5/5] drm/nouveau: gpu lockup recovery
On Mon, Apr 23, 2012 at 06:56:44PM +0200, Martin Peres wrote: > Le 23/04/2012 18:32, Marcin Slusarz a ?crit : > > > > Just run piglit. Even "quick" tests can cause ~5 lockups (it eventually > > messes > > up DDX channel, but this patchset can't fix this case). > > You can run fs-discard-exit-2 test first - for me it causes instant GPU > > lockup. > > > > Marcin > Great, Thanks. > > Did you have a look at > https://bugs.freedesktop.org/show_bug.cgi?id=40886 and > http://xorg.freedesktop.org/wiki/SummerOfCodeIdeas ? Yeah, I've seen them some time ago. > The Ubuntu xorg devs were looking for something like this, but they also > wanted a lockup report. Are you also interested on working on it ? Yes, when this patchset will be applied, I'm going to work on improving error reporting. Marcin
[PATCH 1/5] drm: add optional per device rwsem for all ioctls
On Mon, Apr 23, 2012 at 09:51:48AM +0200, Daniel Vetter wrote: > On Mon, Apr 23, 2012 at 12:18:28AM +0200, Marcin Slusarz wrote: > > Nouveau, in normal circumstances, does not need device lock for every ioctl, > > but incoming "gpu reset" code needs exclusive access to the device. > > This commit adds drm_driver flag which turns on read lock ioctl > > encapsulation. > > > > Signed-off-by: Marcin Slusarz > > Why can't we just move this down to nouveau driver code? Ok, I think it's easily possible by wrapping drm_ioctl. > So why can't nouveau do the same? Also, if this is indeed necessary and we > add this as some mandatory core infrastructure, it's not good enough: In > i915 we go to great lengths to ensure that all processes waiting for gpu > reset are still interruptible, in case the gpu reset dies unexpectedly > (which happens), so this would need to be improved. I came up with a scheme where down_read can be made interruptible. I'll post both changes in a few days. (Unfortunately adding proper down_read_interruptible / down_write_interruptible require a bit of unfunny work - 8 architectures have their own code for rwsems) Marcin
[Nouveau] [PATCH 2/5] drm/nouveau: base fence timeout on time of emission
On Tue, Apr 24, 2012 at 12:37:34PM +1000, Ben Skeggs wrote: > On Mon, 2012-04-23 at 00:18 +0200, Marcin Slusarz wrote: > > Wait loop can be interrupted by signal, so if signals are raised > > periodically (e.g. SIGALRM) this loop may never finish. Use > > emission time as a base for fence timeout. > Ah, thanks for tackling this issue. It's been long on my list of things > to do, but never quite made it to the top. > > Rather than hardcoding the timeout in fence_wait(), I think perhaps > storing "fence->timeout = jiffies + (whatever * HZ);" is a better plan. > I can forsee us wanting longer timeouts for certain operations > (particularly long compute operations) in the future. Yeah, good idea. Later, we will probably need to add code which will keep extending this timeout as long as gpu is progressing. Marcin
[PATCH] drm/edid: Try harder to fix up base EDID blocks
On Mon, 16 Apr 2012 10:40:08 -0400, Adam Jackson wrote: > Requiring the first byte of the EDID base block header to be 0 means we > don't fix up as many transfer errors as we could. Instead have the > callers specify whether it's meant to be block 0 or not, and > conditionally run header fixup based on that. > > Bugzilla: https://bugzilla.redhat.com/812890 > Signed-off-by: Adam Jackson The patch does watch it says on the tin. I don't pretend to know how frequent this corruption is, but as it stands the current code fails to be as effective as it could be. Reviewed-by: Chris Wilson -Chris -- Chris Wilson, Intel Open Source Technology Centre
Re: Linux 3.4-rc4
On Tue, 2012-04-24 at 21:35 -0400, Nick Bowler wrote: > On 2012-04-23 21:03 -0400, Nick Bowler wrote: > > On 2012-04-22 22:45 -0400, Konrad Rzeszutek Wilk wrote: > > > On Sun, Apr 22, 2012 at 08:05:54PM -0400, Nick Bowler wrote: > > > > Following up on the above, the commit which introduces the panics during > > > > boot is this one: > > > > > > > > commit 8e7e70522d760c4ccd4cd370ebfa0ba69e006c6e > > > > Author: Jerome Glisse > > > > Date: Wed Nov 9 17:15:26 2011 -0500 > > > > > > > > drm/ttm: isolate dma data from ttm_tt V4 > [...] > > > dea7e0a ttm: fix agp since ttm tt rework > > > > > > fixed that. > > > > Yes, I just tested this commit and the one immediately before it. The > > one before crashes in the usual way, and dea7e0a boots (with the VGA > > output black as in the original report). So this fixed the crash. > > OK, here's what I did: > > - Since dea7e0a is the first commit that both (a) boots and (b) has >broken VGA, I checked it out on a new branch: > > git checkout -b crazy dea7e0a > > - Next, I reverted *all* (well, I missed one by accident) the remaining >nouveau-specific commits between 3230cfc34 ("drm/nouveau: enable the >ttm dma pool when swiotlb is active V3") (i.e., the last commit that >(a) boots and (b) has non-broken VGA) and dea7e0a: > > git revert --no-edit 0c101461e267..f7b24c42da1a > > - Amazingly, the resulting kernel booted and had working VGA, so I did >a "backwards" bisect on this branch of reverts. In a strange twist >of fate, this actually managed to produce bootable kernels the entire >time. The bisection pinpointed the following commit as the culprit: > > commit a0b25635515ef5049f93b032a1e37f18b16e0f6f > Author: Ben Skeggs > Date: Mon Nov 21 16:41:48 2011 +1000 > > drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues > > - moves out of nouveau_bios.c and demagics the logical state definitions > - simplifies chipset-specific driver interface > - makes most of gpio irq handling common, will use for nv4x hpd later > - api extended to allow both direct gpio access, and access using the > logical function states > - api extended to allow for future use of gpio extender chips > - pre-nv50 was handled very badly, the main issue being that all GPIOs > were being treated as output-only. > - fixes nvd0 so gpio changes actually stick, magic reg needs bashing > > Signed-off-by: Ben Skeggs Excellent! That makes things possible. Are you able to mount debugfs, and email /debugfs/dri/0/vbios.rom for me (privately if you wish) and I'll attempt to track down what broke for you. Thanks! Ben. > > Unfortunately, there are a number of seemingly non-trivial conflicts > trying to revert just this one gigantic commit. So to avoid any > conflicts, I reverted all of the following (in this order) on top of > 3.3.3 (there are even more conflicts trying to revert on top of Linus' > master): > > 7df898b1a70b ("drm/nouveau/disp: check that panel power gpio is enabled at > init time") > 52c4d767437b ("drm/nouveau: move hpd enable/disable to common code") > 47e5d5cb83d4 ("drm/nv40/disp: implement support for hotplug irq") > a0b25635515e ("drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a > number of issues") > > and my VGA is working again! > > Cheers, ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/5] drm/exynos: added vp scaling feature for hdmi
This patch adds vp scaling feature for exynos hdmi. Scaling ratio between source and destination is used for width and height. Also meaningless variables to set registers are cleaned. Signed-off-by: Seung-Woo Kim Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_mixer.c | 88 1 files changed, 33 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 3bc01a6..68ef010 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -54,6 +54,8 @@ struct hdmi_win_data { unsigned intfb_y; unsigned intfb_width; unsigned intfb_height; + unsigned intsrc_width; + unsigned intsrc_height; unsigned intmode_width; unsigned intmode_height; unsigned intscan_flags; @@ -351,10 +353,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) struct mixer_resources *res = &ctx->mixer_res; unsigned long flags; struct hdmi_win_data *win_data; - unsigned int full_width, full_height, width, height; unsigned int x_ratio, y_ratio; - unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; - unsigned int mode_width, mode_height; unsigned int buf_num; dma_addr_t luma_addr[2], chroma_addr[2]; bool tiled_mode = false; @@ -381,21 +380,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) return; } - full_width = win_data->fb_width; - full_height = win_data->fb_height; - width = win_data->crtc_width; - height = win_data->crtc_height; - mode_width = win_data->mode_width; - mode_height = win_data->mode_height; - /* scaling feature: (src << 16) / dst */ - x_ratio = (width << 16) / width; - y_ratio = (height << 16) / height; - - src_x_offset = win_data->fb_x; - src_y_offset = win_data->fb_y; - dst_x_offset = win_data->crtc_x; - dst_y_offset = win_data->crtc_y; + x_ratio = (win_data->src_width << 16) / win_data->crtc_width; + y_ratio = (win_data->src_height << 16) / win_data->crtc_height; if (buf_num == 2) { luma_addr[0] = win_data->dma_addr; @@ -403,7 +390,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) } else { luma_addr[0] = win_data->dma_addr; chroma_addr[0] = win_data->dma_addr - + (full_width * full_height); + + (win_data->fb_width * win_data->fb_height); } if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) { @@ -412,8 +399,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; } else { - luma_addr[1] = luma_addr[0] + full_width; - chroma_addr[1] = chroma_addr[0] + full_width; + luma_addr[1] = luma_addr[0] + win_data->fb_width; + chroma_addr[1] = chroma_addr[0] + win_data->fb_width; } } else { ctx->interlace = false; @@ -434,26 +421,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); /* setting size of input image */ - vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(full_width) | - VP_IMG_VSIZE(full_height)); + vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) | + VP_IMG_VSIZE(win_data->fb_height)); /* chroma height has to reduced by 2 to avoid chroma distorions */ - vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(full_width) | - VP_IMG_VSIZE(full_height / 2)); + vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) | + VP_IMG_VSIZE(win_data->fb_height / 2)); - vp_reg_write(res, VP_SRC_WIDTH, width); - vp_reg_write(res, VP_SRC_HEIGHT, height); + vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width); + vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height); vp_reg_write(res, VP_SRC_H_POSITION, - VP_SRC_H_POSITION_VAL(src_x_offset)); - vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset); + VP_SRC_H_POSITION_VAL(win_data->fb_x)); + vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y); - vp_reg_write(res, VP_DST_WIDTH, width); - vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset); + vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width); + vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x); if (ctx->interlace) { - vp_reg_write(res, VP_DST_HEIGHT, h
[PATCH 4/5] drm/exynos: added source size to overlay structure
Set plane has source size but exynos overlay structure did not consider it. This patch adds source size to overlay structure. For set crtc, source size is set from crtc size. Signed-off-by: Seung-Woo Kim Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_crtc.c |4 drivers/gpu/drm/exynos/exynos_drm_crtc.h |4 drivers/gpu/drm/exynos/exynos_drm_drv.h |4 drivers/gpu/drm/exynos/exynos_drm_plane.c | 10 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 3486ffe..4afb625 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -105,6 +105,8 @@ int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, overlay->fb_y = pos->fb_y; overlay->fb_width = fb->width; overlay->fb_height = fb->height; + overlay->src_width = pos->src_w; + overlay->src_height = pos->src_h; overlay->bpp = fb->bits_per_pixel; overlay->pitch = fb->pitches[0]; overlay->pixel_format = fb->pixel_format; @@ -153,6 +155,8 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc) pos.crtc_y = 0; pos.crtc_w = fb->width - crtc->x; pos.crtc_h = fb->height - crtc->y; + pos.src_w = pos.crtc_w; + pos.src_h = pos.crtc_h; return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 25f72a6..16b8e21 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h @@ -42,6 +42,8 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); * - the unit is screen coordinates. * @fb_y: offset y on a framebuffer to be displayed * - the unit is screen coordinates. + * @src_w: width of source area to be displayed from a framebuffer. + * @src_h: height of source area to be displayed from a framebuffer. * @crtc_x: offset x on hardware screen. * @crtc_y: offset y on hardware screen. * @crtc_w: width of hardware screen. @@ -50,6 +52,8 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); struct exynos_drm_crtc_pos { unsigned int fb_x; unsigned int fb_y; + unsigned int src_w; + unsigned int src_h; unsigned int crtc_x; unsigned int crtc_y; unsigned int crtc_w; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 1d81417..5f5b362 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -77,6 +77,8 @@ struct exynos_drm_overlay_ops { * - the unit is screen coordinates. * @fb_width: width of a framebuffer. * @fb_height: height of a framebuffer. + * @src_width: width of a partial image to be displayed from framebuffer. + * @src_height: height of a partial image to be displayed from framebuffer. * @crtc_x: offset x on hardware screen. * @crtc_y: offset y on hardware screen. * @crtc_width: window width to be displayed (hardware screen). @@ -108,6 +110,8 @@ struct exynos_drm_overlay { unsigned int fb_y; unsigned int fb_width; unsigned int fb_height; + unsigned int src_width; + unsigned int src_height; unsigned int crtc_x; unsigned int crtc_y; unsigned int crtc_width; diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index f92fe4c..c4c6525 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -41,8 +41,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, container_of(plane, struct exynos_plane, base); struct exynos_drm_overlay *overlay = &exynos_plane->overlay; struct exynos_drm_crtc_pos pos; - unsigned int x = src_x >> 16; - unsigned int y = src_y >> 16; int ret; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -53,10 +51,12 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, pos.crtc_w = crtc_w; pos.crtc_h = crtc_h; - pos.fb_x = x; - pos.fb_y = y; + /* considering 16.16 fixed point of source values */ + pos.fb_x = src_x >> 16; + pos.fb_y = src_y >> 16; + pos.src_w = src_w >> 16; + pos.src_h = src_h >> 16; - /* TODO: scale feature */ ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos); if (ret < 0) return ret; -- 1.7.4.1
[PATCH 3/5] drm/exynos: add additional display mode for hdmi
1080p at 30Hz mode is added to hdmi display mode. Signed-off-by: Seung-Woo Kim Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_hdmi.c | 65 ++ 1 files changed, 65 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 5ca0a9f..a137e9e 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -362,6 +362,13 @@ static const u8 hdmiphy_conf27_027[32] = { 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }; +static const u8 hdmiphy_conf74_176[32] = { + 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08, + 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, +}; + static const u8 hdmiphy_conf74_25[32] = { 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, @@ -751,6 +758,63 @@ static const struct hdmi_preset_conf hdmi_conf_1080i60 = { }, }; +static const struct hdmi_preset_conf hdmi_conf_1080p30 = { + .core = { + .h_blank = {0x18, 0x01}, + .v2_blank = {0x65, 0x04}, + .v1_blank = {0x2d, 0x00}, + .v_line = {0x65, 0x04}, + .h_line = {0x98, 0x08}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0x56, 0x00}, + .h_sync_end = {0x82, 0x00}, + .v_sync_line_bef_2 = {0x09, 0x00}, + .v_sync_line_bef_1 = {0x04, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ + }, + .tg = { + 0x00, /* cmd */ + 0x98, 0x08, /* h_fsz */ + 0x18, 0x01, 0x80, 0x07, /* hact */ + 0x65, 0x04, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x2d, 0x00, 0x38, 0x04, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ + }, +}; + static const struct hdmi_preset_conf hdmi_conf_1080p50 = { .core = { .h_blank = {0xd0, 0x02}, @@ -865,6 +929,7 @@ static const struct hdmi_conf hdmi_confs[] = { { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 }, { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 }, { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 }, + { 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 }, { 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 }, { 1920, 1080, 60, false, hdmiphy_conf148_5, &hdmi_conf_1080p60 }, }; -- 1.7.4.1
[PATCH 2/5] drm/exynos: enable dvi mode for dvi monitor
Hdmi monitor and dvi monitor can be distinguished with edid. This patch enables dvi mode if dvi monitor is connected and does not enable audio feature for dvi mode because dvi has no audio feature. Signed-off-by: Seung-Woo Kim Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_hdmi.c | 20 ++-- drivers/gpu/drm/exynos/regs-hdmi.h |6 -- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index ad53c48..5ca0a9f 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -60,6 +60,7 @@ struct hdmi_context { boolhpd; boolpowered; boolis_v13; + booldvi_mode; struct mutexhdmi_mutex; struct resource *regs_res; @@ -1211,10 +1212,12 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); if (raw_edid) { + hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); memcpy(edid, raw_edid, min((1 + raw_edid->extensions) * EDID_LENGTH, len)); - DRM_DEBUG_KMS("width[%d] x height[%d]\n", - raw_edid->width_cm, raw_edid->height_cm); + DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", + (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), + raw_edid->width_cm, raw_edid->height_cm); } else { return -ENODEV; } @@ -1437,10 +1440,7 @@ static void hdmi_audio_init(struct hdmi_context *hdata) static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff) { - u32 mod; - - mod = hdmi_reg_read(hdata, HDMI_MODE_SEL); - if (mod & HDMI_DVI_MODE_EN) + if (hdata->dvi_mode) return; hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0); @@ -1479,6 +1479,14 @@ static void hdmi_conf_init(struct hdmi_context *hdata) /* disable bluescreen */ hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN); + if (hdata->dvi_mode) { + /* choose DVI mode */ + hdmi_reg_writemask(hdata, HDMI_MODE_SEL, + HDMI_MODE_DVI_EN, HDMI_MODE_MASK); + hdmi_reg_writeb(hdata, HDMI_CON_2, + HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS); + } + if (hdata->is_v13) { /* choose bluescreen (fecal) color */ hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12); diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index 3c04bea..9cc7c5e 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h @@ -138,14 +138,16 @@ #define HDMI_ASP_MASK (1 << 2) #define HDMI_EN(1 << 0) +/* HDMI_CON_2 */ +#define HDMI_VID_PREAMBLE_DIS (1 << 5) +#define HDMI_GUARD_BAND_DIS(1 << 1) + /* HDMI_PHY_STATUS */ #define HDMI_PHY_STATUS_READY (1 << 0) /* HDMI_MODE_SEL */ #define HDMI_MODE_HDMI_EN (1 << 1) #define HDMI_MODE_DVI_EN (1 << 0) -#define HDMI_DVI_MODE_EN (1) -#define HDMI_DVI_MODE_DIS (0) #define HDMI_MODE_MASK (3 << 0) /* HDMI_TG_CMD */ -- 1.7.4.1
[PATCH 1/5] drm/exynos: fixed wrong pageflip finish event for interlace mode
Pageflip finish event for interlace mode has bug on checking top field vsync because of comparing between dma address converted by start coordinates and non-converted dma address. Signed-off-by: Seung-Woo Kim Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_mixer.c | 12 +++- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 2f6727a..3bc01a6 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -886,7 +886,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg; struct mixer_context *ctx = drm_hdmi_ctx->ctx; struct mixer_resources *res = &ctx->mixer_res; - u32 val, val_base; + u32 val, base, shadow; spin_lock(&res->reg_slock); @@ -897,12 +897,14 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) if (val & MXR_INT_STATUS_VSYNC) { /* interlace scan need to check shadow register */ if (ctx->interlace) { - val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0)); - if (ctx->win_data[0].dma_addr != val_base) + base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); + shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0)); + if (base != shadow) goto out; - val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1)); - if (ctx->win_data[1].dma_addr != val_base) + base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1)); + shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1)); + if (base != shadow) goto out; } -- 1.7.4.1
[PATCH 0/5] various patches related with hdmi of exynos drm
This patch set adds dvi mode, 1080p at 30Hz mode, and vp scaling feature to hdmi of exynos drm and fixes pageflip bug in interlace mode for hdmi. This patch set is for drm-next branch and based on current patch sets from Inki Dae and Joonyoung Shim. You can refer below links: http://www.spinics.net/lists/dri-devel/msg21739.html http://www.spinics.net/lists/dri-devel/msg21746.html http://www.spinics.net/lists/dri-devel/msg21734.html Seung-Woo Kim (5): drm/exynos: fixed wrong pageflip finish event for interlace mode drm/exynos: enable dvi mode for dvi monitor drm/exynos: add additional display mode for hdmi drm/exynos: added source size to overlay structure drm/exynos: added vp scaling feature for hdmi drivers/gpu/drm/exynos/exynos_drm_crtc.c |4 + drivers/gpu/drm/exynos/exynos_drm_crtc.h |4 + drivers/gpu/drm/exynos/exynos_drm_drv.h |4 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 10 ++-- drivers/gpu/drm/exynos/exynos_hdmi.c | 85 +++-- drivers/gpu/drm/exynos/exynos_mixer.c | 100 - drivers/gpu/drm/exynos/regs-hdmi.h|6 +- 7 files changed, 140 insertions(+), 73 deletions(-) -- 1.7.4.1
Re: [PATCH 1/3] drivers-gpu-drm-allow-to-load-edid-firmware.patch
On Sun, 11 Mar 2012 22:23:22 +0100, Carsten Emde wrote: > On 03/11/2012 02:44 PM, Alan Cox wrote: > >>> This patch allows to load an EDID data set via the firmware interface. >>> It contains data sets of frequently used screen resolutions (1024x768, >>> 1280x1024, 1680x1050 and 1920x1080). The requested EDID data are >>> specified as a module parameter of the drm_kms_helper module, e.g. >>> options drm_kms_helper edid_firmware=edid/1280x1024.bin or as kernel >>> command line parameter. >> >> What if the DRM layer and driver are compiled in. They'll come up as >> console before the file system so the firmware request will hang ? > > Admittedly I did not try to compile the DRM layer and driver into the > kernel. However, I created an error condition by specifying a > non-existing EDID file. In this case, the function returns with error, > the mode count remains 0, and the system continues to run as if the > edid_firmware= parameter had not been specified. Unfortunately, as of at least last month, my system hangs when I try to use your feature (just as described by Alan Cox); the log shows that during the boot process, there is a one-minute hang: [0.175207] [drm] radeon: power management initialized [ 60.896507] [drm:edid_load] *ERROR* Requesting EDID firmware "edid/1920x1200.bin" failed (err=-2) Is there any way to make your feature smarter about its timing with relation to file system accessibility? Sincerely, Michael Witten ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] dma-buf: mmap support
2012/4/25, Daniel Vetter : > On Wed, Apr 25, 2012 at 01:37:51AM +0900, InKi Dae wrote: >> Hi, >> >> > >> > +static int dma_buf_mmap_internal(struct file *file, struct >> > vm_area_struct *vma) >> > +{ >> > + struct dma_buf *dmabuf; >> > + >> > + if (!is_dma_buf_file(file)) >> > + return -EINVAL; >> > + >> > + dmabuf = file->private_data; >> > + >> > + /* check for overflowing the buffer's size */ >> > + if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> >> > PAGE_SHIFT) > >> > + dmabuf->size >> PAGE_SHIFT) >> >> is this condition right? your intention is for checking buffer's size >> is valid or not. by the way why is vma->vm_pgoff added to vm region >> size? > > This check here is to ensure that userspace cannot mmap beyong the end of > the dma_buf object. vm_pgoff is the offset userspace passed in at mmap > time and hence needs to be added. Note that vm_end and vm_start are in > bytes, wheres vm_pgoff is in pages. > You're right, vma area region would be decided by user-desired size that this is passed by mmap syscall so user should set size and vm_pgoff appropriately. it's my missing point. well if any part of dmabuf buffer region had already been mmaped and after that user requested mmap for another region of the dmabuf buffer region again then isn't there any problem? I mean that dmabuf->size would always have same value since any memory region allocated by any allocators such as gem, ump and so on have been exported to dmabuf. so at second mmap request, dmabuf->size wouldn't have reasonable value because with first mmap request, any part of the dmabuf buffer region had already beem mmaped. for example, dmabuf size is 1MB and 512Kb region of the dmabuf was mmaped by first mmap request and then with second mmap request, your code would check whether user-desired size is valid or not with dmabuf->size but dmabuf->size would still have 1MB it means at second mmap request, any size between 512KB ~ 1MB would be ok. it's just my concern and there could be my missing point. Thanks, Inki Dae. >> > + return -EINVAL; >> > + >> > + return dmabuf->ops->mmap(dmabuf, vma); >> > +} >> > + >> > static const struct file_operations dma_buf_fops = { >> >.release= dma_buf_release, >> > + .mmap = dma_buf_mmap_internal, >> > }; >> > >> > /* >> > @@ -82,7 +100,8 @@ struct dma_buf *dma_buf_export(void *priv, const >> > struct dma_buf_ops *ops, >> > || !ops->unmap_dma_buf >> > || !ops->release >> > || !ops->kmap_atomic >> > - || !ops->kmap)) { >> > + || !ops->kmap >> > + || !ops->mmap)) { >> >return ERR_PTR(-EINVAL); >> >} >> > >> > @@ -406,3 +425,46 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, >> > unsigned long page_num, >> >dmabuf->ops->kunmap(dmabuf, page_num, vaddr); >> > } >> > EXPORT_SYMBOL_GPL(dma_buf_kunmap); >> > + >> > + >> > +/** >> > + * dma_buf_mmap - Setup up a userspace mmap with the given vma >> > + * @dma_buf: [in]buffer that should back the vma >> > + * @vma: [in]vma for the mmap >> > + * @pgoff: [in]offset in pages where this mmap should start >> > within the >> > + * dma-buf buffer. >> > + * >> > + * This function adjusts the passed in vma so that it points at the >> > file of the >> > + * dma_buf operation. It alsog adjusts the starting pgoff and does >> > bounds >> > + * checking on the size of the vma. Then it calls the exporters mmap >> > function to >> > + * set up the mapping. >> > + * >> > + * Can return negative error values, returns 0 on success. >> > + */ >> > +int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, >> > +unsigned long pgoff) >> > +{ >> > + if (WARN_ON(!dmabuf || !vma)) >> > + return -EINVAL; >> > + >> > + /* check for offset overflow */ >> > + if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < >> > pgoff) >> >> ditto. isn't it checked whether page offset to be mmaped is placed >> within vm region or not with the condition, if ((vma->vm_end - >> vma->vm_start) >> PAGE_SHIFT) < pgoff)? > > Nope, this check only checks for overflow. The pgoff is the offset within > the dma_buf object. E.g. a drm driver splits up it mmap space into pieces, > which map to individual buffers. If userspace just mmaps parts of such a > buffer, the importer can pass the offset in pgoff. But I expect this to be > 0 for almost all cases. > > Note that we don't need this overflow check in the internal mmap function > because do_mmap will do it for us. But here the importer potentially sets > a completely different pgoff, so we need to do it. dma_buf documentation > also mentions this (and that importers do not have to do these checks). > > Yours, Daniel > >> >> > + return -EOVERFL
Re: [Patch 0/3] Add ability to override a monitor's EDID information
On Tue, 24 Apr 2012 10:49:06 +0200, Thorsten Schoel wrote: > Hello everybody, > > having a monitor provide wrong or invalid EDID information---or none at > all---seems to be a problem quite a number of people are facing. A few > of the non-KMS X-drivers provide individual mechanisms for overriding > such an EDID with user provided data. To my knowledge at least the > kernel currently falls short of providing such a mechanism. This set of > patches attempts to provide one. > > It has a number of potential shortcoming to which I was not yet able to > find any solution. These are: > > 1. It uses drm_get_connector_name to identify a connector. I am not > entirely sure though if these names are guaranteed to be unique (the > names used in /sys/class/drm seem to suggest they are not). Since they > are good enough for the kernel's video parameter, though, I figured they > should be good enough for the present purpose as well. > > 2. One of the patches introduces a new kernel parameter (edid_override). > This parameter takes either the raw edid-data encoded as a hex-string or > the name of a firmware file from which to load the data. I am a bit > unhappy with both solutions since the first puts raw data on the command > line and makes it rather long and the second... well edid-data is not > exactly firmware in the strict sense. It may be firm, but it is probably > not ware. > > 3. I thought about making the sysfs code more sophisticated so that > individual bytes could be written at any position within the data. Yet, > there seems to be no way to truncate a file in sysfs which would be > important when changing the number of 128 byte blocks the data is made > up of. In addition, I cannot see what good such a behaviour would be or > how the obscure use probably is somewhere out there could justify the > additional complexity. I therefore opted for the approach of only > allowing writes of complete edid-blobs in one pass. > > The patches I submit were tested on an x64 with radeon graphics and on > an x86 with i915. They were made for 3.4. > > drivers/gpu/drm/drm_edid.c | 399 > +++- > drivers/gpu/drm/drm_sysfs.c | 43 > include/drm/drm_crtc.h |2 > 3 files changed, 435 insertions(+), 9 deletions(-) Are you aware of the following recent commit? commit da0df92b57311aa1b26a2a90599ed16e1e968b90 Author: Carsten Emde Date: Sun Mar 18 22:37:33 2012 +0100 drm: allow loading an EDID as firmware to override broken monitor Has some of your work already been implemented? That being said, the firmware-loading feature of the above commit is not useful to me, because on my system, it tries to load the EDID data BEFORE the kernel knows how to access the file system where the requisite file resides; perhaps something like your command-line EDID data would be useful to me (and others). Sincerely, Michael Witten ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] dma-buf: mmap support
On Wed, Apr 25, 2012 at 01:37:51AM +0900, InKi Dae wrote: > Hi, > > > > > +static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct > > *vma) > > +{ > > + ? ? ? struct dma_buf *dmabuf; > > + > > + ? ? ? if (!is_dma_buf_file(file)) > > + ? ? ? ? ? ? ? return -EINVAL; > > + > > + ? ? ? dmabuf = file->private_data; > > + > > + ? ? ? /* check for overflowing the buffer's size */ > > + ? ? ? if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > > > + ? ? ? ? ? dmabuf->size >> PAGE_SHIFT) > > is this condition right? your intention is for checking buffer's size > is valid or not. by the way why is vma->vm_pgoff added to vm region > size? This check here is to ensure that userspace cannot mmap beyong the end of the dma_buf object. vm_pgoff is the offset userspace passed in at mmap time and hence needs to be added. Note that vm_end and vm_start are in bytes, wheres vm_pgoff is in pages. > > + ? ? ? ? ? ? ? return -EINVAL; > > + > > + ? ? ? return dmabuf->ops->mmap(dmabuf, vma); > > +} > > + > > ?static const struct file_operations dma_buf_fops = { > > ? ? ? ?.release ? ? ? ?= dma_buf_release, > > + ? ? ? .mmap ? ? ? ? ? = dma_buf_mmap_internal, > > ?}; > > > > ?/* > > @@ -82,7 +100,8 @@ struct dma_buf *dma_buf_export(void *priv, const struct > > dma_buf_ops *ops, > > ? ? ? ? ? ? ? ? ? ? ? ? ?|| !ops->unmap_dma_buf > > ? ? ? ? ? ? ? ? ? ? ? ? ?|| !ops->release > > ? ? ? ? ? ? ? ? ? ? ? ? ?|| !ops->kmap_atomic > > - ? ? ? ? ? ? ? ? ? ? ? ? || !ops->kmap)) { > > + ? ? ? ? ? ? ? ? ? ? ? ? || !ops->kmap > > + ? ? ? ? ? ? ? ? ? ? ? ? || !ops->mmap)) { > > ? ? ? ? ? ? ? ?return ERR_PTR(-EINVAL); > > ? ? ? ?} > > > > @@ -406,3 +425,46 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned > > long page_num, > > ? ? ? ? ? ? ? ?dmabuf->ops->kunmap(dmabuf, page_num, vaddr); > > ?} > > ?EXPORT_SYMBOL_GPL(dma_buf_kunmap); > > + > > + > > +/** > > + * dma_buf_mmap - Setup up a userspace mmap with the given vma > > + * @dma_buf: ? [in] ? ?buffer that should back the vma > > + * @vma: ? ? ? [in] ? ?vma for the mmap > > + * @pgoff: ? ? [in] ? ?offset in pages where this mmap should start within > > the > > + * ? ? ? ? ? ? ? ? ? ? dma-buf buffer. > > + * > > + * This function adjusts the passed in vma so that it points at the file > > of the > > + * dma_buf operation. It alsog adjusts the starting pgoff and does bounds > > + * checking on the size of the vma. Then it calls the exporters mmap > > function to > > + * set up the mapping. > > + * > > + * Can return negative error values, returns 0 on success. > > + */ > > +int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, > > + ? ? ? ? ? ? ? ?unsigned long pgoff) > > +{ > > + ? ? ? if (WARN_ON(!dmabuf || !vma)) > > + ? ? ? ? ? ? ? return -EINVAL; > > + > > + ? ? ? /* check for offset overflow */ > > + ? ? ? if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff) > > ditto. isn't it checked whether page offset to be mmaped is placed > within vm region or not with the condition, if ((vma->vm_end - > vma->vm_start) >> PAGE_SHIFT) < pgoff)? Nope, this check only checks for overflow. The pgoff is the offset within the dma_buf object. E.g. a drm driver splits up it mmap space into pieces, which map to individual buffers. If userspace just mmaps parts of such a buffer, the importer can pass the offset in pgoff. But I expect this to be 0 for almost all cases. Note that we don't need this overflow check in the internal mmap function because do_mmap will do it for us. But here the importer potentially sets a completely different pgoff, so we need to do it. dma_buf documentation also mentions this (and that importers do not have to do these checks). Yours, Daniel > > > + ? ? ? ? ? ? ? return -EOVERFLOW; > > + > > + ? ? ? /* check for overflowing the buffer's size */ > > + ? ? ? if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > > > + ? ? ? ? ? dmabuf->size >> PAGE_SHIFT) > > + ? ? ? ? ? ? ? return -EINVAL; > > + > > + ? ? ? /* readjust the vma */ > > + ? ? ? if (vma->vm_file) > > + ? ? ? ? ? ? ? fput(vma->vm_file); > > + > > + ? ? ? vma->vm_file = dmabuf->file; > > + ? ? ? get_file(vma->vm_file); > > + > > + ? ? ? vma->vm_pgoff = pgoff; > > + > > + ? ? ? return dmabuf->ops->mmap(dmabuf, vma); > > +} > > +EXPORT_SYMBOL_GPL(dma_buf_mmap); > > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > > index 3efbfc2..1f78d15 100644 > > --- a/include/linux/dma-buf.h > > +++ b/include/linux/dma-buf.h > > @@ -61,6 +61,10 @@ struct dma_buf_attachment; > > ?* ? ? ? ? ? ? ? ?This Callback must not sleep. > > ?* @kmap: maps a page from the buffer into kernel address space. > > ?* @kunmap: [optional] unmaps a page from the buffer. > > + * @mmap: used to expose the backing storage to userspace. Note that the > > + * ? ? ? mapping needs to be coherent - if the exporter doesn't directly > > + * ? ? ? support this, it needs to fake coherency by shooting down any ptes > > + * ? ? ? when transitioning away from the cpu d
Re: Linux 3.4-rc4
On 2012-04-23 21:03 -0400, Nick Bowler wrote: > On 2012-04-22 22:45 -0400, Konrad Rzeszutek Wilk wrote: > > On Sun, Apr 22, 2012 at 08:05:54PM -0400, Nick Bowler wrote: > > > Following up on the above, the commit which introduces the panics during > > > boot is this one: > > > > > > commit 8e7e70522d760c4ccd4cd370ebfa0ba69e006c6e > > > Author: Jerome Glisse > > > Date: Wed Nov 9 17:15:26 2011 -0500 > > > > > > drm/ttm: isolate dma data from ttm_tt V4 [...] > > dea7e0a ttm: fix agp since ttm tt rework > > > > fixed that. > > Yes, I just tested this commit and the one immediately before it. The > one before crashes in the usual way, and dea7e0a boots (with the VGA > output black as in the original report). So this fixed the crash. OK, here's what I did: - Since dea7e0a is the first commit that both (a) boots and (b) has broken VGA, I checked it out on a new branch: git checkout -b crazy dea7e0a - Next, I reverted *all* (well, I missed one by accident) the remaining nouveau-specific commits between 3230cfc34 ("drm/nouveau: enable the ttm dma pool when swiotlb is active V3") (i.e., the last commit that (a) boots and (b) has non-broken VGA) and dea7e0a: git revert --no-edit 0c101461e267..f7b24c42da1a - Amazingly, the resulting kernel booted and had working VGA, so I did a "backwards" bisect on this branch of reverts. In a strange twist of fate, this actually managed to produce bootable kernels the entire time. The bisection pinpointed the following commit as the culprit: commit a0b25635515ef5049f93b032a1e37f18b16e0f6f Author: Ben Skeggs Date: Mon Nov 21 16:41:48 2011 +1000 drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues - moves out of nouveau_bios.c and demagics the logical state definitions - simplifies chipset-specific driver interface - makes most of gpio irq handling common, will use for nv4x hpd later - api extended to allow both direct gpio access, and access using the logical function states - api extended to allow for future use of gpio extender chips - pre-nv50 was handled very badly, the main issue being that all GPIOs were being treated as output-only. - fixes nvd0 so gpio changes actually stick, magic reg needs bashing Signed-off-by: Ben Skeggs Unfortunately, there are a number of seemingly non-trivial conflicts trying to revert just this one gigantic commit. So to avoid any conflicts, I reverted all of the following (in this order) on top of 3.3.3 (there are even more conflicts trying to revert on top of Linus' master): 7df898b1a70b ("drm/nouveau/disp: check that panel power gpio is enabled at init time") 52c4d767437b ("drm/nouveau: move hpd enable/disable to common code") 47e5d5cb83d4 ("drm/nv40/disp: implement support for hotplug irq") a0b25635515e ("drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues") and my VGA is working again! Cheers, -- Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC PATCH 5/5] drm/nouveau: gpu lockup recovery
On Tue, 2012-04-24 at 21:31 +0200, Marcin Slusarz wrote: > On Mon, Apr 23, 2012 at 06:56:44PM +0200, Martin Peres wrote: > > Le 23/04/2012 18:32, Marcin Slusarz a écrit : > > > > > > Just run piglit. Even "quick" tests can cause ~5 lockups (it eventually > > > messes > > > up DDX channel, but this patchset can't fix this case). > > > You can run fs-discard-exit-2 test first - for me it causes instant GPU > > > lockup. > > > > > > Marcin > > Great, Thanks. > > > > Did you have a look at > > https://bugs.freedesktop.org/show_bug.cgi?id=40886 and > > http://xorg.freedesktop.org/wiki/SummerOfCodeIdeas ? > > Yeah, I've seen them some time ago. > > > The Ubuntu xorg devs were looking for something like this, but they also > > wanted a lockup report. Are you also interested on working on it ? As I argued at XDC last year, I really question the usefulness of something like this. We have stupidly HUGE amounts of state that could be relevant, and the situations where we even need something like this are RARE. I don't want this useless crap in our kernel module just because some random distro thinks it's so useful, when it's not. On the very very rare (I can think of one situation where we've wanted these register dumps, and they weren't useful even then) occasions we need this info, we can ask people to install envytools and grab it.. We have a GPU with *very* good error reporting, and we log this to dmesg. This is good enough. Any random errorless lockups are much harder, and unless you dump *all* the card state right from the memory controllers, to the clocks, to PFIFO to the particular engine that's involved.. It's going to be useless. The problem could be anything. > > Yes, when this patchset will be applied, I'm going to work on improving > error reporting. Assuming you're not talking about a register-dump style lockup report like above, this could be good. Particularly, fleshing out and improving/completing each engine's IRQ handlers (which will probably have the nice side-effect of surviving a few more errors without locking up) :) Cheers, Ben. > > Marcin > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/6] gma500: Set the mapping mask
From: Alan Cox Some boards such as the Intel D2700MUD allow you to have over 4GB of RAM. The GTT on the PVR based devices is 32bit however. Hugh Dickins points out that we should therefore be setting the mapping gfp mask. This is not the whole fix for the problem. Some further shmem patches will be needed to deal with the corner cases. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/gem.c |2 ++ drivers/gpu/drm/gma500/gtt.c |4 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 9fbb868..fc7d144 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -124,6 +124,8 @@ static int psb_gem_create(struct drm_file *file, dev_err(dev->dev, "GEM init failed for %lld\n", size); return -ENOMEM; } + /* Limit the object to 32bit mappings */ + mapping_set_gfp_mask(r->gem.filp->f_mapping, GFP_KERNEL | __GFP_DMA32); /* Give the object a handle so we can carry it more easily */ ret = drm_gem_handle_create(file, &r->gem, &handle); if (ret) { diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index db2e823..54e5c9e 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -39,6 +39,10 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) { uint32_t mask = PSB_PTE_VALID; + /* Ensure we explode rather than put an invalid low mapping of + a high mapping page into the gtt */ + BUG_ON(pfn & ~(0x >> PAGE_SHIFT)); + if (type & PSB_MMU_CACHED_MEMORY) mask |= PSB_PTE_CACHED; if (type & PSB_MMU_RO_MEMORY)
[PATCH 5/6] gma500: Add ops for hotplug support.
From: Alan Cox This provides the needed callback hooks to add hotplug display support to the GMA36x0 devices. [The actual enabling device part will follow once I've figured out why it breaks suspend/resume on some netbooks] Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/psb_drv.h |3 +++ drivers/gpu/drm/gma500/psb_irq.c | 36 +++- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 6235499..ab483c3 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -130,6 +130,7 @@ enum { #define _PSB_VSYNC_PIPEA_FLAG(1<<7) #define _MDFLD_MIPIA_FLAG(1<<16) #define _MDFLD_MIPIC_FLAG(1<<17) +#define _PSB_IRQ_DISP_HOTSYNC(1<<17) #define _PSB_IRQ_SGX_FLAG(1<<18) #define _PSB_IRQ_MSVDX_FLAG (1<<19) #define _LNC_IRQ_TOPAZ_FLAG (1<<20) @@ -703,6 +704,8 @@ struct psb_ops { /* Display management hooks */ int (*output_init)(struct drm_device *dev); + int (*hotplug)(struct drm_device *dev); + void (*hotplug_enable)(struct drm_device *dev, bool on); /* Power management hooks */ void (*init_pm)(struct drm_device *dev); int (*save_regs)(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 1869586..4f31312 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -199,11 +199,9 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) { - struct drm_device *dev = (struct drm_device *) arg; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - - uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; + struct drm_device *dev = arg; + struct drm_psb_private *dev_priv = dev->dev_private; + uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; int handled = 0; spin_lock(&dev_priv->irqmask_lock); @@ -220,6 +218,8 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) if (vdc_stat & _PSB_IRQ_SGX_FLAG) sgx_int = 1; + if (vdc_stat & _PSB_IRQ_DISP_HOTSYNC) + hotplug_int = 1; vdc_stat &= dev_priv->vdc_irq_mask; spin_unlock(&dev_priv->irqmask_lock); @@ -241,6 +241,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) handled = 1; } + /* Note: this bit has other meanings on some devices, so we will + need to address that later if it ever matters */ + if (hotplug_int && dev_priv->ops->hotplug) { + handled = dev_priv->ops->hotplug(dev); + REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT)); + } + PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); (void) PSB_RVDC32(PSB_INT_IDENTITY_R); DRM_READMEMORYBARRIER(); @@ -273,6 +280,10 @@ void psb_irq_preinstall(struct drm_device *dev) dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; */ + /* Revisit this area - want per device masks ? */ + if (dev_priv->ops->hotplug) + dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; + /* This register is safe even if display island is off */ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); @@ -305,18 +316,25 @@ int psb_irq_postinstall(struct drm_device *dev) else psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + if (dev_priv->ops->hotplug_enable) + dev_priv->ops->hotplug_enable(dev, true); + spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); return 0; } void psb_irq_uninstall(struct drm_device *dev) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); + if (dev_priv->ops->hotplug_enable) { + dev_priv->ops->hotplug_enable(dev, false); + dev_priv->vdc_irq_mask &= ~_PSB_IRQ_DISP_HOTSYNC; + } + PSB_WVDC32(0x, PSB_HWSTAM); if (dev->vblank_enabled[0]) @@ -328,9 +346,9 @@ void psb_irq_uninstall(struct drm_device *dev) if (dev->vblank_enabled[2]) psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | + dev_priv->vdc_irq_mask &= ~(_PSB_IRQ_SGX_FLAG | _PSB_IRQ_MSVDX_FLAG | - _LNC_IRQ_TOPAZ_FLAG; + _LNC_IRQ_TOPAZ_FLAG); /* These two registers are safe even if display island is off */ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
[PATCH 4/6] gma500: implement backlight functionality for Cedartrail devices
From: Alan Cox Basically a straight cut/paste from the reference driver code then cleaned up a spot. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_device.c | 113 --- 1 files changed, 51 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 5cc06a8..292bcec 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -57,8 +57,7 @@ static int cdv_output_init(struct drm_device *dev) cdv_intel_crt_init(dev, &dev_priv->mode_dev); cdv_intel_lvds_init(dev, &dev_priv->mode_dev); - /* These bits indicate HDMI not SDVO on CDV, but we don't yet support - the HDMI interface */ + /* These bits indicate HDMI not SDVO on CDV */ if (REG_READ(SDVOB) & SDVO_DETECTED) cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); if (REG_READ(SDVOC) & SDVO_DETECTED) @@ -69,76 +68,71 @@ static int cdv_output_init(struct drm_device *dev) #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE /* - * Poulsbo Backlight Interfaces + * Cedartrail Backlght Interfaces */ -#define BLC_PWM_PRECISION_FACTOR 100 /* 1000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 100 - -#define PSB_BLC_PWM_PRECISION_FACTOR10 -#define PSB_BLC_MAX_PWM_REG_FREQ0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT(16) - -static int cdv_brightness; static struct backlight_device *cdv_backlight_device; -static int cdv_get_brightness(struct backlight_device *bd) +static int cdv_backlight_combination_mode(struct drm_device *dev) { - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return cdv_brightness; + return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE; } - -static int cdv_backlight_setup(struct drm_device *dev) +static int cdv_get_brightness(struct backlight_device *bd) { - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long core_clock; - /* u32 bl_max_freq; */ - /* unsigned long value; */ - u16 bl_max_freq; - uint32_t value; - uint32_t blc_pwm_precision_factor; - - /* get bl_max_freq and pol from dev_priv*/ - if (!dev_priv->lvds_bl) { - dev_err(dev->dev, "Has no valid LVDS backlight info\n"); - return -ENOENT; - } - bl_max_freq = dev_priv->lvds_bl->freq; - blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; + struct drm_device *dev = bl_get_data(bd); + u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - core_clock = dev_priv->core_freq; + if (cdv_backlight_combination_mode(dev)) { + u8 lbpc; - value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; - value *= blc_pwm_precision_factor; - value /= bl_max_freq; - value /= blc_pwm_precision_factor; + val &= ~1; + pci_read_config_byte(dev->pdev, 0xF4, &lbpc); + val *= lbpc; + } + return val; +} - if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || -value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) - return -ERANGE; - else { - /* FIXME */ +static u32 cdv_get_max_backlight(struct drm_device *dev) +{ + u32 max = REG_READ(BLC_PWM_CTL); + + if (max == 0) { + DRM_DEBUG_KMS("LVDS Panel PWM value is 0!\n"); + /* i915 does this, I believe which means that we should not +* smash PWM control as firmware will take control of it. */ + return 1; } - return 0; + + max >>= 16; + if (cdv_backlight_combination_mode(dev)) + max *= 0xff; + return max; } static int cdv_set_brightness(struct backlight_device *bd) { + struct drm_device *dev = bl_get_data(bd); int level = bd->props.brightness; + u32 blc_pwm_ctl; /* Percentage 1-100% being valid */ if (level < 1) level = 1; - /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ - cdv_brightness = level; + if (cdv_backlight_combination_mode(dev)) { + u32 max = cdv_get_max_backlight(dev); + u8 lbpc; + + lbpc = level * 0xfe / max + 1; + level /= lbpc; + + pci_write_config_byte(dev->pdev, 0xF4, lbpc); + } + + blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | + (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); return 0; } @@ -150,7 +144,6 @@ static const struct backlight_ops cdv_ops = { static int cdv_backlight_init(struct drm_device *d
[PATCH 3/6] cdv: continue synching up with updated reference code
From: Alan Cox In particular clean up the errata handling and correct the crtc masks. We do this a bit differently using our device abstraction for neatness. This doesn't address the ACPI opregion and hotplug plumbing, nor the IRQ related changes that will need. It touches on backlight init but the full backlight support is not in this change set. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_device.c| 20 + drivers/gpu/drm/gma500/cdv_intel_crt.c | 20 +++-- drivers/gpu/drm/gma500/cdv_intel_display.c | 61 drivers/gpu/drm/gma500/cdv_intel_lvds.c| 17 drivers/gpu/drm/gma500/framebuffer.c | 13 ++ drivers/gpu/drm/gma500/mdfld_device.c |2 + drivers/gpu/drm/gma500/oaktrail_device.c |2 + drivers/gpu/drm/gma500/psb_device.c|2 + drivers/gpu/drm/gma500/psb_drv.h |4 ++ drivers/gpu/drm/gma500/psb_intel_reg.h |4 ++ 10 files changed, 89 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index a54cc73..5cc06a8 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -49,6 +49,9 @@ static void cdv_disable_vga(struct drm_device *dev) static int cdv_output_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; + + drm_mode_create_scaling_mode_property(dev); + cdv_disable_vga(dev); cdv_intel_crt_init(dev, &dev_priv->mode_dev); @@ -238,6 +241,18 @@ static void cdv_init_pm(struct drm_device *dev) dev_err(dev->dev, "GPU: power management timed out.\n"); } +static void cdv_errata(struct drm_device *dev) +{ + /* Disable bonus launch. +* CPU and GPU competes for memory and display misses updates and flickers. +* Worst with dual core, dual displays. +* +* Fixes were done to Win 7 gfx driver to disable a feature called Bonus +* Launch to work around the issue, by degrading performance. +*/ +CDV_MSG_WRITE32(3, 0x30, 0x08027108); +} + /** * cdv_save_display_registers - save registers lost on suspend * @dev: our DRM device @@ -355,7 +370,7 @@ static int cdv_restore_display_registers(struct drm_device *dev) REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR); /* Fix arbitration bug */ - CDV_MSG_WRITE32(3, 0x30, 0x08027108); + cdv_errata(dev); drm_mode_config_reset(dev); @@ -464,8 +479,11 @@ const struct psb_ops cdv_chip_ops = { .accel_2d = 0, .pipes = 2, .crtcs = 2, + .hdmi_mask = (1 << 0) | (1 << 1), + .lvds_mask = (1 << 1), .sgx_offset = MRST_SGX_OFFSET, .chip_setup = cdv_chip_setup, + .errata = cdv_errata, .crtc_helper = &cdv_intel_helper_funcs, .crtc_funcs = &cdv_intel_crtc_funcs, diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 1a82843..1874220 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -78,9 +78,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, if (mode->clock > 355000) return MODE_CLOCK_HIGH; - if (mode->hdisplay > 1680 || mode->vdisplay > 1050) - return MODE_PANEL; - return MODE_OK; } @@ -148,13 +145,7 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, struct drm_device *dev = connector->dev; u32 hotplug_en; int i, tries = 0, ret = false; - u32 adpa_orig; - - /* disable the DAC when doing the hotplug detection */ - - adpa_orig = REG_READ(ADPA); - - REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE)); + u32 orig; /* * On a CDV thep, CRT detect sequence need to be done twice @@ -162,7 +153,7 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, */ tries = 2; - hotplug_en = REG_READ(PORT_HOTPLUG_EN); + orig = hotplug_en = REG_READ(PORT_HOTPLUG_EN); hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK); hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; @@ -187,8 +178,11 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, CRT_HOTPLUG_MONITOR_NONE) ret = true; - /* Restore the saved ADPA */ - REG_WRITE(ADPA, adpa_orig); +/* clear the interrupt we just generated, if any */ + REG_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); + + /* and put the bits back */ + REG_WRITE(PORT_HOTPLUG_EN, orig); return ret; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 07b37f5..2fab778 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -226,13 +226,13 @@ cdv_dpll_set_
[PATCH 2/6] gma500: Clean up weirdness in the cdv mode test code
From: Alan Cox Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_crt.c |4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 1de27c7..1a82843 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -67,7 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) static int cdv_intel_crt_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - int max_clock = 0; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -76,8 +75,7 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, return MODE_CLOCK_LOW; /* The max clock for CDV is 355 instead of 400 */ - max_clock = 355000; - if (mode->clock > max_clock) + if (mode->clock > 355000) return MODE_CLOCK_HIGH; if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
[PATCH 1/6] gma500: support 1080p
From: Alan Cox The problem in console mode is lack of linear memory. We can solve that by dropping to 16bpp. The mode setting X server will allocate its own GEM framebuffer in 32bpp and all will be well. We could just do 16bpp anyway but that would be a regression on the lower modes as many distributions don't yet ship the generic mode setting KMS drivers. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_crt.c |6 -- drivers/gpu/drm/gma500/cdv_intel_hdmi.c |7 --- drivers/gpu/drm/gma500/framebuffer.c| 16 drivers/gpu/drm/gma500/oaktrail_hdmi.c |6 -- drivers/gpu/drm/gma500/psb_intel_sdvo.c |6 -- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index a71a6cd..1de27c7 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -67,7 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) static int cdv_intel_crt_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct drm_psb_private *dev_priv = connector->dev->dev_private; int max_clock = 0; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -84,11 +83,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, if (mode->hdisplay > 1680 || mode->vdisplay > 1050) return MODE_PANEL; - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - return MODE_OK; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 8d52695..88b59d4 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -242,8 +242,6 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector) static int cdv_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct drm_psb_private *dev_priv = connector->dev->dev_private; - if (mode->clock > 165000) return MODE_CLOCK_HIGH; if (mode->clock < 2) @@ -257,11 +255,6 @@ static int cdv_hdmi_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_INTERLACE) return MODE_NO_INTERLACE; - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - return MODE_OK; } diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 8ea202f..c2cf6bf 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -543,9 +543,25 @@ static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; + struct drm_device *dev = psb_fbdev->psb_fb_helper.dev; + struct drm_psb_private *dev_priv = dev->dev_private; int new_fb = 0; + int bytespp; int ret; + bytespp = sizes->surface_bpp / 8; + if (bytespp == 3) /* no 24bit packed */ + bytespp = 4; + + /* If the mode will not fit in 32bit then switch to 16bit to get + a console on full resolution. The X mode setting server will + allocate its own 32bit GEM framebuffer */ + if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height > + dev_priv->vram_stolen_size) { +sizes->surface_bpp = 16; +sizes->surface_depth = 16; +} + if (!helper->fb) { ret = psbfb_create(psb_fbdev, sizes); if (ret) diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index f8b367b..2595660 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -179,7 +179,6 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct drm_psb_private *dev_priv = connector->dev->dev_private; if (mode->clock > 165000) return MODE_CLOCK_HIGH; if (mode->clock < 2) @@ -188,11 +187,6 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mo
[PATCH 3/3] gma500: don't register the ACPI video bus
From: Alan Cox We are not yet ready for this and it makes a mess on some devices. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/psb_drv.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index d5a6eab..45bd0c7 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -350,7 +350,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) PSB_WSGX32(0x3000, PSB_CR_BIF_3D_REQ_BASE); /* igd_opregion_init(&dev_priv->opregion_dev); */ - acpi_video_register(); +/* acpi_video_register(); */ if (dev_priv->lid_state) psb_lid_timer_init(dev_priv);
[PATCH 2/3] acpi_video: Intel video is not always i915
From: Alan Cox Handle the GMA500/600/36x0 cases. Also stop it poking at random registers on the i740 cards that may be out there still. This should also allow the legacy gma500 stub driver to go away as the ACPI video layer will now do the right thing rather than assume all the world is Gen graphics and need the gma500 stub as a workaround. Signed-off-by: Alan Cox --- drivers/acpi/video.c | 54 +++--- 1 files changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 66e8f73..b2ae7aa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1743,25 +1743,63 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } +static int __init is_gma_pvr(struct pci_dev *dev) +{ + /* Medfield */ + if ((dev->device & 0xFFF8) == 0x0130) + return 1; + /* GMA36x0 */ + if ((dev->device & 0xFFF8) == 0x0be0) + return 1; + /* GMA600 */ + if ((dev->device & 0xFFF8) == 0x4100) + return 1; + /* GMA500 */ + if ((dev->device & 0xFFFE) == 0x8108) + return 1; + /* E620 */ + if (dev->device == 0x4108) + return 1; + return 0; +} + +static int __init is_i740(struct pci_dev *dev) +{ + if (dev->device == 0x00D1) + return 1; + if (dev->device == 0x7000) + return 1; + return 0; +} + static int __init intel_opregion_present(void) { - int i915 = 0; -#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) + int opregion = 0; struct pci_dev *dev = NULL; - u32 address; for_each_pci_dev(dev) { if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) continue; if (dev->vendor != PCI_VENDOR_ID_INTEL) continue; - pci_read_config_dword(dev, 0xfc, &address); - if (!address) + /* We don't want to poke around undefined i740 registers */ + if (is_i740(dev)) continue; - i915 = 1; - } +#if defined(CONFIG_DRM_GMA500) || defined(CONFIG_DRM_GMA500_MODULE) + if (is_gma_pvr(dev)) + opregion = 1; #endif - return i915; +#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) + if (!is_gma_pvr(dev)) { + u32 address; + pci_read_config_dword(dev, 0xfc, &address); + if (!address) + continue; + opregion = 1; + } +#endif + } + return opregion; } int acpi_video_register(void)
[PATCH 1/3] acpi_video: fix leaking PCI references
From: Alan Cox Otherwise we keep a bogus pci reference to the GPU Signed-off-by: Alan Cox --- drivers/acpi/video.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 9577b6f..66e8f73 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1745,6 +1745,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) static int __init intel_opregion_present(void) { + int i915 = 0; #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) struct pci_dev *dev = NULL; u32 address; @@ -1757,10 +1758,10 @@ static int __init intel_opregion_present(void) pci_read_config_dword(dev, 0xfc, &address); if (!address) continue; - return 1; + i915 = 1; } #endif - return 0; + return i915; } int acpi_video_register(void)
[PATCH 6/6] gma500: panel presence check
From: Alan Cox Introduce a panel presence check for Cedartrail. Non netbook devices don't necessarily have a panel attached. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 57 +++ 1 files changed, 57 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 8359c1a..c87b179 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -556,6 +556,56 @@ const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { .destroy = cdv_intel_lvds_enc_destroy, }; +/* + * Enumerate the child dev array parsed from VBT to check whether + * the LVDS is present. + * If it is present, return 1. + * If it is not present, return false. + * If no child dev is parsed from VBT, it assumes that the LVDS is present. + */ +static bool lvds_is_present_in_vbt(struct drm_device *dev, + u8 *i2c_pin) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + int i; + + if (!dev_priv->child_dev_num) + return true; + + for (i = 0; i < dev_priv->child_dev_num; i++) { + struct child_device_config *child = dev_priv->child_dev + i; + + /* If the device type is not LFP, continue. +* We have to check both the new identifiers as well as the +* old for compatibility with some BIOSes. +*/ + if (child->device_type != DEVICE_TYPE_INT_LFP && + child->device_type != DEVICE_TYPE_LFP) + continue; + + if (child->i2c_pin) + *i2c_pin = child->i2c_pin; + + /* However, we cannot trust the BIOS writers to populate +* the VBT correctly. Since LVDS requires additional +* information from AIM blocks, a non-zero addin offset is +* a good indicator that the LVDS is actually present. +*/ + if (child->addin_offset) + return true; + + /* But even then some BIOS writers perform some black magic +* and instantiate the device without reference to any +* additional data. Trust that if the VBT was written into +* the OpRegion then they have validated the LVDS's existence. +*/ + if (dev_priv->opregion.vbt) + return true; + } + + return false; +} + /** * cdv_intel_lvds_init - setup LVDS connectors on this device * @dev: drm device @@ -576,6 +626,13 @@ void cdv_intel_lvds_init(struct drm_device *dev, struct drm_psb_private *dev_priv = dev->dev_private; u32 lvds; int pipe; + u8 pin; + + pin = GMBUS_PORT_PANEL; + if (!lvds_is_present_in_vbt(dev, &pin)) { + DRM_DEBUG_KMS("LVDS is not present in VBT\n"); + return; + } psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
[PATCH 5/6] gma500: intel_bios updates
From: Alan Cox Pull in various i915 bits that we will need to begin tackling the LVDS detect and ACPI events. We try and drift towards the i915 version of the code with the long term goal that at least some of it can one day be unified. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/intel_bios.c | 232 --- drivers/gpu/drm/gma500/intel_bios.h | 122 +++- drivers/gpu/drm/gma500/intel_opregion.c | 117 ++-- drivers/gpu/drm/gma500/psb_drv.h|4 + 4 files changed, 438 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 51ea6df..479e449 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -26,6 +26,8 @@ #include "psb_intel_reg.h" #include "intel_bios.h" +#defineSLAVE_ADDR1 0x70 +#defineSLAVE_ADDR2 0x72 static void *find_section(struct bdb_header *bdb, int section_id) { @@ -52,6 +54,16 @@ static void *find_section(struct bdb_header *bdb, int section_id) return NULL; } +static u16 +get_blocksize(void *p) +{ + u16 *block_ptr, block_size; + + block_ptr = (u16 *)((char *)p - 2); + block_size = *block_ptr; + return block_size; +} + static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, struct lvds_dvo_timing *dvo_timing) { @@ -75,6 +87,16 @@ static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; + if (dvo_timing->hsync_positive) + panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (dvo_timing->vsync_positive) + panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; + /* Some VBTs have bogus h/vtotal values */ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; @@ -218,6 +240,97 @@ static void parse_general_features(struct drm_psb_private *dev_priv, } static void +parse_sdvo_device_mapping(struct drm_psb_private *dev_priv, + struct bdb_header *bdb) +{ + struct sdvo_device_mapping *p_mapping; + struct bdb_general_definitions *p_defs; + struct child_device_config *p_child; + int i, child_device_num, count; + u16 block_size; + + p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); + if (!p_defs) { + DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); + return; + } + /* judge whether the size of child device meets the requirements. +* If the child device size obtained from general definition block +* is different with sizeof(struct child_device_config), skip the +* parsing of sdvo device info +*/ + if (p_defs->child_dev_size != sizeof(*p_child)) { + /* different child dev size . Ignore it */ + DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + return; + } + /* get the block size of general definitions */ + block_size = get_blocksize(p_defs); + /* get the number of child device */ + child_device_num = (block_size - sizeof(*p_defs)) / + sizeof(*p_child); + count = 0; + for (i = 0; i < child_device_num; i++) { + p_child = &(p_defs->devices[i]); + if (!p_child->device_type) { + /* skip the device block if device type is invalid */ + continue; + } + if (p_child->slave_addr != SLAVE_ADDR1 && + p_child->slave_addr != SLAVE_ADDR2) { + /* +* If the slave address is neither 0x70 nor 0x72, +* it is not a SDVO device. Skip it. +*/ + continue; + } + if (p_child->dvo_port != DEVICE_PORT_DVOB && + p_child->dvo_port != DEVICE_PORT_DVOC) { + /* skip the incorrect SDVO port */ + DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); + continue; + } + DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" + " %s port\n", + p_child->slave_addr, + (p_child->dvo_port == DEVICE_PORT_DVOB) ? + "SDVOB" : "SDVOC"); + p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]); +
[PATCH 4/6] gma500: cache GEM framebuffer pages wc not uc
From: Alan Cox Fixes the case where the modesetting driver is slower than /dev/fb. Signed-off-by: Alan Cox Cc: stable at kernel.org --- drivers/gpu/drm/gma500/gtt.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index c6465b4..db2e823 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -93,7 +93,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) pages = r->pages; /* Make sure changes are visible to the GPU */ - set_pages_array_uc(pages, r->npage); + set_pages_array_wc(pages, r->npage); /* Write our page entries into the GTT itself */ for (i = r->roll; i < r->npage; i++) {
[PATCH 3/6] gma500: Update the Cedarview clock handling
From: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_display.c | 331 +++- drivers/gpu/drm/gma500/psb_intel_drv.h |3 drivers/gpu/drm/gma500/psb_intel_reg.h | 25 ++ 3 files changed, 294 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index be84559..07b37f5 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -216,7 +216,7 @@ static void cdv_sb_reset(struct drm_device *dev) */ static int cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, - struct cdv_intel_clock_t *clock) + struct cdv_intel_clock_t *clock, bool is_lvds) { struct psb_intel_crtc *psb_crtc = to_psb_intel_crtc(crtc); @@ -224,6 +224,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, u32 m, n_vco, p; int ret = 0; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int ref_sfr = (pipe == 0) ? SB_REF_DPLLA : SB_REF_DPLLB; u32 ref_value; cdv_sb_reset(dev); @@ -241,6 +242,35 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, /* We don't know what the other fields of these regs are, so * leave them in place. */ + /* +* The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk +* for the pipe A/B. Display spec 1.06 has wrong definition. +* Correct definition is like below: +* +* refclka mean use clock from same PLL +* +* if DPLLA sets 01 and DPLLB sets 01, they use clock from their pll +* +* if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA +* +*/ + ret = cdv_sb_read(dev, ref_sfr, &ref_value); + if (ret) + return ret; + ref_value &= ~(REF_CLK_MASK); + + /* use DPLL_A for pipeB on CRT/HDMI */ + if (pipe == 1 && !is_lvds) { + DRM_DEBUG_KMS("use DPLLA for pipe B\n"); + ref_value |= REF_CLK_DPLLA; + } else { + DRM_DEBUG_KMS("use their DPLL for pipe A/B\n"); + ref_value |= REF_CLK_DPLL; + } + ret = cdv_sb_write(dev, ref_sfr, ref_value); + if (ret) + return ret; + ret = cdv_sb_read(dev, SB_M(pipe), &m); if (ret) return ret; @@ -308,7 +338,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, return ret; /* always Program the Lane Register for the Pipe A*/ - if (pipe == 0) { +/* if (pipe == 0) */ { /* Program the Lane0/1 for HDMI B */ u32 lane_reg, lane_value; @@ -553,6 +583,200 @@ psb_intel_pipe_set_base_exit: return ret; } +#defineFIFO_PIPEA (1 << 0) +#defineFIFO_PIPEB (1 << 1) + +static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe) +{ + struct drm_crtc *crtc; + struct drm_psb_private *dev_priv = dev->dev_private; + struct psb_intel_crtc *psb_intel_crtc = NULL; + + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + psb_intel_crtc = to_psb_intel_crtc(crtc); + + if (crtc->fb == NULL || !psb_intel_crtc->active) + return false; + return true; +} + +static bool cdv_intel_single_pipe_active (struct drm_device *dev) +{ + uint32_t pipe_enabled = 0; + + if (cdv_intel_pipe_enabled(dev, 0)) + pipe_enabled |= FIFO_PIPEA; + + if (cdv_intel_pipe_enabled(dev, 1)) + pipe_enabled |= FIFO_PIPEB; + + + DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled); + + if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB) + return true; + else + return false; +} + +static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + if (psb_intel_crtc->pipe != 1) + return false; + + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct psb_intel_encoder *psb_intel_encoder = + psb_intel_attached_encoder(connector); + + if (!connector->encoder + || connector->encoder->crtc != crtc) + continue; + + if (psb_intel_encoder->type == INTEL_OUTPUT_LVDS) + return true; + } + + return false; +} + +static void cdv_intel_disable_self_refresh (struct drm_device *dev) +{ + if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) { + + /* Disable self-refresh before adjust WM */ + REG_WR
[PATCH 2/6] gma500: read the PLL bits
From: Alan Cox We need to pull more stuff from the VBT in order to configure the clocking correctly in all cases. Add the relevant bits from the other CDV driver work. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/intel_bios.c | 18 drivers/gpu/drm/gma500/intel_bios.h | 39 +++ drivers/gpu/drm/gma500/psb_drv.h|2 ++ 3 files changed, 59 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index d4d0c5b..51ea6df 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -217,6 +217,23 @@ static void parse_general_features(struct drm_psb_private *dev_priv, } } +static void +parse_driver_features(struct drm_psb_private *dev_priv, + struct bdb_header *bdb) +{ + struct bdb_driver_features *driver; + + driver = find_section(bdb, BDB_DRIVER_FEATURES); + if (!driver) + return; + + /* This bit means to use 96Mhz for DPLL_A or not */ + if (driver->primary_lfp_id) + dev_priv->dplla_96mhz = true; + else + dev_priv->dplla_96mhz = false; +} + /** * psb_intel_init_bios - initialize VBIOS settings & find VBT * @dev: DRM device @@ -263,6 +280,7 @@ bool psb_intel_init_bios(struct drm_device *dev) /* Grab useful general definitions */ parse_general_features(dev_priv, bdb); + parse_driver_features(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_backlight_data(dev_priv, bdb); diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h index 70f1bf0..c67979e 100644 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ b/drivers/gpu/drm/gma500/intel_bios.h @@ -302,6 +302,45 @@ struct bdb_sdvo_lvds_options { u8 panel_misc_bits_4; } __attribute__((packed)); +struct bdb_driver_features { + u8 boot_dev_algorithm:1; + u8 block_display_switch:1; + u8 allow_display_switch:1; + u8 hotplug_dvo:1; + u8 dual_view_zoom:1; + u8 int15h_hook:1; + u8 sprite_in_clone:1; + u8 primary_lfp_id:1; + + u16 boot_mode_x; + u16 boot_mode_y; + u8 boot_mode_bpp; + u8 boot_mode_refresh; + + u16 enable_lfp_primary:1; + u16 selective_mode_pruning:1; + u16 dual_frequency:1; + u16 render_clock_freq:1; /* 0: high freq; 1: low freq */ + u16 nt_clone_support:1; + u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */ + u16 sprite_display_assign:1; /* 0: secondary; 1: primary */ + u16 cui_aspect_scaling:1; + u16 preserve_aspect_ratio:1; + u16 sdvo_device_power_down:1; + u16 crt_hotplug:1; + u16 lvds_config:2; + u16 tv_hotplug:1; + u16 hdmi_config:2; + + u8 static_display:1; + u8 reserved2:7; + u16 legacy_crt_max_x; + u16 legacy_crt_max_y; + u8 legacy_crt_max_refresh; + + u8 hdmi_termination; + u8 custom_vbt_version; +} __attribute__((packed)); extern bool psb_intel_init_bios(struct drm_device *dev); extern void psb_intel_destroy_bios(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 40ce2c9..4c50969 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -669,6 +669,8 @@ struct drm_psb_private { u32 dspcntr[3]; int mdfld_panel_id; + + bool dplla_96mhz; /* DPLL data from the VBT */ };
[PATCH 1/6] gma500: Fix leak of uncached page
From: Alan Cox This was reported a long time ago (and I apologize to whoever it was that reported it as I've lost the original report). Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/psb_drv.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index c34adf9..d5a6eab 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -246,6 +246,7 @@ static int psb_driver_unload(struct drm_device *dev) } psb_gtt_takedown(dev); if (dev_priv->scratch_page) { + set_pages_wb(dev_priv->scratch_page, 1); __free_page(dev_priv->scratch_page); dev_priv->scratch_page = NULL; }
[PATCH v2] scatterlist: add sg_alloc_table_from_pages function
On Tue, Apr 24, 2012 at 02:58:56PM +0200, Tomasz Stanislawski wrote: > This patch adds a new constructor for an sg table. The table is constructed > from an array of struct pages. All contiguous chunks of the pages are merged > into a single sg nodes. A user may provide an offset and a size of a buffer if > the buffer is not page-aligned. > > The function is dedicated for DMABUF exporters which often perform conversion > from an page array to a scatterlist. Moreover the scatterlist should be > squashed in order to save memory and to speed-up the process of DMA mapping > using dma_map_sg. > > The code is based on the patch 'v4l: vb2-dma-contig: add support for > scatterlist in userptr mode' and hints from Laurent Pinchart. > > Signed-off-by: Tomasz Stanislawski > Signed-off-by: Kyungmin Park I like this and we could replace the drm helper function in drm prime with this one. One comment below. -Daniel > --- > include/linux/scatterlist.h |4 +++ > lib/scatterlist.c | 63 > +++ > 2 files changed, 67 insertions(+), 0 deletions(-) > > diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h > index ac9586d..7b600da 100644 > --- a/include/linux/scatterlist.h > +++ b/include/linux/scatterlist.h > @@ -214,6 +214,10 @@ void sg_free_table(struct sg_table *); > int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, >sg_alloc_fn *); > int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); > +int sg_alloc_table_from_pages(struct sg_table *sgt, > + struct page **pages, unsigned int n_pages, > + unsigned long offset, unsigned long size, > + gfp_t gfp_mask); > > size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, > void *buf, size_t buflen); > diff --git a/lib/scatterlist.c b/lib/scatterlist.c > index 6096e89..90f9265 100644 > --- a/lib/scatterlist.c > +++ b/lib/scatterlist.c > @@ -319,6 +319,69 @@ int sg_alloc_table(struct sg_table *table, unsigned int > nents, gfp_t gfp_mask) > EXPORT_SYMBOL(sg_alloc_table); > > /** > + * sg_alloc_table_from_pages - Allocate and initialize an sg table from > + * an array of pages > + * @sgt: The sg table header to use > + * @pages: Pointer to an array of page pointers > + * @n_pages: Number of pages in the pages array > + * @offset: Offset from a start of the first page to a start of a buffer > + * @size: Number of valid bytes in the buffer (after offset) > + * @gfp_mask:GFP allocation mask > + * > + * Description: > + *Allocate and initialize an sg table from a list of pages. Continuous > + *ranges of the pages are squashed into a single scatterlist node. A user > + *may provide an offset at a start and a size of valid data in a buffer > + *specified by the page array. The returned sg table is released by > + *sg_free_table. > + * > + * Returns: > + * 0 on success, negative error on failure > + **/ > +int sg_alloc_table_from_pages(struct sg_table *sgt, > + struct page **pages, unsigned int n_pages, > + unsigned long offset, unsigned long size, > + gfp_t gfp_mask) > +{ > + unsigned int chunks; > + unsigned int i; > + unsigned int cur_page; > + int ret; > + struct scatterlist *s; > + > + /* compute number of contiguous chunks */ > + chunks = 1; > + for (i = 1; i < n_pages; ++i) > + if (pages[i] != pages[i - 1] + 1) > + ++chunks; I'm not aware of the details (and didn't bother to do a full audit), but I guess this could blow up on funky discontig-mem setups. Imo would be safer to compare the pfn or phys address. And also slightly more readable. Imo sg table creation is not a fastpath, the exporter should cache these anyway, so we can waste some cpu cycles here. > + ret = sg_alloc_table(sgt, chunks, gfp_mask); > + if (unlikely(ret)) > + return ret; > + > + /* merging chunks and putting them into the scatterlist */ > + cur_page = 0; > + for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { > + unsigned long chunk_size; > + unsigned int j; > + > + /* looking for the end of the current chunk */ > + for (j = cur_page + 1; j < n_pages; ++j) > + if (pages[j] != pages[j - 1] + 1) > + break; > + > + chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset; > + sg_set_page(s, pages[cur_page], min(size, chunk_size), offset); > + size -= chunk_size; > + offset = 0; > + cur_page = j; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(sg_alloc_table_from_pages); > + > +/** > * sg_miter_start - start mapping iteration over a sg list > * @miter: sg mapping iter to be started > * @sgl: sg list to iterate over > -- > 1.7.5.4 > > ___ > dri-devel
[PATCH] drm: Initial KMS driver for AST (ASpeed Technologies) 2000 series
On Mon, 2012-04-23 at 14:30 +0100, Alan Cox wrote: > > > fbdev objects once exposed to userspace or to fbcon, thanks to some > > wonderful > > API design way back, the mmaps on the fbdev device are direct to the VRAM > > physical pages. Can't tear them down and move them into system RAM pages > > at all easily. > > Thats not strictly true. They can move mapping if the locking is right > and the helpers handle it because you can invalidate the pages in the > userspace mappings and they will get faulted back with the new ones. fbdev userspace mappings is the easy part, TTM has supported that for years. The problem is fbcon, which can access the framebuffer from basically any context for printk. > > Because I'm not 100% sure nothing will get written to it, and if > > Fair point. > > > something gets written > > to it I'd rather not have to complicate the oops printing to have to > > page in memory > > from disk, when it might be the disk that caused the oops. > > If the box was horked that way then you are going to fail to migrate the > graphical frame buffer out in order to go into text mode to print the > oops. Probably safest any oops hits the current visible object ? It's not always that simple either, e.g. this wouldn't work when scanning out a tiled buffer on Radeon HDs. -- Earthling Michel D?nzer | http://www.amd.com Libre software enthusiast | Debian, X and DRI developer
[PATCH 12/13] drm/radeon: fix a bug with the ring syncing code
On 24.04.2012 16:04, Dave Airlie wrote: > 2012/4/19 Christian K?nig: >> Rings need to lock in order, otherwise >> the ring subsystem can deadlock. > No sure if its the commit or not but I was profiling on an r700 and > saw it create a semaphore for ring syncing. > > surely the r700 would have no need? > In theory the first hardware with more than a gfx ring was some r6xx (but of course we haven't released any code/documentation for that yet), so it's ok that the code generally checks for inter ring synchronization needs on r7xx cards. But with the current mainline it should just boil down to an not taken "if" branch, witch it currently doesn't (*crap*). Just tested with my RV710 and I can confirm that it unnecessarily allocates a semaphore. Another bug on my todo list for this patchset, going to send out an v2 soon, but going to test it through first. Thanks for the comment, Christian.
[Bug 49110] AMDILCFGStructurizer.cpp:1751:3: error: 'isCurrentDebugType' was not declared in this scope
https://bugs.freedesktop.org/show_bug.cgi?id=49110 --- Comment #1 from Tom Stellard 2012-04-24 16:04:18 PDT --- I think this happens when you build Mesa with debugging enabled and LLVM without it enabled. It's still a bug though. For now, you could try building a debug version of both Mesa and LLVM. I think that will fix it. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/3] acpi_video: Intel video is not always i915
On Tue, Apr 24, 2012 at 11:31:17PM +0100, Alan Cox wrote: > On Tue, 24 Apr 2012 22:02:18 +0100 > Matthew Garrett wrote: > > The PowerVR Intels I'd seen had the opregion address in the 0xfc > > register as well. Is this no longer true on the latest? > > PowerVR does - i740 never did. > > The PowerVR 0xfc poking also doesn't currently work once the driver takes > over because it isn't yet implementing the driver end of the weird ACPI > messaging/event stuff. > > Once it does the GMA500 will be able to do an ACPI video register, but we > will still need the check to get the ifdeffery right for what drivers are > compiled for the kernel. Right now you seem to set opregion unconditionally on PVR, which seems to be equivalent to the 0xfc check that was there before - I can understand excluding i740, but the PVR check could be left with the gen hardware one? -- Matthew Garrett | mj...@srcf.ucam.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/3] acpi_video: Intel video is not always i915
On Tue, 24 Apr 2012 22:02:18 +0100 Matthew Garrett wrote: > On Tue, Apr 24, 2012 at 04:45:01PM +0100, Alan Cox wrote: > > From: Alan Cox > > > > Handle the GMA500/600/36x0 cases. Also stop it poking at random registers on > > the i740 cards that may be out there still. > > The PowerVR Intels I'd seen had the opregion address in the 0xfc > register as well. Is this no longer true on the latest? PowerVR does - i740 never did. The PowerVR 0xfc poking also doesn't currently work once the driver takes over because it isn't yet implementing the driver end of the weird ACPI messaging/event stuff. Once it does the GMA500 will be able to do an ACPI video register, but we will still need the check to get the ifdeffery right for what drivers are compiled for the kernel. Alan ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/edid: Try harder to fix up base EDID blocks
On Tue, Apr 24, 2012 at 2:56 PM, Adam Jackson wrote: > On 4/16/12 10:40 AM, Adam Jackson wrote: >> >> Requiring the first byte of the EDID base block header to be 0 means we >> don't fix up as many transfer errors as we could. ?Instead have the >> callers specify whether it's meant to be block 0 or not, and >> conditionally run header fixup based on that. > > > Anybody? ?This appears to be a pretty common form of EDID corruption. Seems reasonable to me. Reviewed-by: Alex Deucher > > - ajax > > > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 12/13] drm/radeon: fix a bug with the ring syncing code
2012/4/19 Christian K?nig : > Rings need to lock in order, otherwise > the ring subsystem can deadlock. No sure if its the commit or not but I was profiling on an r700 and saw it create a semaphore for ring syncing. surely the r700 would have no need? Dave.
[PATCH v2] scatterlist: add sg_alloc_table_from_pages function
This patch adds a new constructor for an sg table. The table is constructed from an array of struct pages. All contiguous chunks of the pages are merged into a single sg nodes. A user may provide an offset and a size of a buffer if the buffer is not page-aligned. The function is dedicated for DMABUF exporters which often perform conversion from an page array to a scatterlist. Moreover the scatterlist should be squashed in order to save memory and to speed-up the process of DMA mapping using dma_map_sg. The code is based on the patch 'v4l: vb2-dma-contig: add support for scatterlist in userptr mode' and hints from Laurent Pinchart. Signed-off-by: Tomasz Stanislawski Signed-off-by: Kyungmin Park --- include/linux/scatterlist.h |4 +++ lib/scatterlist.c | 63 +++ 2 files changed, 67 insertions(+), 0 deletions(-) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index ac9586d..7b600da 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -214,6 +214,10 @@ void sg_free_table(struct sg_table *); int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, sg_alloc_fn *); int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); +int sg_alloc_table_from_pages(struct sg_table *sgt, + struct page **pages, unsigned int n_pages, + unsigned long offset, unsigned long size, + gfp_t gfp_mask); size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen); diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 6096e89..90f9265 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -319,6 +319,69 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) EXPORT_SYMBOL(sg_alloc_table); /** + * sg_alloc_table_from_pages - Allocate and initialize an sg table from + *an array of pages + * @sgt: The sg table header to use + * @pages: Pointer to an array of page pointers + * @n_pages: Number of pages in the pages array + * @offset: Offset from a start of the first page to a start of a buffer + * @size: Number of valid bytes in the buffer (after offset) + * @gfp_mask: GFP allocation mask + * + * Description: + *Allocate and initialize an sg table from a list of pages. Continuous + *ranges of the pages are squashed into a single scatterlist node. A user + *may provide an offset at a start and a size of valid data in a buffer + *specified by the page array. The returned sg table is released by + *sg_free_table. + * + * Returns: + * 0 on success, negative error on failure + **/ +int sg_alloc_table_from_pages(struct sg_table *sgt, + struct page **pages, unsigned int n_pages, + unsigned long offset, unsigned long size, + gfp_t gfp_mask) +{ + unsigned int chunks; + unsigned int i; + unsigned int cur_page; + int ret; + struct scatterlist *s; + + /* compute number of contiguous chunks */ + chunks = 1; + for (i = 1; i < n_pages; ++i) + if (pages[i] != pages[i - 1] + 1) + ++chunks; + + ret = sg_alloc_table(sgt, chunks, gfp_mask); + if (unlikely(ret)) + return ret; + + /* merging chunks and putting them into the scatterlist */ + cur_page = 0; + for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { + unsigned long chunk_size; + unsigned int j; + + /* looking for the end of the current chunk */ + for (j = cur_page + 1; j < n_pages; ++j) + if (pages[j] != pages[j - 1] + 1) + break; + + chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset; + sg_set_page(s, pages[cur_page], min(size, chunk_size), offset); + size -= chunk_size; + offset = 0; + cur_page = j; + } + + return 0; +} +EXPORT_SYMBOL(sg_alloc_table_from_pages); + +/** * sg_miter_start - start mapping iteration over a sg list * @miter: sg mapping iter to be started * @sgl: sg list to iterate over -- 1.7.5.4
[PATCH] drm/edid: Try harder to fix up base EDID blocks
On 4/16/12 10:40 AM, Adam Jackson wrote: > Requiring the first byte of the EDID base block header to be 0 means we > don't fix up as many transfer errors as we could. Instead have the > callers specify whether it's meant to be block 0 or not, and > conditionally run header fixup based on that. Anybody? This appears to be a pretty common form of EDID corruption. - ajax
Re: [PATCH 2/3] acpi_video: Intel video is not always i915
On Tue, Apr 24, 2012 at 04:45:01PM +0100, Alan Cox wrote: > From: Alan Cox > > Handle the GMA500/600/36x0 cases. Also stop it poking at random registers on > the i740 cards that may be out there still. The PowerVR Intels I'd seen had the opregion address in the 0xfc register as well. Is this no longer true on the latest? -- Matthew Garrett | mj...@srcf.ucam.org ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 3/4] drm/exynos: added userptr feature.
this feature could be used to use memory region allocated by malloc() in user mode and mmaped memory region allocated by other memory allocators. userptr interface can identify memory type through vm_flags value and would get pages or page frame numbers to user space appropriately. changelog v2: the memory region mmaped with VM_PFNMAP type is physically continuous and start address of the memory region should be set into buf->dma_addr but previous patch had a problem that end address is set into buf->dma_addr so v2 fixes that problem. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_drv.c |2 + drivers/gpu/drm/exynos/exynos_drm_gem.c | 265 +++ drivers/gpu/drm/exynos/exynos_drm_gem.h | 13 ++- include/drm/exynos_drm.h| 25 +++- 4 files changed, 303 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index f58a487..5bb0361 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -211,6 +211,8 @@ static struct drm_ioctl_desc exynos_ioctls[] = { DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), + DRM_IOCTL_DEF_DRV(EXYNOS_GEM_USERPTR, + exynos_drm_gem_userptr_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, exynos_plane_set_zpos_ioctl, DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index afd0cd4..1ee5383 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -66,6 +66,43 @@ static int check_gem_flags(unsigned int flags) return 0; } +static struct vm_area_struct *get_vma(struct vm_area_struct *vma) +{ + struct vm_area_struct *vma_copy; + + vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL); + if (!vma_copy) + return NULL; + + if (vma->vm_ops && vma->vm_ops->open) + vma->vm_ops->open(vma); + + if (vma->vm_file) + get_file(vma->vm_file); + + memcpy(vma_copy, vma, sizeof(*vma)); + + vma_copy->vm_mm = NULL; + vma_copy->vm_next = NULL; + vma_copy->vm_prev = NULL; + + return vma_copy; +} + +static void put_vma(struct vm_area_struct *vma) +{ + if (!vma) + return; + + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + + if (vma->vm_file) + fput(vma->vm_file); + + kfree(vma); +} + static void update_vm_cache_attr(struct exynos_drm_gem_obj *obj, struct vm_area_struct *vma) { @@ -254,6 +291,41 @@ static void exynos_drm_gem_put_pages(struct drm_gem_object *obj) /* add some codes for UNCACHED type here. TODO */ } +static void exynos_drm_put_userptr(struct drm_gem_object *obj) +{ + struct exynos_drm_gem_obj *exynos_gem_obj; + struct exynos_drm_gem_buf *buf; + struct vm_area_struct *vma; + int npages; + + exynos_gem_obj = to_exynos_gem_obj(obj); + buf = exynos_gem_obj->buffer; + vma = exynos_gem_obj->vma; + + if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { + put_vma(exynos_gem_obj->vma); + goto out; + } + + npages = buf->size >> PAGE_SHIFT; + + npages--; + while (npages >= 0) { + if (buf->write) + set_page_dirty_lock(buf->pages[npages]); + + put_page(buf->pages[npages]); + npages--; + } + +out: + kfree(buf->pages); + buf->pages = NULL; + + kfree(buf->sgt); + buf->sgt = NULL; +} + static int exynos_drm_gem_handle_create(struct drm_gem_object *obj, struct drm_file *file_priv, unsigned int *handle) @@ -293,6 +365,8 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) exynos_drm_gem_put_pages(obj); + else if (exynos_gem_obj->flags & EXYNOS_BO_USERPTR) + exynos_drm_put_userptr(obj); else exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf); @@ -606,6 +680,197 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, return 0; } +static int exynos_drm_get_userptr(struct drm_device *dev, + struct exynos_drm_gem_obj *obj, + unsigned long userptr, + unsigned int write) +{ + unsigned int get_npages; + unsigned long npages = 0; + struct vm_area_struct *vma; + struct exynos_dr
[Bug 49110] New: AMDILCFGStructurizer.cpp:1751:3: error: 'isCurrentDebugType' was not declared in this scope
https://bugs.freedesktop.org/show_bug.cgi?id=49110 Bug #: 49110 Summary: AMDILCFGStructurizer.cpp:1751:3: error: 'isCurrentDebugType' was not declared in this scope Classification: Unclassified Product: Mesa Version: git Platform: x86 (IA32) OS/Version: Linux (All) Status: NEW Severity: normal Priority: medium Component: Drivers/Gallium/r600 AssignedTo: dri-devel at lists.freedesktop.org ReportedBy: fabio.ped at libero.it I get this compile error when building the new LLVM compiler: AMDILCFGStructurizer.cpp:1751:3: error: 'isCurrentDebugType' was not declared in this scope Full log is available here: https://launchpadlibrarian.net/102973365/buildlog_ubuntu-precise-amd64.mesa_8.1~git1204241446.587c22~gd~p_FAILEDTOBUILD.txt.gz -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
Enhancing EDID quirk functionality
On 04/24/2012 04:07 AM, Lars-Peter Clausen wrote: > I just had a similar issue with a different driver and remembered your post > > If the S bits in the infoframe are 0 the display may under- or overscan the > the image (Although the spec says it should behave the same if no infoframe > is present). If it is set to 2 the display should underscan the image, so > I'd be interested to see if the following patch changes the displays > behavior for you. > > > --- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c > +++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c > @@ -147,7 +147,7 @@ static void > nouveau_hdmi_video_infoframe(struct drm_encoder *encoder, >struct drm_display_mode *mode) > { > - const u8 Y = 0, A = 0, B = 0, S = 0, C = 0, M = 0, R = 0; > + const u8 Y = 0, A = 0, B = 0, S = 2, C = 0, M = 0, R = 0; > const u8 ITC = 0, EC = 0, Q = 0, SC = 0, VIC = 0, PR = 0; > const u8 bar_top = 0, bar_bottom = 0, bar_left = 0, bar_right = 0; > u8 frame[20]; No change. BTW, I've been grinding ahead with the EDID quirk infrastructure changes that I discussed in my previous note. I'd prefer not to waste huge amounts of my less-than-copious free time, so please speak up if you have any objections. (The preceding paragraph is not specifically directed at Lars-Peter.)
[Bug 43138] Radeon HD5450 fails to load cedar firmware ?
https://bugzilla.kernel.org/show_bug.cgi?id=43138 --- Comment #11 from Michel D?nzer 2012-04-24 13:42:41 --- (In reply to comment #10) > ...nope, as Debian considers that particular firmware to be "nonfree" it is > not > included in the initrd at all, That the firmware is in the firmware-linux-nonfree package merely means it's not installed on the system by default, it doesn't directly prevent the firmware from getting included in the initrd. > so it boils down to a somewhat misleading "bogus length" instead of a more > appropriate "file not found" error for all cases above. The lengths in the original error messages are the amounts of firmware data written by the /lib/udev/firmware.agent helper. If the firmware was missing altogether, how could the helper guess their sizes? Anyway, glad it's working for you now. -- Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are watching the assignee of the bug.
[Nouveau] [PATCH 2/5] drm/nouveau: base fence timeout on time of emission
On Mon, 2012-04-23 at 00:18 +0200, Marcin Slusarz wrote: > Wait loop can be interrupted by signal, so if signals are raised > periodically (e.g. SIGALRM) this loop may never finish. Use > emission time as a base for fence timeout. Ah, thanks for tackling this issue. It's been long on my list of things to do, but never quite made it to the top. Rather than hardcoding the timeout in fence_wait(), I think perhaps storing "fence->timeout = jiffies + (whatever * HZ);" is a better plan. I can forsee us wanting longer timeouts for certain operations (particularly long compute operations) in the future. Ben. > > Signed-off-by: Marcin Slusarz > --- > drivers/gpu/drm/nouveau/nouveau_fence.c |5 - > 1 files changed, 4 insertions(+), 1 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c > b/drivers/gpu/drm/nouveau/nouveau_fence.c > index a22b9ad..59f92e9 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_fence.c > +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c > @@ -44,6 +44,7 @@ struct nouveau_fence { > > uint32_t sequence; > bool signalled; > + unsigned long emitted_at; > > void (*work)(void *priv, bool signalled); > void *priv; > @@ -172,6 +173,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) > } > OUT_RING (chan, fence->sequence); > FIRE_RING(chan); > + fence->emitted_at = jiffies; > > return 0; > } > @@ -230,7 +232,8 @@ __nouveau_fence_signalled(void *sync_obj, void *sync_arg) > int > __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) > { > - unsigned long timeout = jiffies + (3 * DRM_HZ); > + struct nouveau_fence *fence = nouveau_fence(sync_obj); > + unsigned long timeout = fence->emitted_at + 3 * DRM_HZ; > unsigned long sleep_time = NSEC_PER_MSEC / 1000; > ktime_t t; > int ret = 0;
Re: [RFC PATCH 5/5] drm/nouveau: gpu lockup recovery
On Mon, Apr 23, 2012 at 06:56:44PM +0200, Martin Peres wrote: > Le 23/04/2012 18:32, Marcin Slusarz a écrit : > > > > Just run piglit. Even "quick" tests can cause ~5 lockups (it eventually > > messes > > up DDX channel, but this patchset can't fix this case). > > You can run fs-discard-exit-2 test first - for me it causes instant GPU > > lockup. > > > > Marcin > Great, Thanks. > > Did you have a look at > https://bugs.freedesktop.org/show_bug.cgi?id=40886 and > http://xorg.freedesktop.org/wiki/SummerOfCodeIdeas ? Yeah, I've seen them some time ago. > The Ubuntu xorg devs were looking for something like this, but they also > wanted a lockup report. Are you also interested on working on it ? Yes, when this patchset will be applied, I'm going to work on improving error reporting. Marcin ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/edid: Try harder to fix up base EDID blocks
On Mon, 16 Apr 2012 10:40:08 -0400, Adam Jackson wrote: > Requiring the first byte of the EDID base block header to be 0 means we > don't fix up as many transfer errors as we could. Instead have the > callers specify whether it's meant to be block 0 or not, and > conditionally run header fixup based on that. > > Bugzilla: https://bugzilla.redhat.com/812890 > Signed-off-by: Adam Jackson The patch does watch it says on the tin. I don't pretend to know how frequent this corruption is, but as it stands the current code fails to be as effective as it could be. Reviewed-by: Chris Wilson -Chris -- Chris Wilson, Intel Open Source Technology Centre ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/5] drm: add optional per device rwsem for all ioctls
On Mon, Apr 23, 2012 at 09:51:48AM +0200, Daniel Vetter wrote: > On Mon, Apr 23, 2012 at 12:18:28AM +0200, Marcin Slusarz wrote: > > Nouveau, in normal circumstances, does not need device lock for every ioctl, > > but incoming "gpu reset" code needs exclusive access to the device. > > This commit adds drm_driver flag which turns on read lock ioctl > > encapsulation. > > > > Signed-off-by: Marcin Slusarz > > Why can't we just move this down to nouveau driver code? Ok, I think it's easily possible by wrapping drm_ioctl. > So why can't nouveau do the same? Also, if this is indeed necessary and we > add this as some mandatory core infrastructure, it's not good enough: In > i915 we go to great lengths to ensure that all processes waiting for gpu > reset are still interruptible, in case the gpu reset dies unexpectedly > (which happens), so this would need to be improved. I came up with a scheme where down_read can be made interruptible. I'll post both changes in a few days. (Unfortunately adding proper down_read_interruptible / down_write_interruptible require a bit of unfunny work - 8 architectures have their own code for rwsems) Marcin ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/edid: Try harder to fix up base EDID blocks
On Tue, Apr 24, 2012 at 2:56 PM, Adam Jackson wrote: > On 4/16/12 10:40 AM, Adam Jackson wrote: >> >> Requiring the first byte of the EDID base block header to be 0 means we >> don't fix up as many transfer errors as we could. Instead have the >> callers specify whether it's meant to be block 0 or not, and >> conditionally run header fixup based on that. > > > Anybody? This appears to be a pretty common form of EDID corruption. Seems reasonable to me. Reviewed-by: Alex Deucher > > - ajax > > > ___ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: Enhancing EDID quirk functionality
On 04/24/2012 04:07 AM, Lars-Peter Clausen wrote: I just had a similar issue with a different driver and remembered your post If the S bits in the infoframe are 0 the display may under- or overscan the the image (Although the spec says it should behave the same if no infoframe is present). If it is set to 2 the display should underscan the image, so I'd be interested to see if the following patch changes the displays behavior for you. --- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c +++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c @@ -147,7 +147,7 @@ static void nouveau_hdmi_video_infoframe(struct drm_encoder *encoder, struct drm_display_mode *mode) { - const u8 Y = 0, A = 0, B = 0, S = 0, C = 0, M = 0, R = 0; + const u8 Y = 0, A = 0, B = 0, S = 2, C = 0, M = 0, R = 0; const u8 ITC = 0, EC = 0, Q = 0, SC = 0, VIC = 0, PR = 0; const u8 bar_top = 0, bar_bottom = 0, bar_left = 0, bar_right = 0; u8 frame[20]; No change. BTW, I've been grinding ahead with the EDID quirk infrastructure changes that I discussed in my previous note. I'd prefer not to waste huge amounts of my less-than-copious free time, so please speak up if you have any objections. (The preceding paragraph is not specifically directed at Lars-Peter.) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/edid: Try harder to fix up base EDID blocks
On 4/16/12 10:40 AM, Adam Jackson wrote: Requiring the first byte of the EDID base block header to be 0 means we don't fix up as many transfer errors as we could. Instead have the callers specify whether it's meant to be block 0 or not, and conditionally run header fixup based on that. Anybody? This appears to be a pretty common form of EDID corruption. - ajax ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Nouveau] [PATCH 2/5] drm/nouveau: base fence timeout on time of emission
On Tue, Apr 24, 2012 at 12:37:34PM +1000, Ben Skeggs wrote: > On Mon, 2012-04-23 at 00:18 +0200, Marcin Slusarz wrote: > > Wait loop can be interrupted by signal, so if signals are raised > > periodically (e.g. SIGALRM) this loop may never finish. Use > > emission time as a base for fence timeout. > Ah, thanks for tackling this issue. It's been long on my list of things > to do, but never quite made it to the top. > > Rather than hardcoding the timeout in fence_wait(), I think perhaps > storing "fence->timeout = jiffies + (whatever * HZ);" is a better plan. > I can forsee us wanting longer timeouts for certain operations > (particularly long compute operations) in the future. Yeah, good idea. Later, we will probably need to add code which will keep extending this timeout as long as gpu is progressing. Marcin ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Linux 3.4-rc4
On Mon, Apr 23, 2012 at 09:03:45PM -0400, Nick Bowler wrote: > On 2012-04-22 22:45 -0400, Konrad Rzeszutek Wilk wrote: > > On Sun, Apr 22, 2012 at 08:05:54PM -0400, Nick Bowler wrote: > > > Following up on the above, the commit which introduces the panics during > > > boot is this one: > > > > > > commit 8e7e70522d760c4ccd4cd370ebfa0ba69e006c6e > > > Author: Jerome Glisse > > > Date: Wed Nov 9 17:15:26 2011 -0500 > > > > > > drm/ttm: isolate dma data from ttm_tt V4 > > > > I think > > > > dea7e0a ttm: fix agp since ttm tt rework > > > > fixed that. > > Yes, I just tested this commit and the one immediately before it. The > one before crashes in the usual way, and dea7e0a boots (with the VGA > output black as in the original report). So this fixed the crash. > > Now, returning to the original bisection, I marked that commit as "bad" > and dropped all the earlier "skip" markings. Git asks me to test commit > 2a44e4997c5f ("drm/nouveau/disp: introduce proper init/fini, separate > from create/destroy"). I cherry picked the aforementioned ttm fix: > > git cherry-pick -n dea7e0a > > which succeeded. Howevew, the resulting kernel still crashes early, > although now in a different way. I just can't win :( Perhaps there is a better way. You could do this: git log --oneline -r v3.2..v3.3 drivers/gpu/drm/nouveau to get an idea of the set of patches that went in. And use that, so git bisect start -- drivers/gpu/drm/nouveau [this should only do the bisection on those patches] git bisect good v3.2 git bisect bad v3.3 And keep in mind the dea7e0a might need to be stuck on some of these. This _should_ limit the bisection to just the nouveau changes, I hope.
[PATCH] dma-buf: mmap support
Compared to Rob Clark's RFC I've ditched the prepare/finish hooks and corresponding ioctls on the dma_buf file. The major reason for that is that many people seem to be under the impression that this is also for synchronization with outstanding asynchronous processsing. I'm pretty massively opposed to this because: - It boils down reinventing a new rather general-purpose userspace synchronization interface. If we look at things like futexes, this is hard to get right. - Furthermore a lot of kernel code has to interact with this synchronization primitive. This smells a look like the dri1 hw_lock, a horror show I prefer not to reinvent. - Even more fun is that multiple different subsystems would interact here, so we have plenty of opportunities to create funny deadlock scenarios. I think synchronization is a wholesale different problem from data sharing and should be tackled as an orthogonal problem. Now we could demand that prepare/finish may only ensure cache coherency (as Rob intended), but that runs up into the next problem: We not only need mmap support to facilitate sw-only processing nodes in a pipeline (without jumping through hoops by importing the dma_buf into some sw-access only importer), which allows for a nicer ION->dma-buf upgrade path for existing Android userspace. We also need mmap support for existing importing subsystems to support existing userspace libraries. And a loot of these subsystems are expected to export coherent userspace mappings. So prepare/finish can only ever be optional and the exporter /needs/ to support coherent mappings. Given that mmap access is always somewhat fallback-y in nature I've decided to drop this optimization, instead of just making it optional. If we demonstrate a clear need for this, supported by benchmark results, we can always add it in again later as an optional extension. Other differences compared to Rob's RFC is the above mentioned support for mapping a dma-buf through facilities provided by the importer. Which results in mmap support no longer being optional. Note that this dma-buf mmap patch does _not_ support every possible insanity an existing subsystem could pull of with mmap: Because it does not allow to intercept pagefaults and shoot down ptes importing subsystems can't add some magic of their own at these points (e.g. to automatically synchronize with outstanding rendering or set up some special resources). I've done a cursory read through a few mmap implementions of various subsytems and I'm hopeful that we can avoid this (and the complexity it'd bring with it). Additonally I've extended the documentation a bit to explain the hows and whys of this mmap extension. In case we ever want to add support for explicitly cache maneged userspace mmap with a prepare/finish ioctl pair, we could specify that userspace needs to mmap a different part of the dma_buf, e.g. the range starting at dma_buf->size up to dma_buf->size*2. This works because the size of a dma_buf is invariant over it's lifetime. The exporter would obviously need to fall back to coherent mappings for both ranges if a legacy clients maps the coherent range and the architecture cannot suppor conflicting caching policies. Also, this would obviously be optional and userspace needs to be able to fall back to coherent mappings. v2: - Spelling fixes from Rob Clark. - Compile fix for !DMA_BUF from Rob Clark. - Extend commit message to explain how explicitly cache managed mmap support could be added later. - Extend the documentation with implementations notes for exporters that need to manually fake coherency. v3: - dma_buf pointer initialization goof-up noticed by Rebecca Schultz Zavin. Cc: Rob Clark Cc: Rebecca Schultz Zavin Signed-Off-by: Daniel Vetter --- Documentation/dma-buf-sharing.txt | 98 ++--- drivers/base/dma-buf.c| 64 +++- include/linux/dma-buf.h | 16 ++ 3 files changed, 170 insertions(+), 8 deletions(-) diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt index 3bbd5c5..5ff4d2b 100644 --- a/Documentation/dma-buf-sharing.txt +++ b/Documentation/dma-buf-sharing.txt @@ -29,13 +29,6 @@ The buffer-user in memory, mapped into its own address space, so it can access the same area of memory. -*IMPORTANT*: [see https://lkml.org/lkml/2011/12/20/211 for more details] -For this first version, A buffer shared using the dma_buf sharing API: -- *may* be exported to user space using "mmap" *ONLY* by exporter, outside of - this framework. -- with this new iteration of the dma-buf api cpu access from the kernel has been - enable, see below for the details. - dma-buf operations for device dma only -- @@ -313,6 +306,83 @@ Access to a dma_buf from the kernel context involves three steps: enum dma_data_direction dir); +Direct Userspace Access/mmap Support +-
Enhancing EDID quirk functionality
On 04/19/2012 09:16 PM, Ian Pilcher wrote: > Greetings all! > > I recently discovered that my nice 1900x1200 display is horribly > confused by the InfoFrame functionality that was added to the nouveau > driver in Linux 3.3. Additional testing has shown that it has the same > problem with the i915 driver and NVIDIA's proprietary driver. > I just had a similar issue with a different driver and remembered your post If the S bits in the infoframe are 0 the display may under- or overscan the the image (Although the spec says it should behave the same if no infoframe is present). If it is set to 2 the display should underscan the image, so I'd be interested to see if the following patch changes the displays behavior for you. --- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c +++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c @@ -147,7 +147,7 @@ static void nouveau_hdmi_video_infoframe(struct drm_encoder *encoder, struct drm_display_mode *mode) { - const u8 Y = 0, A = 0, B = 0, S = 0, C = 0, M = 0, R = 0; + const u8 Y = 0, A = 0, B = 0, S = 2, C = 0, M = 0, R = 0; const u8 ITC = 0, EC = 0, Q = 0, SC = 0, VIC = 0, PR = 0; const u8 bar_top = 0, bar_bottom = 0, bar_left = 0, bar_right = 0; u8 frame[20];
[Patch 3/3] edid override: make edid writable in sysfs
From: Thorsten Schoel Makes class/drm/[CONNECTOR]/edid writable for adding edid overrides. Signed-off-by: Thorsten Schoel --- diff -Nurp infra/drivers/gpu/drm/drm_sysfs.c sysfs/drivers/gpu/drm/drm_sysfs.c --- infra/drivers/gpu/drm/drm_sysfs.c 2012-01-12 20:42:45.0 +0100 +++ sysfs/drivers/gpu/drm/drm_sysfs.c 2012-01-25 22:13:08.0 +0100 @@ -21,6 +21,8 @@ #include "drm_sysfs.h" #include "drm_core.h" #include "drmP.h" +#include "drm_edid.h" +#include "drm_crtc.h" #define to_drm_minor(d) container_of(d, struct drm_minor, kdev) #define to_drm_connector(d) container_of(d, struct drm_connector, kdev) @@ -228,6 +230,44 @@ static ssize_t edid_show(struct file *fi return count; } +static ssize_t edid_override(struct file *filp, struct kobject *kobj, +struct bin_attribute *attr, char *buf, loff_t off, +size_t count) +{ + struct device *connector_dev = container_of(kobj, struct device, kobj); + struct drm_connector *connector = to_drm_connector(connector_dev); + char *connector_name; + unsigned char *edid_new; + + connector_name = drm_get_connector_name(connector); + + if (!count) { + drm_edid_override_remove(connector_name); + return 0; + } + + /* Only support writing the whole EDID in one piece */ + if (off) + return 0; + + if (count < EDID_LENGTH) + return 0; + if (count != (buf[0x7e] + 1) * EDID_LENGTH) + return 0; + + edid_new = kmalloc(count, GFP_KERNEL); + if (!edid_new) + return 0; + + memcpy(edid_new, buf, count); + + if (drm_edid_override_set(connector_name, (struct edid *)edid_new) < 0) + count = 0; + + kfree(edid_new); + return count; +} + static ssize_t modes_show(struct device *device, struct device_attribute *attr, char *buf) @@ -341,9 +381,10 @@ static struct device_attribute connector static struct bin_attribute edid_attr = { .attr.name = "edid", - .attr.mode = 0444, + .attr.mode = 0644, .size = 0, .read = edid_show, + .write = edid_override, }; /** ---
[Patch 2/3] edid override: module parameter
From: Thorsten Schoel Allows for setting edid overrides through new parameter edid_override for module drm. Signed-off-by: Thorsten Schoel --- diff -Nurp infra/drivers/gpu/drm/drm_edid.c param/drivers/gpu/drm/drm_edid.c --- infra/drivers/gpu/drm/drm_edid.c2012-01-25 22:12:59.0 +0100 +++ param/drivers/gpu/drm/drm_edid.c2012-01-25 22:14:51.0 +0100 @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include "drmP.h" #include "drm_edid.h" @@ -232,11 +234,37 @@ struct drm_edid_override { struct list_head list; char *connector; + char *param; struct edid *edid; unsigned num_blocks; }; LIST_HEAD(drm_edid_override_list); + +static int drm_edid_override_ops__get(char *buffer, const struct kernel_param *kp); +static int drm_edid_override_ops__set(const char *val, const struct kernel_param *kp); +static void drm_edid_override_ops__free(void *arg); + + +struct kernel_param_ops drm_edid_override_ops = { + .get = drm_edid_override_ops__get, + .set = drm_edid_override_ops__set, + .free = drm_edid_override_ops__free +}; + +MODULE_PARM_DESC(edid_override, "Override the EDID data of a monitor. " + "This should be a comma separated list of entries of the format " + "[connector name]:[data]. data is either raw EDID data encoded in " + "hexadecimal format, or, if it cannot be parsed as such, the name " + "of a file containing the EDID data to be loaded through " + "request_firmware. Examples:\nVGA-1:syncmaster913n.edid\n" + "DVI-I-1:00?"); +module_param_cb(edid_override, + &drm_edid_override_ops, + &drm_edid_override_list, + 0600); + + /* * Free the memory associated with an EDID override. */ @@ -246,6 +273,7 @@ drm_edid_override_delete(struct drm_edid if (entry->edid) kfree(entry->edid); kfree(entry->connector); + /* param is generated from the same piece of memory through strsep */ kfree(entry); } @@ -270,7 +299,7 @@ drm_edid_override_remove(const char *con EXPORT_SYMBOL(drm_edid_override_remove); static int -drm_edid_override_do_set(char *connector, struct edid *edid, unsigned num_blocks) +drm_edid_override_do_set(char *connector, struct edid *edid, unsigned num_blocks, char *param) { struct drm_edid_override *entry = NULL; int found = 0; @@ -300,6 +329,7 @@ drm_edid_override_do_set(char *connector entry->connector = connector; entry->edid = edid; entry->num_blocks = num_blocks; + entry->param = param; if (!found) list_add_tail(&entry->list, &drm_edid_override_list); @@ -308,6 +338,25 @@ drm_edid_override_do_set(char *connector return 0; } +/* + * Helper function for setter of module parameter. + */ +static int +drm_edid_override_set_from_param(char *val) +{ + char *connector = NULL, *param = NULL; + + connector = strsep(&val, ":"); + param = strlen(val) ? val : NULL; + + if (param) + return drm_edid_override_do_set(connector, NULL, 0, param); + else + drm_edid_override_remove(connector); + + return 0; +} + /** * Add a new override for connector if none has been set yet or replace the * current one. @@ -336,10 +385,179 @@ drm_edid_override_set(const char *connec } memcpy(edid_dup, edid, edid_size); - return drm_edid_override_do_set(connector_dup, edid_dup, num_blocks); + return drm_edid_override_do_set(connector_dup, edid_dup, num_blocks, NULL); } EXPORT_SYMBOL(drm_edid_override_set); +/* + * Setter for module parameter. + */ +static int +drm_edid_override_ops__set(const char *val, const struct kernel_param *kp) +{ + const char *master = val; + char *substr = NULL; + int result = 0; + + do { + const char *new_master = strchr(master, ','); + int substr_len = 0; + + if (new_master) + substr_len = new_master - master; + else + substr_len = strlen(master); + + substr = kstrndup(master, substr_len, GFP_KERNEL); + if (!substr) + return -ENOMEM; + + result = drm_edid_override_set_from_param(substr); + if (result) + return result; + + master = new_master; + } while (master); + + return 0; +} + +/* moduleparam.h claims this is "4k" */ +#define OPT_GET__BUFFER_LENGTH 4096 +/* + * Getter for module parameter. Will produce a comma separated list of + * all connectors an override has been set for. + */ +static int +drm_edid_override_ops__get(char *buffer, const struct kernel_param *kp) +{ + struct drm_edid_override *entry = NULL; + int remaining_buf = OPT_GET_
[Patch 1/3] edid override: infrastructure
From: Thorsten Schoel Provides infrastructure for overriding edid information of individual monitors. Signed-off-by: Thorsten Schoel --- diff -Nurp vanilla/drivers/gpu/drm/drm_edid.c infra/drivers/gpu/drm/drm_edid.c --- vanilla/drivers/gpu/drm/drm_edid.c 2012-01-25 22:29:25.0 +0100 +++ infra/drivers/gpu/drm/drm_edid.c2012-01-25 22:12:59.0 +0100 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include "drmP.h" #include "drm_edid.h" @@ -226,6 +228,158 @@ bool drm_edid_is_valid(struct edid *edid } EXPORT_SYMBOL(drm_edid_is_valid); +struct drm_edid_override { + struct list_head list; + + char *connector; + struct edid *edid; + unsigned num_blocks; +}; +LIST_HEAD(drm_edid_override_list); + +/* + * Free the memory associated with an EDID override. + */ +static void +drm_edid_override_delete(struct drm_edid_override *entry) +{ + if (entry->edid) + kfree(entry->edid); + kfree(entry->connector); + kfree(entry); +} + +/** + * Remove an existing override. + * + * \param connector : name of a drm_connector + */ +void +drm_edid_override_remove(const char *connector) +{ + struct drm_edid_override *entry = NULL; + + list_for_each_entry (entry, &drm_edid_override_list, list) { + if (strcmp(entry->connector, connector)) + continue; + list_del(&entry->list); + drm_edid_override_delete(entry); + break; + } +} +EXPORT_SYMBOL(drm_edid_override_remove); + +static int +drm_edid_override_do_set(char *connector, struct edid *edid, unsigned num_blocks) +{ + struct drm_edid_override *entry = NULL; + int found = 0; + + /* replace previous entry if present */ + list_for_each_entry (entry, &drm_edid_override_list, list) { + if (strcmp(connector, entry->connector)) + continue; + found = 1; + break; + } + + if (!found) { + entry = kmalloc(sizeof(struct drm_edid_override), GFP_KERNEL); + if (!entry) { + kfree(connector); + kfree(edid); + return -ENOMEM; + } + INIT_LIST_HEAD(&entry->list); + } else { + kfree(entry->connector); + if (entry->edid) + kfree(entry->edid); + } + + entry->connector = connector; + entry->edid = edid; + entry->num_blocks = num_blocks; + + if (!found) + list_add_tail(&entry->list, &drm_edid_override_list); + DRM_INFO("Set new EDID override for connector %s", connector); + + return 0; +} + +/** + * Add a new override for connector if none has been set yet or replace the + * current one. + * + * \param connector : name of a drm_connector as retrieved through drm_get_connector_name + * \param edid : binary EDID data + */ +int +drm_edid_override_set(const char *connector, const struct edid *edid) +{ + char *connector_dup = NULL; + struct edid *edid_dup = NULL; + int num_blocks = 0; + unsigned edid_size = 0; + + connector_dup = kstrdup(connector, GFP_KERNEL); + if (!connector_dup) + return -ENOMEM; + + num_blocks = edid->extensions + 1; + edid_size = num_blocks * EDID_LENGTH; + edid_dup = kmalloc(edid_size, GFP_KERNEL); + if (!edid_dup) { + kfree(connector_dup); + return -ENOMEM; + } + memcpy(edid_dup, edid, edid_size); + + return drm_edid_override_do_set(connector_dup, edid_dup, num_blocks); +} +EXPORT_SYMBOL(drm_edid_override_set); + +/** + * Get EDID information from overrides list if available. + * + * \param connector : DRM connector to get EDID for + * \return a newly allocated edid structure filled with the EDID data from the + *override or NULL if no override for @connector could be found. + */ +static struct edid * +drm_edid_override_get (struct drm_connector *connector) +{ + struct list_head *pos = NULL; + struct drm_edid_override *entry = NULL; + char *connector_name = NULL; + struct edid *result = NULL; + + connector_name = drm_get_connector_name(connector); + + list_for_each(pos, &drm_edid_override_list) { + entry = (struct drm_edid_override *) + list_entry(pos, struct drm_edid_override, list); + if(!strcmp(entry->connector, connector_name)) + break; + else + entry = NULL; + } + + if (!entry) + return NULL; + + if (!entry->edid) { + DRM_ERROR("EDID override without EDID data for connector %s", connector_name); + return NULL; + } + + if
[Patch 0/3] Add ability to override a monitor's EDID information
Hello everybody, having a monitor provide wrong or invalid EDID information ? or none at all ? seems to be a problem quite a number of people are facing. A few of the non-KMS X-drivers provide individual mechanisms for overriding such an EDID with user provided data. To my knowledge at least the kernel currently falls short of providing such a mechanism. This set of patches attempts to provide one. It has a number of potential shortcoming to which I was not yet able to find any solution. These are: 1. It uses drm_get_connector_name to identify a connector. I am not entirely sure though if these names are guaranteed to be unique (the names used in /sys/class/drm seem to suggest they are not). Since they are good enough for the kernel's video parameter, though, I figured they should be good enough for the present purpose as well. 2. One of the patches introduces a new kernel parameter (edid_override). This parameter takes either the raw edid-data encoded as a hex-string or the name of a firmware file from which to load the data. I am a bit unhappy with both solutions since the first puts raw data on the command line and makes it rather long and the second? well edid-data is not exactly firmware in the strict sense. It may be firm, but it is probably not ware. 3. I thought about making the sysfs code more sophisticated so that individual bytes could be written at any position within the data. Yet, there seems to be no way to truncate a file in sysfs which would be important when changing the number of 128 byte blocks the data is made up of. In addition, I cannot see what good such a behaviour would be or how the obscure use probably is somewhere out there could justify the additional complexity. I therefore opted for the approach of only allowing writes of complete edid-blobs in one pass. The patches I submit were tested on an x64 with radeon graphics and on an x86 with i915. They were made for 3.4. drivers/gpu/drm/drm_edid.c | 399 +++- drivers/gpu/drm/drm_sysfs.c | 43 include/drm/drm_crtc.h |2 3 files changed, 435 insertions(+), 9 deletions(-)
PCI resources above 4GB
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 16/04/12 18:29, Yinghai Lu wrote: > On Sun, Apr 15, 2012 at 11:54 PM, Yinghai Lu > wrote: >> On Sun, Apr 15, 2012 at 1:06 PM, Yinghai Lu >> wrote: 3. use pci_bus_allocate_resource in drm/radeon driver ... ===> but that could fail. so could hack it like a. disable bar 0x10 and steal BAR address, then set 0x30 to that address then copy ROM to ram. after that, disable rom again and set back address to 0x10. You try to update radeon_get_bios() to achieve that. >> >> patches for solution 3: map_rom.patch will try to borrow mem or >> mem pref bar for ROM copying >> >> and You still need to use pci=norom > > map_rom.patch missed one ! > > Please check map_rom_v2.patch > Hopefully, I'm going to have time to look into this again later today, depending how well other tasks go... -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.19 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk+WdwwACgkQGcb56gMuC62DgQCglk+MxOIxWxbLChNWNlAOdbSp tysAnA83Mfa6tZ6TC97xHIqpFqtPJ5Wc =Vd8+ -END PGP SIGNATURE-
[Bug 43138] Radeon HD5450 fails to load cedar firmware ?
https://bugzilla.kernel.org/show_bug.cgi?id=43138 bugtraq at hobbit.in-berlin.de changed: What|Removed |Added Resolution|CODE_FIX|INVALID -- Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are watching the assignee of the bug.
[Bug 43138] Radeon HD5450 fails to load cedar firmware ?
https://bugzilla.kernel.org/show_bug.cgi?id=43138 bugtraq at hobbit.in-berlin.de changed: What|Removed |Added Status|NEW |RESOLVED Resolution||CODE_FIX --- Comment #10 from bugtraq at hobbit.in-berlin.de 2012-04-24 10:17:27 --- stupid me should've checked this beforehand, very sorry for having wasted your time & thanks for your patience... ...nope, as Debian considers that particular firmware to be "nonfree" it is not included in the initrd at all, so it boils down to a somewhat misleading "bogus length" instead of a more appropriate "file not found" error for all cases above. issue solved. -- Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are watching the assignee of the bug.
Re: [PATCH] dma-buf: mmap support
On Wed, Apr 25, 2012 at 01:37:51AM +0900, InKi Dae wrote: > Hi, > > > > > +static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct > > *vma) > > +{ > > + struct dma_buf *dmabuf; > > + > > + if (!is_dma_buf_file(file)) > > + return -EINVAL; > > + > > + dmabuf = file->private_data; > > + > > + /* check for overflowing the buffer's size */ > > + if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > > > + dmabuf->size >> PAGE_SHIFT) > > is this condition right? your intention is for checking buffer's size > is valid or not. by the way why is vma->vm_pgoff added to vm region > size? This check here is to ensure that userspace cannot mmap beyong the end of the dma_buf object. vm_pgoff is the offset userspace passed in at mmap time and hence needs to be added. Note that vm_end and vm_start are in bytes, wheres vm_pgoff is in pages. > > + return -EINVAL; > > + > > + return dmabuf->ops->mmap(dmabuf, vma); > > +} > > + > > static const struct file_operations dma_buf_fops = { > > .release = dma_buf_release, > > + .mmap = dma_buf_mmap_internal, > > }; > > > > /* > > @@ -82,7 +100,8 @@ struct dma_buf *dma_buf_export(void *priv, const struct > > dma_buf_ops *ops, > > || !ops->unmap_dma_buf > > || !ops->release > > || !ops->kmap_atomic > > - || !ops->kmap)) { > > + || !ops->kmap > > + || !ops->mmap)) { > > return ERR_PTR(-EINVAL); > > } > > > > @@ -406,3 +425,46 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned > > long page_num, > > dmabuf->ops->kunmap(dmabuf, page_num, vaddr); > > } > > EXPORT_SYMBOL_GPL(dma_buf_kunmap); > > + > > + > > +/** > > + * dma_buf_mmap - Setup up a userspace mmap with the given vma > > + * @dma_buf: [in] buffer that should back the vma > > + * @vma: [in] vma for the mmap > > + * @pgoff: [in] offset in pages where this mmap should start within > > the > > + * dma-buf buffer. > > + * > > + * This function adjusts the passed in vma so that it points at the file > > of the > > + * dma_buf operation. It alsog adjusts the starting pgoff and does bounds > > + * checking on the size of the vma. Then it calls the exporters mmap > > function to > > + * set up the mapping. > > + * > > + * Can return negative error values, returns 0 on success. > > + */ > > +int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, > > + unsigned long pgoff) > > +{ > > + if (WARN_ON(!dmabuf || !vma)) > > + return -EINVAL; > > + > > + /* check for offset overflow */ > > + if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff) > > ditto. isn't it checked whether page offset to be mmaped is placed > within vm region or not with the condition, if ((vma->vm_end - > vma->vm_start) >> PAGE_SHIFT) < pgoff)? Nope, this check only checks for overflow. The pgoff is the offset within the dma_buf object. E.g. a drm driver splits up it mmap space into pieces, which map to individual buffers. If userspace just mmaps parts of such a buffer, the importer can pass the offset in pgoff. But I expect this to be 0 for almost all cases. Note that we don't need this overflow check in the internal mmap function because do_mmap will do it for us. But here the importer potentially sets a completely different pgoff, so we need to do it. dma_buf documentation also mentions this (and that importers do not have to do these checks). Yours, Daniel > > > + return -EOVERFLOW; > > + > > + /* check for overflowing the buffer's size */ > > + if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > > > + dmabuf->size >> PAGE_SHIFT) > > + return -EINVAL; > > + > > + /* readjust the vma */ > > + if (vma->vm_file) > > + fput(vma->vm_file); > > + > > + vma->vm_file = dmabuf->file; > > + get_file(vma->vm_file); > > + > > + vma->vm_pgoff = pgoff; > > + > > + return dmabuf->ops->mmap(dmabuf, vma); > > +} > > +EXPORT_SYMBOL_GPL(dma_buf_mmap); > > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > > index 3efbfc2..1f78d15 100644 > > --- a/include/linux/dma-buf.h > > +++ b/include/linux/dma-buf.h > > @@ -61,6 +61,10 @@ struct dma_buf_attachment; > > * This Callback must not sleep. > > * @kmap: maps a page from the buffer into kernel address space. > > * @kunmap: [optional] unmaps a page from the buffer. > > + * @mmap: used to expose the backing storage to userspace. Note that the > > + * mapping needs to be coherent - if the exporter doesn't directly > > + * support this, it needs to fake coherency by shooting down any ptes > > + * when transitioning away from the cpu d
state of drm next
On Fri, Apr 20, 2012 at 10:10 PM, Alex Deucher wrote: > On Fri, Apr 20, 2012 at 8:27 AM, Dave Airlie wrote: >> Hi, >> >> So I've spent today trawling and most likely missing patches on the >> list for -next. >> >> -next before today had: >> an intel -next from Daniel >> radeon - copy optimisation, pci bus master race fix. >> two agp patches >> >> I've merged today into drm-core-next >> Ville's framebuffer creation sanity check series >> Paulo's CEA/EDID patches that touch core (I think there are two i915 >> patches that can come via Daniel). >> Lars-Peter Clausen: CEA/EDID patches >> Ajax's: DMT modes adding patches >> >> I've also got in -next: >> mjg59's work on multiple gpu with EFI interactions, I'll push to >> -core-next once it stops breaking builds on misc arches! >> >> So feel free to point me at anything I've missed or haven't commented >> on, and everyone keep reviewing everyone else's stuff as a path to >> success, as I'm busy!! > > Can you pick the following patches? > http://lists.freedesktop.org/archives/dri-devel/2012-March/020577.html > http://lists.freedesktop.org/archives/dri-devel/2012-March/020717.html > http://lists.freedesktop.org/archives/dri-devel/2012-March/020855.html I've merged these 3 to drm-core-next. Dave.
[Bug 27563] [810] Xorg freezes sometimes when playing Crack-Attack (races in drivers/char/drm/drm.ko?)
https://bugs.freedesktop.org/show_bug.cgi?id=27563 Daniel Vetter changed: What|Removed |Added Status|NEW |RESOLVED Resolution||WONTFIX --- Comment #6 from Daniel Vetter 2012-04-24 02:56:15 PDT --- I've looked a few times into the i810 drm kernel driver to clean up various things all accross drm, and the code in there is horrible. It is so horrible that you stop caring about race conditions you noticed after reading just a few functions of code ... :( Given that, I think the only way to fix this disaster is to rewrite the i810 support as a new, clean kernel modeset driver. That needs a volunteer with too much time. Hence I'll close this as wontfix. Sorry. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
Re: [PATCH] dma-buf: mmap support
Hi, > > +static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct > *vma) > +{ > + struct dma_buf *dmabuf; > + > + if (!is_dma_buf_file(file)) > + return -EINVAL; > + > + dmabuf = file->private_data; > + > + /* check for overflowing the buffer's size */ > + if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > > + dmabuf->size >> PAGE_SHIFT) is this condition right? your intention is for checking buffer's size is valid or not. by the way why is vma->vm_pgoff added to vm region size? > + return -EINVAL; > + > + return dmabuf->ops->mmap(dmabuf, vma); > +} > + > static const struct file_operations dma_buf_fops = { > .release = dma_buf_release, > + .mmap = dma_buf_mmap_internal, > }; > > /* > @@ -82,7 +100,8 @@ struct dma_buf *dma_buf_export(void *priv, const struct > dma_buf_ops *ops, > || !ops->unmap_dma_buf > || !ops->release > || !ops->kmap_atomic > - || !ops->kmap)) { > + || !ops->kmap > + || !ops->mmap)) { > return ERR_PTR(-EINVAL); > } > > @@ -406,3 +425,46 @@ void dma_buf_kunmap(struct dma_buf *dmabuf, unsigned > long page_num, > dmabuf->ops->kunmap(dmabuf, page_num, vaddr); > } > EXPORT_SYMBOL_GPL(dma_buf_kunmap); > + > + > +/** > + * dma_buf_mmap - Setup up a userspace mmap with the given vma > + * @dma_buf: [in] buffer that should back the vma > + * @vma: [in] vma for the mmap > + * @pgoff: [in] offset in pages where this mmap should start within > the > + * dma-buf buffer. > + * > + * This function adjusts the passed in vma so that it points at the file of > the > + * dma_buf operation. It alsog adjusts the starting pgoff and does bounds > + * checking on the size of the vma. Then it calls the exporters mmap > function to > + * set up the mapping. > + * > + * Can return negative error values, returns 0 on success. > + */ > +int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, > + unsigned long pgoff) > +{ > + if (WARN_ON(!dmabuf || !vma)) > + return -EINVAL; > + > + /* check for offset overflow */ > + if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff) ditto. isn't it checked whether page offset to be mmaped is placed within vm region or not with the condition, if ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff)? > + return -EOVERFLOW; > + > + /* check for overflowing the buffer's size */ > + if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > > + dmabuf->size >> PAGE_SHIFT) > + return -EINVAL; > + > + /* readjust the vma */ > + if (vma->vm_file) > + fput(vma->vm_file); > + > + vma->vm_file = dmabuf->file; > + get_file(vma->vm_file); > + > + vma->vm_pgoff = pgoff; > + > + return dmabuf->ops->mmap(dmabuf, vma); > +} > +EXPORT_SYMBOL_GPL(dma_buf_mmap); > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > index 3efbfc2..1f78d15 100644 > --- a/include/linux/dma-buf.h > +++ b/include/linux/dma-buf.h > @@ -61,6 +61,10 @@ struct dma_buf_attachment; > * This Callback must not sleep. > * @kmap: maps a page from the buffer into kernel address space. > * @kunmap: [optional] unmaps a page from the buffer. > + * @mmap: used to expose the backing storage to userspace. Note that the > + * mapping needs to be coherent - if the exporter doesn't directly > + * support this, it needs to fake coherency by shooting down any ptes > + * when transitioning away from the cpu domain. > */ > struct dma_buf_ops { > int (*attach)(struct dma_buf *, struct device *, > @@ -92,6 +96,8 @@ struct dma_buf_ops { > void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *); > void *(*kmap)(struct dma_buf *, unsigned long); > void (*kunmap)(struct dma_buf *, unsigned long, void *); > + > + int (*mmap)(struct dma_buf *, struct vm_area_struct *vma); > }; > > /** > @@ -167,6 +173,9 @@ void *dma_buf_kmap_atomic(struct dma_buf *, unsigned > long); > void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *); > void *dma_buf_kmap(struct dma_buf *, unsigned long); > void dma_buf_kunmap(struct dma_buf *, unsigned long, void *); > + > +int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, > + unsigned long); > #else > > static inline struct dma_buf_attachment *dma_buf_attach(struct dma_buf > *dmabuf, > @@ -248,6 +257,13 @@ static inline void dma_buf_kunmap(struct dma_buf *dmabuf, > unsigned long pnum, void *vaddr) > { > } > + > +static inline int dma_buf_mmap(struct dma_buf *dmabuf, > + struct vm_ar
[Bug 30654] [855] flickers when vblank_mode is enabled
https://bugs.freedesktop.org/show_bug.cgi?id=30654 Chris Wilson changed: What|Removed |Added Status|REOPENED|RESOLVED Resolution||FIXED --- Comment #17 from Chris Wilson 2012-04-24 02:11:18 PDT --- I believe this will be fixed with: commit 8fa2a569d3fb6ea78b83c6062b2f3aec528cc9e5 Author: Chris Wilson Date: Sun Apr 22 21:13:57 2012 +0100 drm/i915: i8xx interrupt handler gen2 hardware has some significant differences from the other interrupt routines that were glossed over and then forgotten about in the transition to KMS. Such as - 16bit IIR - PendingFlip status bit This patch reintroduces a handler specifically for gen2 for the purpose of handling pageflips correctly, simplifying code in the process. v2: Also fixup ring get/put irq to only access 16bit registers (Daniel) Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=24202 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=41793 Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
[PATCH 6/6] gma500: Set the mapping mask
From: Alan Cox Some boards such as the Intel D2700MUD allow you to have over 4GB of RAM. The GTT on the PVR based devices is 32bit however. Hugh Dickins points out that we should therefore be setting the mapping gfp mask. This is not the whole fix for the problem. Some further shmem patches will be needed to deal with the corner cases. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/gem.c |2 ++ drivers/gpu/drm/gma500/gtt.c |4 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 9fbb868..fc7d144 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -124,6 +124,8 @@ static int psb_gem_create(struct drm_file *file, dev_err(dev->dev, "GEM init failed for %lld\n", size); return -ENOMEM; } + /* Limit the object to 32bit mappings */ + mapping_set_gfp_mask(r->gem.filp->f_mapping, GFP_KERNEL | __GFP_DMA32); /* Give the object a handle so we can carry it more easily */ ret = drm_gem_handle_create(file, &r->gem, &handle); if (ret) { diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index db2e823..54e5c9e 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -39,6 +39,10 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) { uint32_t mask = PSB_PTE_VALID; + /* Ensure we explode rather than put an invalid low mapping of + a high mapping page into the gtt */ + BUG_ON(pfn & ~(0x >> PAGE_SHIFT)); + if (type & PSB_MMU_CACHED_MEMORY) mask |= PSB_PTE_CACHED; if (type & PSB_MMU_RO_MEMORY) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/6] gma500: Add ops for hotplug support.
From: Alan Cox This provides the needed callback hooks to add hotplug display support to the GMA36x0 devices. [The actual enabling device part will follow once I've figured out why it breaks suspend/resume on some netbooks] Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/psb_drv.h |3 +++ drivers/gpu/drm/gma500/psb_irq.c | 36 +++- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 6235499..ab483c3 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -130,6 +130,7 @@ enum { #define _PSB_VSYNC_PIPEA_FLAG(1<<7) #define _MDFLD_MIPIA_FLAG(1<<16) #define _MDFLD_MIPIC_FLAG(1<<17) +#define _PSB_IRQ_DISP_HOTSYNC(1<<17) #define _PSB_IRQ_SGX_FLAG(1<<18) #define _PSB_IRQ_MSVDX_FLAG (1<<19) #define _LNC_IRQ_TOPAZ_FLAG (1<<20) @@ -703,6 +704,8 @@ struct psb_ops { /* Display management hooks */ int (*output_init)(struct drm_device *dev); + int (*hotplug)(struct drm_device *dev); + void (*hotplug_enable)(struct drm_device *dev, bool on); /* Power management hooks */ void (*init_pm)(struct drm_device *dev); int (*save_regs)(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 1869586..4f31312 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -199,11 +199,9 @@ static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) { - struct drm_device *dev = (struct drm_device *) arg; - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; - - uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; + struct drm_device *dev = arg; + struct drm_psb_private *dev_priv = dev->dev_private; + uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0; int handled = 0; spin_lock(&dev_priv->irqmask_lock); @@ -220,6 +218,8 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) if (vdc_stat & _PSB_IRQ_SGX_FLAG) sgx_int = 1; + if (vdc_stat & _PSB_IRQ_DISP_HOTSYNC) + hotplug_int = 1; vdc_stat &= dev_priv->vdc_irq_mask; spin_unlock(&dev_priv->irqmask_lock); @@ -241,6 +241,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) handled = 1; } + /* Note: this bit has other meanings on some devices, so we will + need to address that later if it ever matters */ + if (hotplug_int && dev_priv->ops->hotplug) { + handled = dev_priv->ops->hotplug(dev); + REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT)); + } + PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); (void) PSB_RVDC32(PSB_INT_IDENTITY_R); DRM_READMEMORYBARRIER(); @@ -273,6 +280,10 @@ void psb_irq_preinstall(struct drm_device *dev) dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; */ + /* Revisit this area - want per device masks ? */ + if (dev_priv->ops->hotplug) + dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC; + /* This register is safe even if display island is off */ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); @@ -305,18 +316,25 @@ int psb_irq_postinstall(struct drm_device *dev) else psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + if (dev_priv->ops->hotplug_enable) + dev_priv->ops->hotplug_enable(dev, true); + spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); return 0; } void psb_irq_uninstall(struct drm_device *dev) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); + if (dev_priv->ops->hotplug_enable) { + dev_priv->ops->hotplug_enable(dev, false); + dev_priv->vdc_irq_mask &= ~_PSB_IRQ_DISP_HOTSYNC; + } + PSB_WVDC32(0x, PSB_HWSTAM); if (dev->vblank_enabled[0]) @@ -328,9 +346,9 @@ void psb_irq_uninstall(struct drm_device *dev) if (dev->vblank_enabled[2]) psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | + dev_priv->vdc_irq_mask &= ~(_PSB_IRQ_SGX_FLAG | _PSB_IRQ_MSVDX_FLAG | - _LNC_IRQ_TOPAZ_FLAG; + _LNC_IRQ_TOPAZ_FLAG); /* These two registers are safe even if display island is off */ PSB_WVDC32(~dev_priv->vdc_irq_mask, PS
[PATCH 4/6] gma500: implement backlight functionality for Cedartrail devices
From: Alan Cox Basically a straight cut/paste from the reference driver code then cleaned up a spot. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_device.c | 113 --- 1 files changed, 51 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 5cc06a8..292bcec 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -57,8 +57,7 @@ static int cdv_output_init(struct drm_device *dev) cdv_intel_crt_init(dev, &dev_priv->mode_dev); cdv_intel_lvds_init(dev, &dev_priv->mode_dev); - /* These bits indicate HDMI not SDVO on CDV, but we don't yet support - the HDMI interface */ + /* These bits indicate HDMI not SDVO on CDV */ if (REG_READ(SDVOB) & SDVO_DETECTED) cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); if (REG_READ(SDVOC) & SDVO_DETECTED) @@ -69,76 +68,71 @@ static int cdv_output_init(struct drm_device *dev) #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE /* - * Poulsbo Backlight Interfaces + * Cedartrail Backlght Interfaces */ -#define BLC_PWM_PRECISION_FACTOR 100 /* 1000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 100 - -#define PSB_BLC_PWM_PRECISION_FACTOR10 -#define PSB_BLC_MAX_PWM_REG_FREQ0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT(16) - -static int cdv_brightness; static struct backlight_device *cdv_backlight_device; -static int cdv_get_brightness(struct backlight_device *bd) +static int cdv_backlight_combination_mode(struct drm_device *dev) { - /* return locally cached var instead of HW read (due to DPST etc.) */ - /* FIXME: ideally return actual value in case firmware fiddled with - it */ - return cdv_brightness; + return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE; } - -static int cdv_backlight_setup(struct drm_device *dev) +static int cdv_get_brightness(struct backlight_device *bd) { - struct drm_psb_private *dev_priv = dev->dev_private; - unsigned long core_clock; - /* u32 bl_max_freq; */ - /* unsigned long value; */ - u16 bl_max_freq; - uint32_t value; - uint32_t blc_pwm_precision_factor; - - /* get bl_max_freq and pol from dev_priv*/ - if (!dev_priv->lvds_bl) { - dev_err(dev->dev, "Has no valid LVDS backlight info\n"); - return -ENOENT; - } - bl_max_freq = dev_priv->lvds_bl->freq; - blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; + struct drm_device *dev = bl_get_data(bd); + u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - core_clock = dev_priv->core_freq; + if (cdv_backlight_combination_mode(dev)) { + u8 lbpc; - value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; - value *= blc_pwm_precision_factor; - value /= bl_max_freq; - value /= blc_pwm_precision_factor; + val &= ~1; + pci_read_config_byte(dev->pdev, 0xF4, &lbpc); + val *= lbpc; + } + return val; +} - if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || -value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) - return -ERANGE; - else { - /* FIXME */ +static u32 cdv_get_max_backlight(struct drm_device *dev) +{ + u32 max = REG_READ(BLC_PWM_CTL); + + if (max == 0) { + DRM_DEBUG_KMS("LVDS Panel PWM value is 0!\n"); + /* i915 does this, I believe which means that we should not +* smash PWM control as firmware will take control of it. */ + return 1; } - return 0; + + max >>= 16; + if (cdv_backlight_combination_mode(dev)) + max *= 0xff; + return max; } static int cdv_set_brightness(struct backlight_device *bd) { + struct drm_device *dev = bl_get_data(bd); int level = bd->props.brightness; + u32 blc_pwm_ctl; /* Percentage 1-100% being valid */ if (level < 1) level = 1; - /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ - cdv_brightness = level; + if (cdv_backlight_combination_mode(dev)) { + u32 max = cdv_get_max_backlight(dev); + u8 lbpc; + + lbpc = level * 0xfe / max + 1; + level /= lbpc; + + pci_write_config_byte(dev->pdev, 0xF4, lbpc); + } + + blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; + REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl | + (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); return 0; } @@ -150,7 +144,6 @@ static const struct backlight_ops cdv_ops = { static int cdv_backlight_init(struct d
[PATCH 3/6] cdv: continue synching up with updated reference code
From: Alan Cox In particular clean up the errata handling and correct the crtc masks. We do this a bit differently using our device abstraction for neatness. This doesn't address the ACPI opregion and hotplug plumbing, nor the IRQ related changes that will need. It touches on backlight init but the full backlight support is not in this change set. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_device.c| 20 + drivers/gpu/drm/gma500/cdv_intel_crt.c | 20 +++-- drivers/gpu/drm/gma500/cdv_intel_display.c | 61 drivers/gpu/drm/gma500/cdv_intel_lvds.c| 17 drivers/gpu/drm/gma500/framebuffer.c | 13 ++ drivers/gpu/drm/gma500/mdfld_device.c |2 + drivers/gpu/drm/gma500/oaktrail_device.c |2 + drivers/gpu/drm/gma500/psb_device.c|2 + drivers/gpu/drm/gma500/psb_drv.h |4 ++ drivers/gpu/drm/gma500/psb_intel_reg.h |4 ++ 10 files changed, 89 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index a54cc73..5cc06a8 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -49,6 +49,9 @@ static void cdv_disable_vga(struct drm_device *dev) static int cdv_output_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; + + drm_mode_create_scaling_mode_property(dev); + cdv_disable_vga(dev); cdv_intel_crt_init(dev, &dev_priv->mode_dev); @@ -238,6 +241,18 @@ static void cdv_init_pm(struct drm_device *dev) dev_err(dev->dev, "GPU: power management timed out.\n"); } +static void cdv_errata(struct drm_device *dev) +{ + /* Disable bonus launch. +* CPU and GPU competes for memory and display misses updates and flickers. +* Worst with dual core, dual displays. +* +* Fixes were done to Win 7 gfx driver to disable a feature called Bonus +* Launch to work around the issue, by degrading performance. +*/ +CDV_MSG_WRITE32(3, 0x30, 0x08027108); +} + /** * cdv_save_display_registers - save registers lost on suspend * @dev: our DRM device @@ -355,7 +370,7 @@ static int cdv_restore_display_registers(struct drm_device *dev) REG_WRITE(PSB_INT_MASK_R, regs->cdv.saveIMR); /* Fix arbitration bug */ - CDV_MSG_WRITE32(3, 0x30, 0x08027108); + cdv_errata(dev); drm_mode_config_reset(dev); @@ -464,8 +479,11 @@ const struct psb_ops cdv_chip_ops = { .accel_2d = 0, .pipes = 2, .crtcs = 2, + .hdmi_mask = (1 << 0) | (1 << 1), + .lvds_mask = (1 << 1), .sgx_offset = MRST_SGX_OFFSET, .chip_setup = cdv_chip_setup, + .errata = cdv_errata, .crtc_helper = &cdv_intel_helper_funcs, .crtc_funcs = &cdv_intel_crtc_funcs, diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 1a82843..1874220 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -78,9 +78,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, if (mode->clock > 355000) return MODE_CLOCK_HIGH; - if (mode->hdisplay > 1680 || mode->vdisplay > 1050) - return MODE_PANEL; - return MODE_OK; } @@ -148,13 +145,7 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, struct drm_device *dev = connector->dev; u32 hotplug_en; int i, tries = 0, ret = false; - u32 adpa_orig; - - /* disable the DAC when doing the hotplug detection */ - - adpa_orig = REG_READ(ADPA); - - REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE)); + u32 orig; /* * On a CDV thep, CRT detect sequence need to be done twice @@ -162,7 +153,7 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, */ tries = 2; - hotplug_en = REG_READ(PORT_HOTPLUG_EN); + orig = hotplug_en = REG_READ(PORT_HOTPLUG_EN); hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK); hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; @@ -187,8 +178,11 @@ static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, CRT_HOTPLUG_MONITOR_NONE) ret = true; - /* Restore the saved ADPA */ - REG_WRITE(ADPA, adpa_orig); +/* clear the interrupt we just generated, if any */ + REG_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); + + /* and put the bits back */ + REG_WRITE(PORT_HOTPLUG_EN, orig); return ret; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 07b37f5..2fab778 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -226,13 +226,13 @@
[PATCH 2/6] gma500: Clean up weirdness in the cdv mode test code
From: Alan Cox Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_crt.c |4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 1de27c7..1a82843 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -67,7 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) static int cdv_intel_crt_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - int max_clock = 0; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -76,8 +75,7 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, return MODE_CLOCK_LOW; /* The max clock for CDV is 355 instead of 400 */ - max_clock = 355000; - if (mode->clock > max_clock) + if (mode->clock > 355000) return MODE_CLOCK_HIGH; if (mode->hdisplay > 1680 || mode->vdisplay > 1050) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/6] gma500: support 1080p
From: Alan Cox The problem in console mode is lack of linear memory. We can solve that by dropping to 16bpp. The mode setting X server will allocate its own GEM framebuffer in 32bpp and all will be well. We could just do 16bpp anyway but that would be a regression on the lower modes as many distributions don't yet ship the generic mode setting KMS drivers. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_crt.c |6 -- drivers/gpu/drm/gma500/cdv_intel_hdmi.c |7 --- drivers/gpu/drm/gma500/framebuffer.c| 16 drivers/gpu/drm/gma500/oaktrail_hdmi.c |6 -- drivers/gpu/drm/gma500/psb_intel_sdvo.c |6 -- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index a71a6cd..1de27c7 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -67,7 +67,6 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) static int cdv_intel_crt_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct drm_psb_private *dev_priv = connector->dev->dev_private; int max_clock = 0; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; @@ -84,11 +83,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector, if (mode->hdisplay > 1680 || mode->vdisplay > 1050) return MODE_PANEL; - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - return MODE_OK; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 8d52695..88b59d4 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -242,8 +242,6 @@ static int cdv_hdmi_get_modes(struct drm_connector *connector) static int cdv_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct drm_psb_private *dev_priv = connector->dev->dev_private; - if (mode->clock > 165000) return MODE_CLOCK_HIGH; if (mode->clock < 2) @@ -257,11 +255,6 @@ static int cdv_hdmi_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_INTERLACE) return MODE_NO_INTERLACE; - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((ALIGN(mode->hdisplay * 4, 64) * mode->vdisplay) > - dev_priv->vram_stolen_size) - return MODE_MEM; - return MODE_OK; } diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 8ea202f..c2cf6bf 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -543,9 +543,25 @@ static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; + struct drm_device *dev = psb_fbdev->psb_fb_helper.dev; + struct drm_psb_private *dev_priv = dev->dev_private; int new_fb = 0; + int bytespp; int ret; + bytespp = sizes->surface_bpp / 8; + if (bytespp == 3) /* no 24bit packed */ + bytespp = 4; + + /* If the mode will not fit in 32bit then switch to 16bit to get + a console on full resolution. The X mode setting server will + allocate its own 32bit GEM framebuffer */ + if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height > + dev_priv->vram_stolen_size) { +sizes->surface_bpp = 16; +sizes->surface_depth = 16; +} + if (!helper->fb) { ret = psbfb_create(psb_fbdev, sizes); if (ret) diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index f8b367b..2595660 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -179,7 +179,6 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct drm_psb_private *dev_priv = connector->dev->dev_private; if (mode->clock > 165000) return MODE_CLOCK_HIGH; if (mode->clock < 2) @@ -188,11 +187,6 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; - /* We assume worst case scenario of 32 bpp here, since we don't know */ - if ((AL
[PATCH 3/3] gma500: don't register the ACPI video bus
From: Alan Cox We are not yet ready for this and it makes a mess on some devices. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/psb_drv.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index d5a6eab..45bd0c7 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -350,7 +350,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) PSB_WSGX32(0x3000, PSB_CR_BIF_3D_REQ_BASE); /* igd_opregion_init(&dev_priv->opregion_dev); */ - acpi_video_register(); +/* acpi_video_register(); */ if (dev_priv->lid_state) psb_lid_timer_init(dev_priv); ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/3] acpi_video: Intel video is not always i915
From: Alan Cox Handle the GMA500/600/36x0 cases. Also stop it poking at random registers on the i740 cards that may be out there still. This should also allow the legacy gma500 stub driver to go away as the ACPI video layer will now do the right thing rather than assume all the world is Gen graphics and need the gma500 stub as a workaround. Signed-off-by: Alan Cox --- drivers/acpi/video.c | 54 +++--- 1 files changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 66e8f73..b2ae7aa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1743,25 +1743,63 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } +static int __init is_gma_pvr(struct pci_dev *dev) +{ + /* Medfield */ + if ((dev->device & 0xFFF8) == 0x0130) + return 1; + /* GMA36x0 */ + if ((dev->device & 0xFFF8) == 0x0be0) + return 1; + /* GMA600 */ + if ((dev->device & 0xFFF8) == 0x4100) + return 1; + /* GMA500 */ + if ((dev->device & 0xFFFE) == 0x8108) + return 1; + /* E620 */ + if (dev->device == 0x4108) + return 1; + return 0; +} + +static int __init is_i740(struct pci_dev *dev) +{ + if (dev->device == 0x00D1) + return 1; + if (dev->device == 0x7000) + return 1; + return 0; +} + static int __init intel_opregion_present(void) { - int i915 = 0; -#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) + int opregion = 0; struct pci_dev *dev = NULL; - u32 address; for_each_pci_dev(dev) { if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) continue; if (dev->vendor != PCI_VENDOR_ID_INTEL) continue; - pci_read_config_dword(dev, 0xfc, &address); - if (!address) + /* We don't want to poke around undefined i740 registers */ + if (is_i740(dev)) continue; - i915 = 1; - } +#if defined(CONFIG_DRM_GMA500) || defined(CONFIG_DRM_GMA500_MODULE) + if (is_gma_pvr(dev)) + opregion = 1; #endif - return i915; +#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) + if (!is_gma_pvr(dev)) { + u32 address; + pci_read_config_dword(dev, 0xfc, &address); + if (!address) + continue; + opregion = 1; + } +#endif + } + return opregion; } int acpi_video_register(void) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/3] acpi_video: fix leaking PCI references
From: Alan Cox Otherwise we keep a bogus pci reference to the GPU Signed-off-by: Alan Cox --- drivers/acpi/video.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 9577b6f..66e8f73 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1745,6 +1745,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) static int __init intel_opregion_present(void) { + int i915 = 0; #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) struct pci_dev *dev = NULL; u32 address; @@ -1757,10 +1758,10 @@ static int __init intel_opregion_present(void) pci_read_config_dword(dev, 0xfc, &address); if (!address) continue; - return 1; + i915 = 1; } #endif - return 0; + return i915; } int acpi_video_register(void) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 6/6] gma500: panel presence check
From: Alan Cox Introduce a panel presence check for Cedartrail. Non netbook devices don't necessarily have a panel attached. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 57 +++ 1 files changed, 57 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 8359c1a..c87b179 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -556,6 +556,56 @@ const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { .destroy = cdv_intel_lvds_enc_destroy, }; +/* + * Enumerate the child dev array parsed from VBT to check whether + * the LVDS is present. + * If it is present, return 1. + * If it is not present, return false. + * If no child dev is parsed from VBT, it assumes that the LVDS is present. + */ +static bool lvds_is_present_in_vbt(struct drm_device *dev, + u8 *i2c_pin) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + int i; + + if (!dev_priv->child_dev_num) + return true; + + for (i = 0; i < dev_priv->child_dev_num; i++) { + struct child_device_config *child = dev_priv->child_dev + i; + + /* If the device type is not LFP, continue. +* We have to check both the new identifiers as well as the +* old for compatibility with some BIOSes. +*/ + if (child->device_type != DEVICE_TYPE_INT_LFP && + child->device_type != DEVICE_TYPE_LFP) + continue; + + if (child->i2c_pin) + *i2c_pin = child->i2c_pin; + + /* However, we cannot trust the BIOS writers to populate +* the VBT correctly. Since LVDS requires additional +* information from AIM blocks, a non-zero addin offset is +* a good indicator that the LVDS is actually present. +*/ + if (child->addin_offset) + return true; + + /* But even then some BIOS writers perform some black magic +* and instantiate the device without reference to any +* additional data. Trust that if the VBT was written into +* the OpRegion then they have validated the LVDS's existence. +*/ + if (dev_priv->opregion.vbt) + return true; + } + + return false; +} + /** * cdv_intel_lvds_init - setup LVDS connectors on this device * @dev: drm device @@ -576,6 +626,13 @@ void cdv_intel_lvds_init(struct drm_device *dev, struct drm_psb_private *dev_priv = dev->dev_private; u32 lvds; int pipe; + u8 pin; + + pin = GMBUS_PORT_PANEL; + if (!lvds_is_present_in_vbt(dev, &pin)) { + DRM_DEBUG_KMS("LVDS is not present in VBT\n"); + return; + } psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 5/6] gma500: intel_bios updates
From: Alan Cox Pull in various i915 bits that we will need to begin tackling the LVDS detect and ACPI events. We try and drift towards the i915 version of the code with the long term goal that at least some of it can one day be unified. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/intel_bios.c | 232 --- drivers/gpu/drm/gma500/intel_bios.h | 122 +++- drivers/gpu/drm/gma500/intel_opregion.c | 117 ++-- drivers/gpu/drm/gma500/psb_drv.h|4 + 4 files changed, 438 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 51ea6df..479e449 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -26,6 +26,8 @@ #include "psb_intel_reg.h" #include "intel_bios.h" +#defineSLAVE_ADDR1 0x70 +#defineSLAVE_ADDR2 0x72 static void *find_section(struct bdb_header *bdb, int section_id) { @@ -52,6 +54,16 @@ static void *find_section(struct bdb_header *bdb, int section_id) return NULL; } +static u16 +get_blocksize(void *p) +{ + u16 *block_ptr, block_size; + + block_ptr = (u16 *)((char *)p - 2); + block_size = *block_ptr; + return block_size; +} + static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, struct lvds_dvo_timing *dvo_timing) { @@ -75,6 +87,16 @@ static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; + if (dvo_timing->hsync_positive) + panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC; + else + panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC; + + if (dvo_timing->vsync_positive) + panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC; + else + panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; + /* Some VBTs have bogus h/vtotal values */ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; @@ -218,6 +240,97 @@ static void parse_general_features(struct drm_psb_private *dev_priv, } static void +parse_sdvo_device_mapping(struct drm_psb_private *dev_priv, + struct bdb_header *bdb) +{ + struct sdvo_device_mapping *p_mapping; + struct bdb_general_definitions *p_defs; + struct child_device_config *p_child; + int i, child_device_num, count; + u16 block_size; + + p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); + if (!p_defs) { + DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); + return; + } + /* judge whether the size of child device meets the requirements. +* If the child device size obtained from general definition block +* is different with sizeof(struct child_device_config), skip the +* parsing of sdvo device info +*/ + if (p_defs->child_dev_size != sizeof(*p_child)) { + /* different child dev size . Ignore it */ + DRM_DEBUG_KMS("different child size is found. Invalid.\n"); + return; + } + /* get the block size of general definitions */ + block_size = get_blocksize(p_defs); + /* get the number of child device */ + child_device_num = (block_size - sizeof(*p_defs)) / + sizeof(*p_child); + count = 0; + for (i = 0; i < child_device_num; i++) { + p_child = &(p_defs->devices[i]); + if (!p_child->device_type) { + /* skip the device block if device type is invalid */ + continue; + } + if (p_child->slave_addr != SLAVE_ADDR1 && + p_child->slave_addr != SLAVE_ADDR2) { + /* +* If the slave address is neither 0x70 nor 0x72, +* it is not a SDVO device. Skip it. +*/ + continue; + } + if (p_child->dvo_port != DEVICE_PORT_DVOB && + p_child->dvo_port != DEVICE_PORT_DVOC) { + /* skip the incorrect SDVO port */ + DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n"); + continue; + } + DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on" + " %s port\n", + p_child->slave_addr, + (p_child->dvo_port == DEVICE_PORT_DVOB) ? + "SDVOB" : "SDVOC"); + p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
[PATCH 4/6] gma500: cache GEM framebuffer pages wc not uc
From: Alan Cox Fixes the case where the modesetting driver is slower than /dev/fb. Signed-off-by: Alan Cox Cc: sta...@kernel.org --- drivers/gpu/drm/gma500/gtt.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index c6465b4..db2e823 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -93,7 +93,7 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) pages = r->pages; /* Make sure changes are visible to the GPU */ - set_pages_array_uc(pages, r->npage); + set_pages_array_wc(pages, r->npage); /* Write our page entries into the GTT itself */ for (i = r->roll; i < r->npage; i++) { ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/6] gma500: Update the Cedarview clock handling
From: Alan Cox --- drivers/gpu/drm/gma500/cdv_intel_display.c | 331 +++- drivers/gpu/drm/gma500/psb_intel_drv.h |3 drivers/gpu/drm/gma500/psb_intel_reg.h | 25 ++ 3 files changed, 294 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index be84559..07b37f5 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -216,7 +216,7 @@ static void cdv_sb_reset(struct drm_device *dev) */ static int cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, - struct cdv_intel_clock_t *clock) + struct cdv_intel_clock_t *clock, bool is_lvds) { struct psb_intel_crtc *psb_crtc = to_psb_intel_crtc(crtc); @@ -224,6 +224,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, u32 m, n_vco, p; int ret = 0; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; + int ref_sfr = (pipe == 0) ? SB_REF_DPLLA : SB_REF_DPLLB; u32 ref_value; cdv_sb_reset(dev); @@ -241,6 +242,35 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, /* We don't know what the other fields of these regs are, so * leave them in place. */ + /* +* The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk +* for the pipe A/B. Display spec 1.06 has wrong definition. +* Correct definition is like below: +* +* refclka mean use clock from same PLL +* +* if DPLLA sets 01 and DPLLB sets 01, they use clock from their pll +* +* if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA +* +*/ + ret = cdv_sb_read(dev, ref_sfr, &ref_value); + if (ret) + return ret; + ref_value &= ~(REF_CLK_MASK); + + /* use DPLL_A for pipeB on CRT/HDMI */ + if (pipe == 1 && !is_lvds) { + DRM_DEBUG_KMS("use DPLLA for pipe B\n"); + ref_value |= REF_CLK_DPLLA; + } else { + DRM_DEBUG_KMS("use their DPLL for pipe A/B\n"); + ref_value |= REF_CLK_DPLL; + } + ret = cdv_sb_write(dev, ref_sfr, ref_value); + if (ret) + return ret; + ret = cdv_sb_read(dev, SB_M(pipe), &m); if (ret) return ret; @@ -308,7 +338,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, return ret; /* always Program the Lane Register for the Pipe A*/ - if (pipe == 0) { +/* if (pipe == 0) */ { /* Program the Lane0/1 for HDMI B */ u32 lane_reg, lane_value; @@ -553,6 +583,200 @@ psb_intel_pipe_set_base_exit: return ret; } +#defineFIFO_PIPEA (1 << 0) +#defineFIFO_PIPEB (1 << 1) + +static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe) +{ + struct drm_crtc *crtc; + struct drm_psb_private *dev_priv = dev->dev_private; + struct psb_intel_crtc *psb_intel_crtc = NULL; + + crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + psb_intel_crtc = to_psb_intel_crtc(crtc); + + if (crtc->fb == NULL || !psb_intel_crtc->active) + return false; + return true; +} + +static bool cdv_intel_single_pipe_active (struct drm_device *dev) +{ + uint32_t pipe_enabled = 0; + + if (cdv_intel_pipe_enabled(dev, 0)) + pipe_enabled |= FIFO_PIPEA; + + if (cdv_intel_pipe_enabled(dev, 1)) + pipe_enabled |= FIFO_PIPEB; + + + DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled); + + if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB) + return true; + else + return false; +} + +static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + if (psb_intel_crtc->pipe != 1) + return false; + + list_for_each_entry(connector, &mode_config->connector_list, head) { + struct psb_intel_encoder *psb_intel_encoder = + psb_intel_attached_encoder(connector); + + if (!connector->encoder + || connector->encoder->crtc != crtc) + continue; + + if (psb_intel_encoder->type == INTEL_OUTPUT_LVDS) + return true; + } + + return false; +} + +static void cdv_intel_disable_self_refresh (struct drm_device *dev) +{ + if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) { + + /* Disable self-refresh before adjust WM */ + RE
[PATCH 2/6] gma500: read the PLL bits
From: Alan Cox We need to pull more stuff from the VBT in order to configure the clocking correctly in all cases. Add the relevant bits from the other CDV driver work. Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/intel_bios.c | 18 drivers/gpu/drm/gma500/intel_bios.h | 39 +++ drivers/gpu/drm/gma500/psb_drv.h|2 ++ 3 files changed, 59 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index d4d0c5b..51ea6df 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -217,6 +217,23 @@ static void parse_general_features(struct drm_psb_private *dev_priv, } } +static void +parse_driver_features(struct drm_psb_private *dev_priv, + struct bdb_header *bdb) +{ + struct bdb_driver_features *driver; + + driver = find_section(bdb, BDB_DRIVER_FEATURES); + if (!driver) + return; + + /* This bit means to use 96Mhz for DPLL_A or not */ + if (driver->primary_lfp_id) + dev_priv->dplla_96mhz = true; + else + dev_priv->dplla_96mhz = false; +} + /** * psb_intel_init_bios - initialize VBIOS settings & find VBT * @dev: DRM device @@ -263,6 +280,7 @@ bool psb_intel_init_bios(struct drm_device *dev) /* Grab useful general definitions */ parse_general_features(dev_priv, bdb); + parse_driver_features(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_backlight_data(dev_priv, bdb); diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h index 70f1bf0..c67979e 100644 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ b/drivers/gpu/drm/gma500/intel_bios.h @@ -302,6 +302,45 @@ struct bdb_sdvo_lvds_options { u8 panel_misc_bits_4; } __attribute__((packed)); +struct bdb_driver_features { + u8 boot_dev_algorithm:1; + u8 block_display_switch:1; + u8 allow_display_switch:1; + u8 hotplug_dvo:1; + u8 dual_view_zoom:1; + u8 int15h_hook:1; + u8 sprite_in_clone:1; + u8 primary_lfp_id:1; + + u16 boot_mode_x; + u16 boot_mode_y; + u8 boot_mode_bpp; + u8 boot_mode_refresh; + + u16 enable_lfp_primary:1; + u16 selective_mode_pruning:1; + u16 dual_frequency:1; + u16 render_clock_freq:1; /* 0: high freq; 1: low freq */ + u16 nt_clone_support:1; + u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */ + u16 sprite_display_assign:1; /* 0: secondary; 1: primary */ + u16 cui_aspect_scaling:1; + u16 preserve_aspect_ratio:1; + u16 sdvo_device_power_down:1; + u16 crt_hotplug:1; + u16 lvds_config:2; + u16 tv_hotplug:1; + u16 hdmi_config:2; + + u8 static_display:1; + u8 reserved2:7; + u16 legacy_crt_max_x; + u16 legacy_crt_max_y; + u8 legacy_crt_max_refresh; + + u8 hdmi_termination; + u8 custom_vbt_version; +} __attribute__((packed)); extern bool psb_intel_init_bios(struct drm_device *dev); extern void psb_intel_destroy_bios(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 40ce2c9..4c50969 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -669,6 +669,8 @@ struct drm_psb_private { u32 dspcntr[3]; int mdfld_panel_id; + + bool dplla_96mhz; /* DPLL data from the VBT */ }; ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/6] gma500: Fix leak of uncached page
From: Alan Cox This was reported a long time ago (and I apologize to whoever it was that reported it as I've lost the original report). Signed-off-by: Alan Cox --- drivers/gpu/drm/gma500/psb_drv.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index c34adf9..d5a6eab 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -246,6 +246,7 @@ static int psb_driver_unload(struct drm_device *dev) } psb_gtt_takedown(dev); if (dev_priv->scratch_page) { + set_pages_wb(dev_priv->scratch_page, 1); __free_page(dev_priv->scratch_page); dev_priv->scratch_page = NULL; } ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 41668] Screen locks up at random points when using a 3D compositing wm (gnome-shell) on an rv515 (radeon mobility x1300)
https://bugs.freedesktop.org/show_bug.cgi?id=41668 --- Comment #26 from Michel D?nzer 2012-04-24 01:37:57 PDT --- Current kernels disable MSI by default for RV515. Does that resolve this report? -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
[Bug 43138] Radeon HD5450 fails to load cedar firmware ?
https://bugzilla.kernel.org/show_bug.cgi?id=43138 --- Comment #9 from Michel D?nzer 2012-04-24 08:24:23 --- (In reply to comment #7) > that leaves the pretty unlikely bug in the loader and/or some weird local > hardware problem - no idea how much different the cards in the cedar family > really are from each other? It's got nothing to do with the hardware. request_firmware() reports sizes of the files in question which do not match the sizes of the files on your system (which match the expected sizes). So something goes wrong between your filesystem and request_firmware(). The most likely explanation seeming a problem when copying the files into the initrd, or maybe /lib/udev/firmware.agent in the initrd doing something wrong or something like that. What does gunzip -c /boot/initrd.img-$(uname -r) | cpio -tv | grep CEDAR say? (In reply to comment #8) > Boot with "radeon.modeset=0 3" The '3' won't have any visible effect on a Debian system, you'd need 'single' for single user mode. > If it works it means debian initrd doesn't include the firmware. It does include something (otherwise the failure would be different), but possibly not the correct files. -- Configure bugmail: https://bugzilla.kernel.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are watching the assignee of the bug.
[Patch 3/3] edid override: make edid writable in sysfs
From: Thorsten Schoel Makes class/drm/[CONNECTOR]/edid writable for adding edid overrides. Signed-off-by: Thorsten Schoel --- diff -Nurp infra/drivers/gpu/drm/drm_sysfs.c sysfs/drivers/gpu/drm/drm_sysfs.c --- infra/drivers/gpu/drm/drm_sysfs.c 2012-01-12 20:42:45.0 +0100 +++ sysfs/drivers/gpu/drm/drm_sysfs.c 2012-01-25 22:13:08.0 +0100 @@ -21,6 +21,8 @@ #include "drm_sysfs.h" #include "drm_core.h" #include "drmP.h" +#include "drm_edid.h" +#include "drm_crtc.h" #define to_drm_minor(d) container_of(d, struct drm_minor, kdev) #define to_drm_connector(d) container_of(d, struct drm_connector, kdev) @@ -228,6 +230,44 @@ static ssize_t edid_show(struct file *fi return count; } +static ssize_t edid_override(struct file *filp, struct kobject *kobj, +struct bin_attribute *attr, char *buf, loff_t off, +size_t count) +{ + struct device *connector_dev = container_of(kobj, struct device, kobj); + struct drm_connector *connector = to_drm_connector(connector_dev); + char *connector_name; + unsigned char *edid_new; + + connector_name = drm_get_connector_name(connector); + + if (!count) { + drm_edid_override_remove(connector_name); + return 0; + } + + /* Only support writing the whole EDID in one piece */ + if (off) + return 0; + + if (count < EDID_LENGTH) + return 0; + if (count != (buf[0x7e] + 1) * EDID_LENGTH) + return 0; + + edid_new = kmalloc(count, GFP_KERNEL); + if (!edid_new) + return 0; + + memcpy(edid_new, buf, count); + + if (drm_edid_override_set(connector_name, (struct edid *)edid_new) < 0) + count = 0; + + kfree(edid_new); + return count; +} + static ssize_t modes_show(struct device *device, struct device_attribute *attr, char *buf) @@ -341,9 +381,10 @@ static struct device_attribute connector static struct bin_attribute edid_attr = { .attr.name = "edid", - .attr.mode = 0444, + .attr.mode = 0644, .size = 0, .read = edid_show, + .write = edid_override, }; /** --- ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Patch 2/3] edid override: module parameter
From: Thorsten Schoel Allows for setting edid overrides through new parameter edid_override for module drm. Signed-off-by: Thorsten Schoel --- diff -Nurp infra/drivers/gpu/drm/drm_edid.c param/drivers/gpu/drm/drm_edid.c --- infra/drivers/gpu/drm/drm_edid.c2012-01-25 22:12:59.0 +0100 +++ param/drivers/gpu/drm/drm_edid.c2012-01-25 22:14:51.0 +0100 @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include "drmP.h" #include "drm_edid.h" @@ -232,11 +234,37 @@ struct drm_edid_override { struct list_head list; char *connector; + char *param; struct edid *edid; unsigned num_blocks; }; LIST_HEAD(drm_edid_override_list); + +static int drm_edid_override_ops__get(char *buffer, const struct kernel_param *kp); +static int drm_edid_override_ops__set(const char *val, const struct kernel_param *kp); +static void drm_edid_override_ops__free(void *arg); + + +struct kernel_param_ops drm_edid_override_ops = { + .get = drm_edid_override_ops__get, + .set = drm_edid_override_ops__set, + .free = drm_edid_override_ops__free +}; + +MODULE_PARM_DESC(edid_override, "Override the EDID data of a monitor. " + "This should be a comma separated list of entries of the format " + "[connector name]:[data]. data is either raw EDID data encoded in " + "hexadecimal format, or, if it cannot be parsed as such, the name " + "of a file containing the EDID data to be loaded through " + "request_firmware. Examples:\nVGA-1:syncmaster913n.edid\n" + "DVI-I-1:00…"); +module_param_cb(edid_override, + &drm_edid_override_ops, + &drm_edid_override_list, + 0600); + + /* * Free the memory associated with an EDID override. */ @@ -246,6 +273,7 @@ drm_edid_override_delete(struct drm_edid if (entry->edid) kfree(entry->edid); kfree(entry->connector); + /* param is generated from the same piece of memory through strsep */ kfree(entry); } @@ -270,7 +299,7 @@ drm_edid_override_remove(const char *con EXPORT_SYMBOL(drm_edid_override_remove); static int -drm_edid_override_do_set(char *connector, struct edid *edid, unsigned num_blocks) +drm_edid_override_do_set(char *connector, struct edid *edid, unsigned num_blocks, char *param) { struct drm_edid_override *entry = NULL; int found = 0; @@ -300,6 +329,7 @@ drm_edid_override_do_set(char *connector entry->connector = connector; entry->edid = edid; entry->num_blocks = num_blocks; + entry->param = param; if (!found) list_add_tail(&entry->list, &drm_edid_override_list); @@ -308,6 +338,25 @@ drm_edid_override_do_set(char *connector return 0; } +/* + * Helper function for setter of module parameter. + */ +static int +drm_edid_override_set_from_param(char *val) +{ + char *connector = NULL, *param = NULL; + + connector = strsep(&val, ":"); + param = strlen(val) ? val : NULL; + + if (param) + return drm_edid_override_do_set(connector, NULL, 0, param); + else + drm_edid_override_remove(connector); + + return 0; +} + /** * Add a new override for connector if none has been set yet or replace the * current one. @@ -336,10 +385,179 @@ drm_edid_override_set(const char *connec } memcpy(edid_dup, edid, edid_size); - return drm_edid_override_do_set(connector_dup, edid_dup, num_blocks); + return drm_edid_override_do_set(connector_dup, edid_dup, num_blocks, NULL); } EXPORT_SYMBOL(drm_edid_override_set); +/* + * Setter for module parameter. + */ +static int +drm_edid_override_ops__set(const char *val, const struct kernel_param *kp) +{ + const char *master = val; + char *substr = NULL; + int result = 0; + + do { + const char *new_master = strchr(master, ','); + int substr_len = 0; + + if (new_master) + substr_len = new_master - master; + else + substr_len = strlen(master); + + substr = kstrndup(master, substr_len, GFP_KERNEL); + if (!substr) + return -ENOMEM; + + result = drm_edid_override_set_from_param(substr); + if (result) + return result; + + master = new_master; + } while (master); + + return 0; +} + +/* moduleparam.h claims this is "4k" */ +#define OPT_GET__BUFFER_LENGTH 4096 +/* + * Getter for module parameter. Will produce a comma separated list of + * all connectors an override has been set for. + */ +static int +drm_edid_override_ops__get(char *buffer, const struct kernel_param *kp) +{ + struct drm_edid_override *entry = NULL; +
[Patch 0/3] Add ability to override a monitor's EDID information
Hello everybody, having a monitor provide wrong or invalid EDID information – or none at all – seems to be a problem quite a number of people are facing. A few of the non-KMS X-drivers provide individual mechanisms for overriding such an EDID with user provided data. To my knowledge at least the kernel currently falls short of providing such a mechanism. This set of patches attempts to provide one. It has a number of potential shortcoming to which I was not yet able to find any solution. These are: 1. It uses drm_get_connector_name to identify a connector. I am not entirely sure though if these names are guaranteed to be unique (the names used in /sys/class/drm seem to suggest they are not). Since they are good enough for the kernel's video parameter, though, I figured they should be good enough for the present purpose as well. 2. One of the patches introduces a new kernel parameter (edid_override). This parameter takes either the raw edid-data encoded as a hex-string or the name of a firmware file from which to load the data. I am a bit unhappy with both solutions since the first puts raw data on the command line and makes it rather long and the second… well edid-data is not exactly firmware in the strict sense. It may be firm, but it is probably not ware. 3. I thought about making the sysfs code more sophisticated so that individual bytes could be written at any position within the data. Yet, there seems to be no way to truncate a file in sysfs which would be important when changing the number of 128 byte blocks the data is made up of. In addition, I cannot see what good such a behaviour would be or how the obscure use probably is somewhere out there could justify the additional complexity. I therefore opted for the approach of only allowing writes of complete edid-blobs in one pass. The patches I submit were tested on an x64 with radeon graphics and on an x86 with i915. They were made for 3.4. drivers/gpu/drm/drm_edid.c | 399 +++- drivers/gpu/drm/drm_sysfs.c | 43 include/drm/drm_crtc.h |2 3 files changed, 435 insertions(+), 9 deletions(-) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Patch 1/3] edid override: infrastructure
From: Thorsten Schoel Provides infrastructure for overriding edid information of individual monitors. Signed-off-by: Thorsten Schoel --- diff -Nurp vanilla/drivers/gpu/drm/drm_edid.c infra/drivers/gpu/drm/drm_edid.c --- vanilla/drivers/gpu/drm/drm_edid.c 2012-01-25 22:29:25.0 +0100 +++ infra/drivers/gpu/drm/drm_edid.c2012-01-25 22:12:59.0 +0100 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include "drmP.h" #include "drm_edid.h" @@ -226,6 +228,158 @@ bool drm_edid_is_valid(struct edid *edid } EXPORT_SYMBOL(drm_edid_is_valid); +struct drm_edid_override { + struct list_head list; + + char *connector; + struct edid *edid; + unsigned num_blocks; +}; +LIST_HEAD(drm_edid_override_list); + +/* + * Free the memory associated with an EDID override. + */ +static void +drm_edid_override_delete(struct drm_edid_override *entry) +{ + if (entry->edid) + kfree(entry->edid); + kfree(entry->connector); + kfree(entry); +} + +/** + * Remove an existing override. + * + * \param connector : name of a drm_connector + */ +void +drm_edid_override_remove(const char *connector) +{ + struct drm_edid_override *entry = NULL; + + list_for_each_entry (entry, &drm_edid_override_list, list) { + if (strcmp(entry->connector, connector)) + continue; + list_del(&entry->list); + drm_edid_override_delete(entry); + break; + } +} +EXPORT_SYMBOL(drm_edid_override_remove); + +static int +drm_edid_override_do_set(char *connector, struct edid *edid, unsigned num_blocks) +{ + struct drm_edid_override *entry = NULL; + int found = 0; + + /* replace previous entry if present */ + list_for_each_entry (entry, &drm_edid_override_list, list) { + if (strcmp(connector, entry->connector)) + continue; + found = 1; + break; + } + + if (!found) { + entry = kmalloc(sizeof(struct drm_edid_override), GFP_KERNEL); + if (!entry) { + kfree(connector); + kfree(edid); + return -ENOMEM; + } + INIT_LIST_HEAD(&entry->list); + } else { + kfree(entry->connector); + if (entry->edid) + kfree(entry->edid); + } + + entry->connector = connector; + entry->edid = edid; + entry->num_blocks = num_blocks; + + if (!found) + list_add_tail(&entry->list, &drm_edid_override_list); + DRM_INFO("Set new EDID override for connector %s", connector); + + return 0; +} + +/** + * Add a new override for connector if none has been set yet or replace the + * current one. + * + * \param connector : name of a drm_connector as retrieved through drm_get_connector_name + * \param edid : binary EDID data + */ +int +drm_edid_override_set(const char *connector, const struct edid *edid) +{ + char *connector_dup = NULL; + struct edid *edid_dup = NULL; + int num_blocks = 0; + unsigned edid_size = 0; + + connector_dup = kstrdup(connector, GFP_KERNEL); + if (!connector_dup) + return -ENOMEM; + + num_blocks = edid->extensions + 1; + edid_size = num_blocks * EDID_LENGTH; + edid_dup = kmalloc(edid_size, GFP_KERNEL); + if (!edid_dup) { + kfree(connector_dup); + return -ENOMEM; + } + memcpy(edid_dup, edid, edid_size); + + return drm_edid_override_do_set(connector_dup, edid_dup, num_blocks); +} +EXPORT_SYMBOL(drm_edid_override_set); + +/** + * Get EDID information from overrides list if available. + * + * \param connector : DRM connector to get EDID for + * \return a newly allocated edid structure filled with the EDID data from the + *override or NULL if no override for @connector could be found. + */ +static struct edid * +drm_edid_override_get (struct drm_connector *connector) +{ + struct list_head *pos = NULL; + struct drm_edid_override *entry = NULL; + char *connector_name = NULL; + struct edid *result = NULL; + + connector_name = drm_get_connector_name(connector); + + list_for_each(pos, &drm_edid_override_list) { + entry = (struct drm_edid_override *) + list_entry(pos, struct drm_edid_override, list); + if(!strcmp(entry->connector, connector_name)) + break; + else + entry = NULL; + } + + if (!entry) + return NULL; + + if (!entry->edid) { + DRM_ERROR("EDID override without EDID data for connector %s", connector_name); + return NULL; + } + + i
Re: Linux 3.4-rc4
On Mon, Apr 23, 2012 at 09:03:45PM -0400, Nick Bowler wrote: > On 2012-04-22 22:45 -0400, Konrad Rzeszutek Wilk wrote: > > On Sun, Apr 22, 2012 at 08:05:54PM -0400, Nick Bowler wrote: > > > Following up on the above, the commit which introduces the panics during > > > boot is this one: > > > > > > commit 8e7e70522d760c4ccd4cd370ebfa0ba69e006c6e > > > Author: Jerome Glisse > > > Date: Wed Nov 9 17:15:26 2011 -0500 > > > > > > drm/ttm: isolate dma data from ttm_tt V4 > > > > I think > > > > dea7e0a ttm: fix agp since ttm tt rework > > > > fixed that. > > Yes, I just tested this commit and the one immediately before it. The > one before crashes in the usual way, and dea7e0a boots (with the VGA > output black as in the original report). So this fixed the crash. > > Now, returning to the original bisection, I marked that commit as "bad" > and dropped all the earlier "skip" markings. Git asks me to test commit > 2a44e4997c5f ("drm/nouveau/disp: introduce proper init/fini, separate > from create/destroy"). I cherry picked the aforementioned ttm fix: > > git cherry-pick -n dea7e0a > > which succeeded. Howevew, the resulting kernel still crashes early, > although now in a different way. I just can't win :( Perhaps there is a better way. You could do this: git log --oneline -r v3.2..v3.3 drivers/gpu/drm/nouveau to get an idea of the set of patches that went in. And use that, so git bisect start -- drivers/gpu/drm/nouveau [this should only do the bisection on those patches] git bisect good v3.2 git bisect bad v3.3 And keep in mind the dea7e0a might need to be stuck on some of these. This _should_ limit the bisection to just the nouveau changes, I hope. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 49083] Crashing when open gnome-control-center 3.4.1
https://bugs.freedesktop.org/show_bug.cgi?id=49083 Michel D?nzer changed: What|Removed |Added Attachment #60490|text/x-log |text/plain mime type|| -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
Re: [PATCH v2] scatterlist: add sg_alloc_table_from_pages function
On Tue, Apr 24, 2012 at 02:58:56PM +0200, Tomasz Stanislawski wrote: > This patch adds a new constructor for an sg table. The table is constructed > from an array of struct pages. All contiguous chunks of the pages are merged > into a single sg nodes. A user may provide an offset and a size of a buffer if > the buffer is not page-aligned. > > The function is dedicated for DMABUF exporters which often perform conversion > from an page array to a scatterlist. Moreover the scatterlist should be > squashed in order to save memory and to speed-up the process of DMA mapping > using dma_map_sg. > > The code is based on the patch 'v4l: vb2-dma-contig: add support for > scatterlist in userptr mode' and hints from Laurent Pinchart. > > Signed-off-by: Tomasz Stanislawski > Signed-off-by: Kyungmin Park I like this and we could replace the drm helper function in drm prime with this one. One comment below. -Daniel > --- > include/linux/scatterlist.h |4 +++ > lib/scatterlist.c | 63 > +++ > 2 files changed, 67 insertions(+), 0 deletions(-) > > diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h > index ac9586d..7b600da 100644 > --- a/include/linux/scatterlist.h > +++ b/include/linux/scatterlist.h > @@ -214,6 +214,10 @@ void sg_free_table(struct sg_table *); > int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, >sg_alloc_fn *); > int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); > +int sg_alloc_table_from_pages(struct sg_table *sgt, > + struct page **pages, unsigned int n_pages, > + unsigned long offset, unsigned long size, > + gfp_t gfp_mask); > > size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, > void *buf, size_t buflen); > diff --git a/lib/scatterlist.c b/lib/scatterlist.c > index 6096e89..90f9265 100644 > --- a/lib/scatterlist.c > +++ b/lib/scatterlist.c > @@ -319,6 +319,69 @@ int sg_alloc_table(struct sg_table *table, unsigned int > nents, gfp_t gfp_mask) > EXPORT_SYMBOL(sg_alloc_table); > > /** > + * sg_alloc_table_from_pages - Allocate and initialize an sg table from > + * an array of pages > + * @sgt: The sg table header to use > + * @pages: Pointer to an array of page pointers > + * @n_pages: Number of pages in the pages array > + * @offset: Offset from a start of the first page to a start of a buffer > + * @size: Number of valid bytes in the buffer (after offset) > + * @gfp_mask:GFP allocation mask > + * > + * Description: > + *Allocate and initialize an sg table from a list of pages. Continuous > + *ranges of the pages are squashed into a single scatterlist node. A user > + *may provide an offset at a start and a size of valid data in a buffer > + *specified by the page array. The returned sg table is released by > + *sg_free_table. > + * > + * Returns: > + * 0 on success, negative error on failure > + **/ > +int sg_alloc_table_from_pages(struct sg_table *sgt, > + struct page **pages, unsigned int n_pages, > + unsigned long offset, unsigned long size, > + gfp_t gfp_mask) > +{ > + unsigned int chunks; > + unsigned int i; > + unsigned int cur_page; > + int ret; > + struct scatterlist *s; > + > + /* compute number of contiguous chunks */ > + chunks = 1; > + for (i = 1; i < n_pages; ++i) > + if (pages[i] != pages[i - 1] + 1) > + ++chunks; I'm not aware of the details (and didn't bother to do a full audit), but I guess this could blow up on funky discontig-mem setups. Imo would be safer to compare the pfn or phys address. And also slightly more readable. Imo sg table creation is not a fastpath, the exporter should cache these anyway, so we can waste some cpu cycles here. > + ret = sg_alloc_table(sgt, chunks, gfp_mask); > + if (unlikely(ret)) > + return ret; > + > + /* merging chunks and putting them into the scatterlist */ > + cur_page = 0; > + for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { > + unsigned long chunk_size; > + unsigned int j; > + > + /* looking for the end of the current chunk */ > + for (j = cur_page + 1; j < n_pages; ++j) > + if (pages[j] != pages[j - 1] + 1) > + break; > + > + chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset; > + sg_set_page(s, pages[cur_page], min(size, chunk_size), offset); > + size -= chunk_size; > + offset = 0; > + cur_page = j; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(sg_alloc_table_from_pages); > + > +/** > * sg_miter_start - start mapping iteration over a sg list > * @miter: sg mapping iter to be started > * @sgl: sg list to iterate over > -- > 1.7.5.4 > > ___ > dri-devel
Re: [PATCH] drm: Initial KMS driver for AST (ASpeed Technologies) 2000 series
On Mon, 2012-04-23 at 14:30 +0100, Alan Cox wrote: > > > fbdev objects once exposed to userspace or to fbcon, thanks to some > > wonderful > > API design way back, the mmaps on the fbdev device are direct to the VRAM > > physical pages. Can't tear them down and move them into system RAM pages > > at all easily. > > Thats not strictly true. They can move mapping if the locking is right > and the helpers handle it because you can invalidate the pages in the > userspace mappings and they will get faulted back with the new ones. fbdev userspace mappings is the easy part, TTM has supported that for years. The problem is fbcon, which can access the framebuffer from basically any context for printk. > > Because I'm not 100% sure nothing will get written to it, and if > > Fair point. > > > something gets written > > to it I'd rather not have to complicate the oops printing to have to > > page in memory > > from disk, when it might be the disk that caused the oops. > > If the box was horked that way then you are going to fail to migrate the > graphical frame buffer out in order to go into text mode to print the > oops. Probably safest any oops hits the current visible object ? It's not always that simple either, e.g. this wouldn't work when scanning out a tiled buffer on Radeon HDs. -- Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Debian, X and DRI developer ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel