[Intel-gfx] [PATCH] [drm/i915] Add support for creating an fb device using one pipe
Keith Packard
keithp at keithp.com
Mon Nov 3 08:39:03 CET 2008
This takes an existing configured pipe/plane and allocates a new frame
buffer for it, then it hooks that up to the framebuffer driver to create an
fb device. Suitable hacks to the X server to leave the vt in KD_TEXT mode
and you can use this fb device with fbcon to show console messages while X
is up and running.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
drivers/gpu/drm/Kconfig | 3 +
drivers/gpu/drm/i915/Makefile | 3 +-
drivers/gpu/drm/i915/i915_debug_fb.c | 435 ++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_debug_fb.h | 14 +
drivers/gpu/drm/i915/i915_drv.h | 7 +
drivers/gpu/drm/i915/i915_gem.c | 2 +
drivers/gpu/drm/i915/i915_gem_proc.c | 106 ++++++++
7 files changed, 569 insertions(+), 1 deletions(-)
create mode 100644 drivers/gpu/drm/i915/i915_debug_fb.c
create mode 100644 drivers/gpu/drm/i915/i915_debug_fb.h
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index a8b33c2..9612ee0 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -66,6 +66,9 @@ config DRM_I830
config DRM_I915
tristate "i915 driver"
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
help
Choose this option if you have a system that has Intel 830M, 845G,
852GM, 855GM 865G or 915G integrated graphics. If M is selected, the
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index d8fb5d8..9a83df3 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -8,7 +8,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
i915_gem.o \
i915_gem_debug.o \
i915_gem_proc.o \
- i915_gem_tiling.o
+ i915_gem_tiling.o \
+ i915_debug_fb.o
i915-$(CONFIG_ACPI) += i915_opregion.o
i915-$(CONFIG_COMPAT) += i915_ioc32.o
diff --git a/drivers/gpu/drm/i915/i915_debug_fb.c b/drivers/gpu/drm/i915/i915_debug_fb.c
new file mode 100644
index 0000000..02919b7
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_debug_fb.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright © 2008 Keith Packard <keithp at keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+/*
+ * Debug frame buffer. This steals one of the video outputs
+ * and replaces the frame buffer with our own memory
+ */
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tc.h>
+#include <linux/types.h>
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "i915_reg.h"
+#include <linux/swap.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+struct debug_fb_par {
+ int pipe;
+ int gtt_base;
+ size_t size;
+ struct drm_gem_object *fb_object;
+ u32 pseudo_palette[16];
+ u32 dspaddr_reg;
+ u32 saveDSPADDR;
+ u32 dspsurf_reg;
+ u32 saveDSPSURF;
+ u32 dsptileoff_reg;
+ u32 saveDSPTILEOFF;
+};
+
+static inline u32 convert_bitfield(int val, struct fb_bitfield *bf)
+{
+ unsigned int mask = (1 << bf->length) - 1;
+
+ return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
+static int i915_debug_fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ u32 v;
+
+ /* 16 registers */
+ if (regno >= 16)
+ return 1;
+
+ v = (convert_bitfield(transp, &info->var.transp) |
+ convert_bitfield(blue, &info->var.blue) |
+ convert_bitfield(green, &info->var.green) |
+ convert_bitfield(red, &info->var.red));
+
+ printk(KERN_INFO "color register %d rgb %04x %04x %04x v %08x\n",
+ regno, red, green, blue, v);
+
+ ((u32 *) (info->pseudo_palette))[regno] = v;
+ return 0;
+}
+
+static struct fb_var_screeninfo debug_fb_var = {
+ .xres = 1024,
+ .yres = 768,
+ .xres_virtual = 1024,
+ .yres_virtual = 768,
+ .bits_per_pixel = 32,
+ .red.length = 8,
+ .green.length = 8,
+ .blue.length = 8,
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .accel_flags = FB_ACCEL_NONE,
+ .pixclock = 14452,
+ .left_margin = 116,
+ .right_margin = 12,
+ .upper_margin = 34,
+ .lower_margin = 12,
+ .hsync_len = 128,
+ .vsync_len = 3,
+ .sync = FB_SYNC_ON_GREEN,
+ .vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo debug_fb_fix = {
+ .id = "DEBUG-FB",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+};
+
+static void i915_imageblit(struct fb_info *p, const struct fb_image *image)
+{
+#if 0
+ printk(KERN_INFO "imageblit state %d visual %d x %d y %d depth %d\n",
+ p->state, p->fix.visual, image->dx, image->dy, image->depth);
+ printk(KERN_INFO " fg %d -> %08x bg %d -> %08x\n",
+ image->fg_color,
+ ((u32*)(p->pseudo_palette))[image->fg_color],
+ image->bg_color,
+ ((u32*)(p->pseudo_palette))[image->bg_color]);
+#endif
+ cfb_imageblit(p, image);
+}
+
+static struct fb_ops debug_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_setcolreg = i915_debug_fb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = i915_imageblit,
+};
+
+static int pipe_for_plane(struct drm_device *dev, int plane)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ u32 dspcntr_reg = plane == 0 ? DSPACNTR : DSPBCNTR;
+ u32 dspcntr;
+
+ dspcntr = I915_READ(dspcntr_reg);
+ if (!(dspcntr & DISPLAY_PLANE_ENABLE))
+ return -1;
+
+ switch (dspcntr & DISPPLANE_SEL_PIPE_MASK) {
+ case DISPPLANE_SEL_PIPE_A:
+ return 0;
+ case DISPPLANE_SEL_PIPE_B:
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+static int plane_for_pipe(struct drm_device *dev, int pipe)
+{
+ if (pipe_for_plane(dev, 0) == pipe)
+ return 0;
+ if (pipe_for_plane(dev, 1) == pipe)
+ return 1;
+ return -1;
+}
+
+int i915_debug_fb_create(struct drm_device *dev, int pipe)
+{
+ struct drm_minor *minor = dev->primary;
+ struct device *device = &minor->kdev;
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct fb_info *info;
+ struct debug_fb_par *par;
+ int err;
+ int plane;
+ int width, height, bpp, depth, stride;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+ u32 dspcntr_reg, dspsize_reg, dspstride_reg, dspaddr_reg, pipesrc_reg;
+ u32 dspcntr, dspsize, dspstride, dspaddr, pipesrc;
+ u32 dspsurf_reg, dspsurf = 0;
+ u32 dsptileoff_reg, dsptileoff = 0;
+
+ plane = plane_for_pipe(dev, pipe);
+
+ switch (pipe) {
+ case 0:
+ pipesrc_reg = PIPEASRC;
+ break;
+ case 1:
+ pipesrc_reg = PIPEBSRC;
+ break;
+ default:
+ printk(KERN_ERR "pipe %d is not running\n", pipe);
+ return -ENXIO;
+ }
+
+ switch (plane) {
+ case 0:
+ dspcntr_reg = DSPACNTR;
+ dspsize_reg = DSPASIZE;
+ dspstride_reg = DSPASTRIDE;
+ dspaddr_reg = DSPAADDR;
+ dspsurf_reg = DSPASURF;
+ dsptileoff_reg = DSPATILEOFF;
+ break;
+ case 1:
+ dspcntr_reg = DSPBCNTR;
+ dspsize_reg = DSPBSIZE;
+ dspstride_reg = DSPBSTRIDE;
+ dspaddr_reg = DSPBADDR;
+ dspsurf_reg = DSPBSURF;
+ dsptileoff_reg = DSPBTILEOFF;
+ break;
+ default:
+ printk(KERN_ERR "pipe %d is not running\n", pipe);
+ return -ENXIO;
+ }
+ pipesrc = I915_READ(pipesrc_reg);
+ dspcntr = I915_READ(dspcntr_reg);
+ dspsize = I915_READ(dspsize_reg);
+ dspstride = I915_READ(dspstride_reg);
+ dspaddr = I915_READ(dspaddr_reg);
+ if (IS_I965G(dev)) {
+ dspsurf = I915_READ(dspsurf_reg);
+ dsptileoff = I915_READ(dsptileoff_reg);
+ }
+
+ switch (dspcntr & DISPPLANE_PIXFORMAT_MASK) {
+ case DISPPLANE_8BPP:
+ default:
+ bpp = 8; depth = 8; break;
+ case DISPPLANE_15_16BPP:
+ bpp = 16; depth = 15; break;
+ case DISPPLANE_16BPP:
+ bpp = 16; depth = 16; break;
+ case DISPPLANE_32BPP_NO_ALPHA:
+ case DISPPLANE_32BPP:
+ bpp = 32; depth = 24; break;
+ }
+ width = ((pipesrc >> 16) & 0xffff) + 1;
+ height = (pipesrc & 0xffff) + 1;
+ stride = (dspstride / (bpp / 8));
+ printk(KERN_INFO "detected plane %dx%d stride %d bpp %d\n",
+ width, height, stride, bpp);
+
+ info = framebuffer_alloc(sizeof(struct debug_fb_par), device);
+ if (!info) {
+ printk(KERN_ERR "%s: Cannot allocate memory\n", device->bus_id);
+ return -ENOMEM;
+ }
+
+ par = info->par;
+
+ par->pipe = pipe;
+ par->size = height * stride * bpp / 8;
+ par->dspaddr_reg = dspaddr_reg;
+ par->saveDSPADDR = dspaddr;
+ par->dspsurf_reg = dspsurf_reg;
+ par->saveDSPSURF = dspsurf;
+ par->dsptileoff_reg = dsptileoff_reg;
+ par->saveDSPTILEOFF = dsptileoff;
+ printk(KERN_INFO "save: DSPADDR %08x DSPSURF %08x DSPTILEOFF %08x\n",
+ par->saveDSPADDR, par->saveDSPSURF, par->saveDSPTILEOFF);
+
+ par->fb_object = drm_gem_object_alloc(dev, par->size);
+ printk(KERN_INFO "created object %p\n", par->fb_object);
+
+ if (!par->fb_object) {
+ printk(KERN_ERR "%s: Cannot allocate memory\n", device->bus_id);
+ err = -ENOMEM;
+ goto err_alloc;
+ }
+ obj = par->fb_object;
+ obj_priv = obj->driver_private;
+
+ err = i915_gem_object_pin(obj, 128 * 1024);
+
+ i915_gem_clflush_object (obj);
+ drm_agp_chipset_flush(dev);
+ obj->write_domain = 0;
+
+ printk(KERN_INFO "pinning returns %d\n", err);
+
+ if (err) {
+ printk(KERN_ERR "%s: Cannot pin framebuffer\n", device->bus_id);
+ goto err_pin;
+ }
+
+ dev_priv->fb_info = info;
+
+ info->fbops = &debug_fb_ops;
+ info->fix = debug_fb_fix;
+ info->var = debug_fb_var;
+ info->pseudo_palette = par->pseudo_palette;
+
+ info->var.xres = info->var.xres_virtual = width;
+ info->var.yres = info->var.yres_virtual = height;
+ info->var.bits_per_pixel = bpp;
+ switch (depth) {
+ case 8:
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ case 15:
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->var.red.offset = 10;
+ info->var.red.length = 5;
+ info->var.green.offset = 5;
+ info->var.green.length = 5;
+ info->var.blue.offset = 0;
+ info->var.blue.length = 5;
+ break;
+ case 16:
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->var.red.offset = 11;
+ info->var.red.length = 5;
+ info->var.green.offset = 5;
+ info->var.green.length = 6;
+ info->var.blue.offset = 0;
+ info->var.blue.length = 5;
+ break;
+ case 24:
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->var.red.offset = 16;
+ info->var.red.length = 8;
+ info->var.green.offset = 8;
+ info->var.green.length = 8;
+ info->var.blue.offset = 0;
+ info->var.blue.length = 8;
+ break;
+ }
+
+ info->flags = FBINFO_DEFAULT;
+
+ /* Frame buffer mapping setup. */
+ info->fix.smem_start = dev->agp->base + obj_priv->gtt_offset;
+ info->fix.smem_len = par->size;
+ info->fix.line_length = stride * bpp / 8;
+
+ printk(KERN_INFO "start %lx len %d\n", info->fix.smem_start, info->fix.smem_len);
+
+ info->screen_base = ioremap_wc(info->fix.smem_start,
+ info->fix.smem_len);
+ printk(KERN_INFO "screen mapped at %p\n", info->screen_base);
+ if (!info->screen_base) {
+ printk(KERN_ERR "%s: Cannot map FB\n", device->bus_id);
+ err = -ENOMEM;
+ goto err_ioremap;
+ }
+ info->screen_size = info->fix.smem_len;
+ memset(info->screen_base, 0, info->screen_size);
+
+ err = register_framebuffer(info);
+ if (err < 0) {
+ printk(KERN_ERR "%s: Cannot register framebuffer\n",
+ device->bus_id);
+ goto err_register;
+ }
+
+ if (IS_I965G(dev)) {
+ I915_WRITE(dspaddr_reg, 0);
+ I915_WRITE(dspsurf_reg, obj_priv->gtt_offset);
+ I915_WRITE(dsptileoff_reg, 0);
+ (void) I915_READ(dspsurf_reg);
+ } else {
+ I915_WRITE(dspaddr_reg, obj_priv->gtt_offset);
+ (void) I915_READ(dspaddr_reg);
+ }
+
+ pr_info("fb%d: %s frame buffer device at %s\n",
+ info->node, info->fix.id, device->bus_id);
+
+ return 0;
+
+err_register:
+ iounmap(info->screen_base);
+err_ioremap:
+ mutex_lock(&dev->struct_mutex);
+ i915_gem_object_unpin(obj);
+ mutex_unlock(&dev->struct_mutex);
+err_pin:
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+err_alloc:
+ framebuffer_release(info);
+ return err;
+}
+
+int i915_debug_fb_pipe(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct fb_info *info = dev_priv->fb_info;
+ struct debug_fb_par *par;
+
+ if (!info)
+ return -1;
+ par = info->par;
+ return par->pipe;
+}
+
+int i915_debug_fb_destroy(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct fb_info *info = dev_priv->fb_info;
+ struct debug_fb_par *par;
+ struct drm_gem_object *obj;
+
+ if (!info)
+ return 0;
+ par = info->par;
+ obj = par->fb_object;
+
+ printk(KERN_INFO "restore: DSPADDR %08x DSPSURF %08x DSPTILEOFF %08x\n",
+ par->saveDSPADDR, par->saveDSPSURF, par->saveDSPTILEOFF);
+ if (IS_I965G(dev)) {
+ I915_WRITE(par->dspaddr_reg, par->saveDSPADDR);
+ I915_WRITE(par->dspsurf_reg, par->saveDSPSURF);
+ I915_WRITE(par->dsptileoff_reg, par->saveDSPTILEOFF);
+ (void) I915_READ(par->dsptileoff_reg);
+ } else {
+ I915_WRITE(par->dspaddr_reg, par->saveDSPADDR);
+ (void) I915_READ(par->dspaddr_reg);
+ }
+
+ unregister_framebuffer(info);
+ iounmap(info->screen_base);
+
+ mutex_lock(&dev->struct_mutex);
+ i915_gem_object_unpin(par->fb_object);
+ drm_gem_object_unreference(par->fb_object);
+ mutex_unlock(&dev->struct_mutex);
+
+ framebuffer_release(info);
+
+ dev_priv->fb_info = NULL;
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_debug_fb.h b/drivers/gpu/drm/i915/i915_debug_fb.h
new file mode 100644
index 0000000..7269382
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_debug_fb.h
@@ -0,0 +1,14 @@
+
+/* IOmem resource offsets. */
+#define PMAG_BA_FBMEM 0x000000 /* frame buffer */
+#define PMAG_BA_BT459 0x200000 /* Bt459 RAMDAC */
+#define PMAG_BA_IRQ 0x300000 /* IRQ acknowledge */
+#define PMAG_BA_ROM 0x380000 /* REX option ROM */
+#define PMAG_BA_BT438 0x380000 /* Bt438 clock chip reset */
+#define PMAG_BA_SIZE 0x400000 /* address space size */
+
+/* Bt459 register offsets, byte-wide registers. */
+#define BT459_ADDR_LO 0x0 /* address low */
+#define BT459_ADDR_HI 0x4 /* address high */
+#define BT459_DATA 0x8 /* data window register */
+#define BT459_CMAP 0xc /* color map window register */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 2dfd4ac..868aefd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -152,6 +152,8 @@ typedef struct drm_i915_private {
struct intel_opregion opregion;
+ struct fb_info *fb_info;
+
/* Register state */
u8 saveLBB;
u32 saveDSPACNTR;
@@ -521,6 +523,11 @@ void i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_work_handler(struct work_struct *work);
void i915_gem_clflush_object(struct drm_gem_object *obj);
+/* i915_debug_fb.c */
+int i915_debug_fb_create(struct drm_device *dev, int pipe);
+int i915_debug_fb_pipe(struct drm_device *dev);
+int i915_debug_fb_destroy(struct drm_device *dev);
+
/* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 61f16e2..584195c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2600,6 +2600,8 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
ret = i915_gem_idle(dev);
drm_irq_uninstall(dev);
+ i915_debug_fb_destroy(dev);
+
io_mapping_free(dev_priv->mm.gtt_mapping);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c
index 93de15b..754b252 100644
--- a/drivers/gpu/drm/i915/i915_gem_proc.c
+++ b/drivers/gpu/drm/i915/i915_gem_proc.c
@@ -238,19 +238,96 @@ static int i915_interrupt_info(char *buf, char **start, off_t offset,
if (dev_priv->hw_status_page != NULL) {
DRM_PROC_PRINT("Current sequence: %d\n",
i915_get_gem_seqno(dev));
+ DRM_PROC_PRINT("Current breadcrumb: %d\n",
+ READ_BREADCRUMB(dev_priv));
} else {
DRM_PROC_PRINT("Current sequence: hws uninitialized\n");
+ DRM_PROC_PRINT("Current breadcrumb: hws uninitialized\n");
}
DRM_PROC_PRINT("Waiter sequence: %d\n",
dev_priv->mm.waiting_gem_seqno);
+ DRM_PROC_PRINT("Waiter breadcrumb: %d\n",
+ dev_priv->breadcrumb_wait);
DRM_PROC_PRINT("IRQ sequence: %d\n",
dev_priv->mm.irq_gem_seqno);
+ if (dev_priv->sarea_priv) {
+ DRM_PROC_PRINT("IRQ breadcrumb: %d\n",
+ dev_priv->sarea_priv->last_dispatch);
+ } else {
+ DRM_PROC_PRINT("IRQ breadcrumb: sarea uninitialized\n");
+ }
+
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+static int i915_gem_fb_read(char *buf, char **start, off_t offset,
+ int request, int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ int len = 0;
+ int pipe;
+
+ if (offset > DRM_PROC_LIMIT) {
+ *eof = 1;
+ return 0;
+ }
+
+ pipe = i915_debug_fb_pipe(dev);
+
+ *start = &buf[offset];
+ *eof = 0;
+ DRM_PROC_PRINT("Frame buffer pipe: %d\n", pipe);
if (len > request + offset)
return request;
*eof = 1;
return len - offset;
}
+#define LINE_SIZE 80
+
+static int i915_gem_fb_write(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ char line[LINE_SIZE];
+ char *end;
+ int pipe;
+ int ret;
+
+ if (!count)
+ return -EINVAL;
+ memset(line, 0, LINE_SIZE);
+ if (count > LINE_SIZE)
+ count = LINE_SIZE;
+ if (copy_from_user(line, buffer, count - 1))
+ return -EFAULT;
+ pipe = simple_strtol(line, &end, 10);
+ if (end == line)
+ return -EINVAL;
+ DRM_ERROR("line %s pipe %d\n", line, pipe);
+ switch (pipe) {
+ case 0:
+ case 1:
+ i915_debug_fb_destroy(dev);
+ ret = i915_debug_fb_create(dev, pipe);
+ break;
+ case -1:
+ ret = i915_debug_fb_destroy(dev);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret == 0)
+ ret = count;
+ return ret;
+}
+
static struct drm_proc_list {
/** file name */
const char *name;
@@ -267,6 +344,19 @@ static struct drm_proc_list {
#define I915_GEM_PROC_ENTRIES ARRAY_SIZE(i915_gem_proc_list)
+static struct drm_rw_proc_list {
+ /** file name */
+ const char *name;
+ /** proc callback*/
+ int (*read) (char *, char **, off_t, int, int *, void *);
+ int (*write) (struct file *file, const char __user *buffer,
+ unsigned long len, void *data);
+} i915_gem_proc_rw_list[] = {
+ {"i915_gem_fb", i915_gem_fb_read, i915_gem_fb_write},
+};
+
+#define I915_GEM_PROC_RW_ENTRIES ARRAY_SIZE(i915_gem_proc_rw_list)
+
int i915_gem_proc_init(struct drm_minor *minor)
{
struct proc_dir_entry *ent;
@@ -286,6 +376,20 @@ int i915_gem_proc_init(struct drm_minor *minor)
ent->read_proc = i915_gem_proc_list[i].f;
ent->data = minor;
}
+
+ for (i = 0; i < I915_GEM_PROC_RW_ENTRIES; i++) {
+ ent = create_proc_entry(i915_gem_proc_rw_list[i].name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ minor->dev_root);
+ if (!ent) {
+ DRM_ERROR("Cannot create /proc/dri/.../%s\n",
+ i915_gem_proc_rw_list[i].name);
+ return -1;
+ }
+ ent->read_proc = i915_gem_proc_rw_list[i].read;
+ ent->write_proc = i915_gem_proc_rw_list[i].write;
+ ent->data = minor;
+ }
return 0;
}
@@ -298,4 +402,6 @@ void i915_gem_proc_cleanup(struct drm_minor *minor)
for (i = 0; i < I915_GEM_PROC_ENTRIES; i++)
remove_proc_entry(i915_gem_proc_list[i].name, minor->dev_root);
+ for (i = 0; i < I915_GEM_PROC_RW_ENTRIES; i++)
+ remove_proc_entry(i915_gem_proc_rw_list[i].name, minor->dev_root);
}
--
1.5.6.5
More information about the Intel-gfx
mailing list