On Thu, Nov 10, 2011 at 8:54 AM, InKi Dae <daeinki@xxxxxxxxx> wrote: > 2011/11/9 Rob Clark <robdclark@xxxxxxxxx>: >> On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae <daeinki@xxxxxxxxx> wrote: >>> Hello, all. >>> >>> I am trying to implement multi planer using your plane patch and I >>> think it's good but I am still warried about that drm_mode_fb_cmd2 >>> structure has only one handle. I know this handle is sent to >>> framebuffer module to create new framebuffer. and the framebuffer >>> would cover entire a image. as you know, the image could be consisted >>> of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't >>> support multi planer because it has only one handle. with update_plane >>> callback, a buffer of the framebuffer would be set to a hardware >>> overlay. how we could set two planes or three planes to the hardware >>> overlay? but there might be my missing point so please give me any >>> comments. in addition, have you been looked into gem flink and open >>> functions for memory sharing between processes? gem object basically >>> has one buffer so we can't modify it because of compatibility. so I >>> think it's right way that gem object manages only one buffer. for such >>> a reason, maybe drm_mode_fb_cmd2 structure should include one more >>> handles and plane count. each handle has a gem object to one plane and >>> plane count means how many planes are requested and when update_plane >>> callback is called by setplane(), we could set them of the specific >>> framebuffer to a hardware overlay. >> >> The current plan is to add a 3rd ioctl, for adding multi-planar fb.. >> I guess it is a good thing that I'm not the only one who wants this >> :-) >> >>> another one, and also I have tried to implement the way sharing the >>> memory between v4l2 based drivers and drm based drivers through >>> application and this works fine. this feature had been introduced by >>> v4l2 framework as user ptr. my way also is similar to it. the >>> difference is that application could get new gem handle from specific >>> gem framework of kernel side if user application requests user ptr >>> import with the user space address(mmaped memory). the new gem handle >>> means a gem object to the memory mapped to the user space address. >>> this way makes different applications to be possible to share the >>> memory between v4l2 based driver and drm based driver. and also this >>> feature is considered for IOMMU so it would support non continuous >>> memory also. I will introduce this feature soon. >> >> btw, there was an RFC a little while back for "dmabuf" buffer sharing >> mechanism.. the idea would be to export a (for example) GEM buffer to >> a dmabuf handle which could be passed in to other devices, including >> for example v4l2 (although without necessarily requiring a userspace >> mapping).. >> >> http://www.spinics.net/lists/dri-devel/msg15077.html >> >> It sounds like you are looking for a similar thing.. >> > > Hi, Rob. > > GEM framework already supports memory sharing way that a object name > created by gem flink is sent to another process and then the process > opens the object name. at that time, the gem framework of kernel side > creates new gem object. and I know that dmabuf is similar to the ION > introduced by Rebecca who is an engineer of Google at least for buffer > sharing way. but is it possible to share the memory region drawing on > only user virtual address mmaped with another process?. for instance, > as you know, v4l2 based driver has request buf feature that the driver > of kernel side allocates the memory regions as user-desired buffer > count and user gets user virtual address with mmap request after quary > buffer request. so we need to share this memory mmaped at here also. > for this, v4l2 based driver has userptr feature that user application > sets user virtual address to userptr structure and then the address is > translated to bus address(physical address without iommu or device > address with iommu) and sets it to hardware. I think it doesn't need > dmabuf if we would use it only for sharing the gem buffer with another > process because GEM framework already can do it. I will try to find > the way that we can use this feature commonly for generic gem > framework. this feature has already been implemented in our specific > gem framework and also tested. There are a few limitations with userptr: 1) will simply fail if importing driver has some special dma requirements (contiguous memory, specific address range, etc).. 2) requires a userspace virtual mapping of buffer.. which might not always be required for fully hw accelerated use cases And in general I'm not a huge fan of dma'ing to arbitrary malloc'd buffers (which userptr seems to encourage).. So it's true, that somehow people have managed to ship linux based products without dmabuf, using various hacks.. but part of the point of dmabuf is to try to get to a cleaner more generic solution. BR, -R > thank you, > Inki dae. > > >> BR, >> -R >> >>> Thank you, >>> Inki Dae. >>> >>> 2011/11/9 Jesse Barnes <jbarnes@xxxxxxxxxxxxxxxx>: >>>> To properly support the various plane formats supported by different >>>> hardware, the kernel must know the pixel format of a framebuffer object. >>>> So add a new ioctl taking a format argument corresponding to a fourcc >>>> name from videodev2.h. Implement the fb creation hooks in terms of the >>>> new mode_fb_cmd2 using helpers where the old bpp/depth values are >>>> needed. >>>> >>>> Acked-by: Alan Cox <alan@xxxxxxxxxxxxxxxxxxx> >>>> Reviewed-by: Rob Clark <rob.clark@xxxxxxxxxx> >>>> Signed-off-by: Jesse Barnes <jbarnes@xxxxxxxxxxxxxxxx> >>>> --- >>>> drivers/gpu/drm/drm_crtc.c | 108 +++++++++++++++++++++++++++- >>>> drivers/gpu/drm/drm_crtc_helper.c | 50 ++++++++++++- >>>> drivers/gpu/drm/drm_drv.c | 1 + >>>> drivers/gpu/drm/i915/intel_display.c | 36 +++++----- >>>> drivers/gpu/drm/i915/intel_drv.h | 2 +- >>>> drivers/gpu/drm/i915/intel_fb.c | 11 ++-- >>>> drivers/gpu/drm/nouveau/nouveau_display.c | 4 +- >>>> drivers/gpu/drm/nouveau/nouveau_fb.h | 2 +- >>>> drivers/gpu/drm/nouveau/nouveau_fbcon.c | 13 ++-- >>>> drivers/gpu/drm/radeon/radeon_display.c | 4 +- >>>> drivers/gpu/drm/radeon/radeon_fb.c | 18 +++-- >>>> drivers/gpu/drm/radeon/radeon_mode.h | 2 +- >>>> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 ++++-- >>>> drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 + >>>> drivers/staging/gma500/framebuffer.c | 2 +- >>>> include/drm/drm.h | 1 + >>>> include/drm/drm_crtc.h | 7 ++- >>>> include/drm/drm_crtc_helper.h | 4 +- >>>> include/drm/drm_mode.h | 28 +++++++- >>>> include/linux/videodev2.h | 1 + >>>> 20 files changed, 256 insertions(+), 61 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c >>>> index 804ef12..39cccb4 100644 >>>> --- a/drivers/gpu/drm/drm_crtc.c >>>> +++ b/drivers/gpu/drm/drm_crtc.c >>>> @@ -1910,6 +1910,42 @@ out: >>>> return ret; >>>> } >>>> >>>> +/* Original addfb only supported RGB formats, so figure out which one */ >>>> +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) >>>> +{ >>>> + uint32_t fmt; >>>> + >>>> + switch (bpp) { >>>> + case 8: >>>> + fmt = V4L2_PIX_FMT_RGB332; >>>> + break; >>>> + case 16: >>>> + if (depth == 15) >>>> + fmt = V4L2_PIX_FMT_RGB555; >>>> + else >>>> + fmt = V4L2_PIX_FMT_RGB565; >>>> + break; >>>> + case 24: >>>> + fmt = V4L2_PIX_FMT_RGB24; >>>> + break; >>>> + case 32: >>>> + if (depth == 24) >>>> + fmt = V4L2_PIX_FMT_RGB24; >>>> + else if (depth == 30) >>>> + fmt = V4L2_PIX_FMT_INTC_RGB30; >>>> + else >>>> + fmt = V4L2_PIX_FMT_RGB32; >>>> + break; >>>> + default: >>>> + DRM_ERROR("bad bpp, assuming RGB24 pixel format\n"); >>>> + fmt = V4L2_PIX_FMT_RGB24; >>>> + break; >>>> + } >>>> + >>>> + return fmt; >>>> +} >>>> +EXPORT_SYMBOL(drm_mode_legacy_fb_format); >>>> + >>>> /** >>>> * drm_mode_addfb - add an FB to the graphics configuration >>>> * @inode: inode from the ioctl >>>> @@ -1930,7 +1966,74 @@ out: >>>> int drm_mode_addfb(struct drm_device *dev, >>>> void *data, struct drm_file *file_priv) >>>> { >>>> - struct drm_mode_fb_cmd *r = data; >>>> + struct drm_mode_fb_cmd *or = data; >>>> + struct drm_mode_fb_cmd2 r; >>>> + struct drm_mode_config *config = &dev->mode_config; >>>> + struct drm_framebuffer *fb; >>>> + int ret = 0; >>>> + >>>> + /* Use new struct with format internally */ >>>> + r.fb_id = or->fb_id; >>>> + r.width = or->width; >>>> + r.height = or->height; >>>> + r.pitches[0] = or->pitch; >>>> + r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); >>>> + r.handle = or->handle; >>>> + >>>> + if (!drm_core_check_feature(dev, DRIVER_MODESET)) >>>> + return -EINVAL; >>>> + >>>> + if ((config->min_width > r.width) || (r.width > config->max_width)) { >>>> + DRM_ERROR("mode new framebuffer width not within limits\n"); >>>> + return -EINVAL; >>>> + } >>>> + if ((config->min_height > r.height) || (r.height > config->max_height)) { >>>> + DRM_ERROR("mode new framebuffer height not within limits\n"); >>>> + return -EINVAL; >>>> + } >>>> + >>>> + mutex_lock(&dev->mode_config.mutex); >>>> + >>>> + /* TODO check buffer is sufficiently large */ >>>> + /* TODO setup destructor callback */ >>>> + >>>> + fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); >>>> + if (IS_ERR(fb)) { >>>> + DRM_ERROR("could not create framebuffer\n"); >>>> + ret = PTR_ERR(fb); >>>> + goto out; >>>> + } >>>> + >>>> + or->fb_id = fb->base.id; >>>> + list_add(&fb->filp_head, &file_priv->fbs); >>>> + DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); >>>> + >>>> +out: >>>> + mutex_unlock(&dev->mode_config.mutex); >>>> + return ret; >>>> +} >>>> + >>>> +/** >>>> + * drm_mode_addfb2 - add an FB to the graphics configuration >>>> + * @inode: inode from the ioctl >>>> + * @filp: file * from the ioctl >>>> + * @cmd: cmd from ioctl >>>> + * @arg: arg from ioctl >>>> + * >>>> + * LOCKING: >>>> + * Takes mode config lock. >>>> + * >>>> + * Add a new FB to the specified CRTC, given a user request with format. >>>> + * >>>> + * Called by the user via ioctl. >>>> + * >>>> + * RETURNS: >>>> + * Zero on success, errno on failure. >>>> + */ >>>> +int drm_mode_addfb2(struct drm_device *dev, >>>> + void *data, struct drm_file *file_priv) >>>> +{ >>>> + struct drm_mode_fb_cmd2 *r = data; >>>> struct drm_mode_config *config = &dev->mode_config; >>>> struct drm_framebuffer *fb; >>>> int ret = 0; >>>> @@ -1951,9 +2054,6 @@ int drm_mode_addfb(struct drm_device *dev, >>>> >>>> mutex_lock(&dev->mode_config.mutex); >>>> >>>> - /* TODO check buffer is sufficiently large */ >>>> - /* TODO setup destructor callback */ >>>> - >>>> fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); >>>> if (IS_ERR(fb)) { >>>> DRM_ERROR("could not create framebuffer\n"); >>>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c >>>> index f236644..68011bb 100644 >>>> --- a/drivers/gpu/drm/drm_crtc_helper.c >>>> +++ b/drivers/gpu/drm/drm_crtc_helper.c >>>> @@ -807,14 +807,56 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode) >>>> } >>>> EXPORT_SYMBOL(drm_helper_connector_dpms); >>>> >>>> +/* >>>> + * Just need to support RGB formats here for compat with code that doesn't >>>> + * use pixel formats directly yet. >>>> + */ >>>> +void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth, >>>> + int *bpp) >>>> +{ >>>> + switch (format) { >>>> + case V4L2_PIX_FMT_RGB332: >>>> + *depth = 8; >>>> + *bpp = 8; >>>> + break; >>>> + case V4L2_PIX_FMT_RGB555: >>>> + *depth = 15; >>>> + *bpp = 16; >>>> + break; >>>> + case V4L2_PIX_FMT_RGB565: >>>> + *depth = 16; >>>> + *bpp = 16; >>>> + break; >>>> + case V4L2_PIX_FMT_RGB24: >>>> + *depth = 24; >>>> + *bpp = 32; >>>> + break; >>>> + case V4L2_PIX_FMT_INTC_RGB30: >>>> + *depth = 30; >>>> + *bpp = 32; >>>> + break; >>>> + case V4L2_PIX_FMT_RGB32: >>>> + *depth = 32; >>>> + *bpp = 32; >>>> + break; >>>> + default: >>>> + DRM_DEBUG_KMS("unsupported pixel format\n"); >>>> + *depth = 0; >>>> + *bpp = 0; >>>> + break; >>>> + } >>>> +} >>>> +EXPORT_SYMBOL(drm_helper_get_fb_bpp_depth); >>>> + >>>> int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, >>>> - struct drm_mode_fb_cmd *mode_cmd) >>>> + struct drm_mode_fb_cmd2 *mode_cmd) >>>> { >>>> fb->width = mode_cmd->width; >>>> fb->height = mode_cmd->height; >>>> - fb->pitch = mode_cmd->pitch; >>>> - fb->bits_per_pixel = mode_cmd->bpp; >>>> - fb->depth = mode_cmd->depth; >>>> + fb->pitch = mode_cmd->pitches[0]; >>>> + drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &fb->depth, >>>> + &fb->bits_per_pixel); >>>> + fb->pixel_format = mode_cmd->pixel_format; >>>> >>>> return 0; >>>> } >>>> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c >>>> index d782bd1..6d87a59 100644 >>>> --- a/drivers/gpu/drm/drm_drv.c >>>> +++ b/drivers/gpu/drm/drm_drv.c >>>> @@ -152,6 +152,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { >>>> DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), >>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c >>>> index 9fa342e..aae7b03 100644 >>>> --- a/drivers/gpu/drm/i915/intel_display.c >>>> +++ b/drivers/gpu/drm/i915/intel_display.c >>>> @@ -6279,7 +6279,7 @@ static struct drm_display_mode load_detect_mode = { >>>> >>>> static struct drm_framebuffer * >>>> intel_framebuffer_create(struct drm_device *dev, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct drm_i915_gem_object *obj) >>>> { >>>> struct intel_framebuffer *intel_fb; >>>> @@ -6321,7 +6321,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, >>>> int depth, int bpp) >>>> { >>>> struct drm_i915_gem_object *obj; >>>> - struct drm_mode_fb_cmd mode_cmd; >>>> + struct drm_mode_fb_cmd2 mode_cmd; >>>> >>>> obj = i915_gem_alloc_object(dev, >>>> intel_framebuffer_size_for_mode(mode, bpp)); >>>> @@ -6330,9 +6330,9 @@ intel_framebuffer_create_for_mode(struct drm_device *dev, >>>> >>>> mode_cmd.width = mode->hdisplay; >>>> mode_cmd.height = mode->vdisplay; >>>> - mode_cmd.depth = depth; >>>> - mode_cmd.bpp = bpp; >>>> - mode_cmd.pitch = intel_framebuffer_pitch_for_width(mode_cmd.width, bpp); >>>> + mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width, >>>> + bpp); >>>> + mode_cmd.pixel_format = 0; >>>> >>>> return intel_framebuffer_create(dev, &mode_cmd, obj); >>>> } >>>> @@ -7573,7 +7573,7 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { >>>> >>>> int intel_framebuffer_init(struct drm_device *dev, >>>> struct intel_framebuffer *intel_fb, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct drm_i915_gem_object *obj) >>>> { >>>> int ret; >>>> @@ -7581,21 +7581,23 @@ int intel_framebuffer_init(struct drm_device *dev, >>>> if (obj->tiling_mode == I915_TILING_Y) >>>> return -EINVAL; >>>> >>>> - if (mode_cmd->pitch & 63) >>>> + if (mode_cmd->pitches[0] & 63) >>>> return -EINVAL; >>>> >>>> - switch (mode_cmd->bpp) { >>>> - case 8: >>>> - case 16: >>>> - /* Only pre-ILK can handle 5:5:5 */ >>>> - if (mode_cmd->depth == 15 && !HAS_PCH_SPLIT(dev)) >>>> - return -EINVAL; >>>> + switch (mode_cmd->pixel_format) { >>>> + case V4L2_PIX_FMT_RGB332: >>>> + case V4L2_PIX_FMT_RGB565: >>>> + case V4L2_PIX_FMT_RGB24: >>>> + case V4L2_PIX_FMT_INTC_RGB30: >>>> + /* RGB formats are common across chipsets */ >>>> break; >>>> - >>>> - case 24: >>>> - case 32: >>>> + case V4L2_PIX_FMT_YUYV: >>>> + case V4L2_PIX_FMT_UYVY: >>>> + case V4L2_PIX_FMT_YVYU: >>>> + case V4L2_PIX_FMT_VYUY: >>>> break; >>>> default: >>>> + DRM_ERROR("unsupported pixel format\n"); >>>> return -EINVAL; >>>> } >>>> >>>> @@ -7613,7 +7615,7 @@ int intel_framebuffer_init(struct drm_device *dev, >>>> static struct drm_framebuffer * >>>> intel_user_framebuffer_create(struct drm_device *dev, >>>> struct drm_file *filp, >>>> - struct drm_mode_fb_cmd *mode_cmd) >>>> + struct drm_mode_fb_cmd2 *mode_cmd) >>>> { >>>> struct drm_i915_gem_object *obj; >>>> >>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h >>>> index bd9a604..23c5622 100644 >>>> --- a/drivers/gpu/drm/i915/intel_drv.h >>>> +++ b/drivers/gpu/drm/i915/intel_drv.h >>>> @@ -359,7 +359,7 @@ extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, >>>> >>>> extern int intel_framebuffer_init(struct drm_device *dev, >>>> struct intel_framebuffer *ifb, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct drm_i915_gem_object *obj); >>>> extern int intel_fbdev_init(struct drm_device *dev); >>>> extern void intel_fbdev_fini(struct drm_device *dev); >>>> diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c >>>> index ec49bae..dc1db4f 100644 >>>> --- a/drivers/gpu/drm/i915/intel_fb.c >>>> +++ b/drivers/gpu/drm/i915/intel_fb.c >>>> @@ -65,7 +65,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, >>>> struct drm_i915_private *dev_priv = dev->dev_private; >>>> struct fb_info *info; >>>> struct drm_framebuffer *fb; >>>> - struct drm_mode_fb_cmd mode_cmd; >>>> + struct drm_mode_fb_cmd2 mode_cmd; >>>> struct drm_i915_gem_object *obj; >>>> struct device *device = &dev->pdev->dev; >>>> int size, ret; >>>> @@ -77,11 +77,12 @@ static int intelfb_create(struct intel_fbdev *ifbdev, >>>> mode_cmd.width = sizes->surface_width; >>>> mode_cmd.height = sizes->surface_height; >>>> >>>> - mode_cmd.bpp = sizes->surface_bpp; >>>> - mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); >>>> - mode_cmd.depth = sizes->surface_depth; >>>> + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / >>>> + 8), 64); >>>> + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, >>>> + sizes->surface_depth); >>>> >>>> - size = mode_cmd.pitch * mode_cmd.height; >>>> + size = mode_cmd.pitches[0] * mode_cmd.height; >>>> size = ALIGN(size, PAGE_SIZE); >>>> obj = i915_gem_alloc_object(dev, size); >>>> if (!obj) { >>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c >>>> index ddbabef..7a428a9 100644 >>>> --- a/drivers/gpu/drm/nouveau/nouveau_display.c >>>> +++ b/drivers/gpu/drm/nouveau/nouveau_display.c >>>> @@ -64,7 +64,7 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { >>>> int >>>> nouveau_framebuffer_init(struct drm_device *dev, >>>> struct nouveau_framebuffer *nv_fb, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct nouveau_bo *nvbo) >>>> { >>>> struct drm_nouveau_private *dev_priv = dev->dev_private; >>>> @@ -124,7 +124,7 @@ nouveau_framebuffer_init(struct drm_device *dev, >>>> static struct drm_framebuffer * >>>> nouveau_user_framebuffer_create(struct drm_device *dev, >>>> struct drm_file *file_priv, >>>> - struct drm_mode_fb_cmd *mode_cmd) >>>> + struct drm_mode_fb_cmd2 *mode_cmd) >>>> { >>>> struct nouveau_framebuffer *nouveau_fb; >>>> struct drm_gem_object *gem; >>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h >>>> index 95c843e..f4dd301 100644 >>>> --- a/drivers/gpu/drm/nouveau/nouveau_fb.h >>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fb.h >>>> @@ -45,5 +45,5 @@ nouveau_framebuffer(struct drm_framebuffer *fb) >>>> extern const struct drm_mode_config_funcs nouveau_mode_config_funcs; >>>> >>>> int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, >>>> - struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo); >>>> + struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo); >>>> #endif /* __NOUVEAU_FB_H__ */ >>>> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c >>>> index 14a8627..d663065 100644 >>>> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c >>>> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c >>>> @@ -281,7 +281,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, >>>> struct nouveau_framebuffer *nouveau_fb; >>>> struct nouveau_channel *chan; >>>> struct nouveau_bo *nvbo; >>>> - struct drm_mode_fb_cmd mode_cmd; >>>> + struct drm_mode_fb_cmd2 mode_cmd; >>>> struct pci_dev *pdev = dev->pdev; >>>> struct device *device = &pdev->dev; >>>> int size, ret; >>>> @@ -289,12 +289,13 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, >>>> mode_cmd.width = sizes->surface_width; >>>> mode_cmd.height = sizes->surface_height; >>>> >>>> - mode_cmd.bpp = sizes->surface_bpp; >>>> - mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); >>>> - mode_cmd.pitch = roundup(mode_cmd.pitch, 256); >>>> - mode_cmd.depth = sizes->surface_depth; >>>> + mode_cmd.pitches[0] = mode_cmd.width * (sizes->surface_bpp >> 3); >>>> + mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], 256); >>>> >>>> - size = mode_cmd.pitch * mode_cmd.height; >>>> + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, >>>> + sizes->surface_depth); >>>> + >>>> + size = mode_cmd.pitches[0] * mode_cmd.height; >>>> size = roundup(size, PAGE_SIZE); >>>> >>>> ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, >>>> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c >>>> index 6adb3e5..6fde9c3 100644 >>>> --- a/drivers/gpu/drm/radeon/radeon_display.c >>>> +++ b/drivers/gpu/drm/radeon/radeon_display.c >>>> @@ -1113,7 +1113,7 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = { >>>> void >>>> radeon_framebuffer_init(struct drm_device *dev, >>>> struct radeon_framebuffer *rfb, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct drm_gem_object *obj) >>>> { >>>> rfb->obj = obj; >>>> @@ -1124,7 +1124,7 @@ radeon_framebuffer_init(struct drm_device *dev, >>>> static struct drm_framebuffer * >>>> radeon_user_framebuffer_create(struct drm_device *dev, >>>> struct drm_file *file_priv, >>>> - struct drm_mode_fb_cmd *mode_cmd) >>>> + struct drm_mode_fb_cmd2 *mode_cmd) >>>> { >>>> struct drm_gem_object *obj; >>>> struct radeon_framebuffer *radeon_fb; >>>> diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c >>>> index 0b7b486..ea110ad 100644 >>>> --- a/drivers/gpu/drm/radeon/radeon_fb.c >>>> +++ b/drivers/gpu/drm/radeon/radeon_fb.c >>>> @@ -103,7 +103,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) >>>> } >>>> >>>> static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct drm_gem_object **gobj_p) >>>> { >>>> struct radeon_device *rdev = rfbdev->rdev; >>>> @@ -114,13 +114,17 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, >>>> int ret; >>>> int aligned_size, size; >>>> int height = mode_cmd->height; >>>> + u32 bpp, depth; >>>> + >>>> + drm_helper_get_fb_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); >>>> >>>> /* need to align pitch with crtc limits */ >>>> - mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8); >>>> + mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, >>>> + fb_tiled) * ((bpp + 1) / 8); >>>> >>>> if (rdev->family >= CHIP_R600) >>>> height = ALIGN(mode_cmd->height, 8); >>>> - size = mode_cmd->pitch * height; >>>> + size = mode_cmd->pitches[0] * height; >>>> aligned_size = ALIGN(size, PAGE_SIZE); >>>> ret = radeon_gem_object_create(rdev, aligned_size, 0, >>>> RADEON_GEM_DOMAIN_VRAM, >>>> @@ -151,7 +155,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, >>>> if (tiling_flags) { >>>> ret = radeon_bo_set_tiling_flags(rbo, >>>> tiling_flags | RADEON_TILING_SURFACE, >>>> - mode_cmd->pitch); >>>> + mode_cmd->pitches[0]); >>>> if (ret) >>>> dev_err(rdev->dev, "FB failed to set tiling flags\n"); >>>> } >>>> @@ -187,7 +191,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, >>>> struct radeon_device *rdev = rfbdev->rdev; >>>> struct fb_info *info; >>>> struct drm_framebuffer *fb = NULL; >>>> - struct drm_mode_fb_cmd mode_cmd; >>>> + struct drm_mode_fb_cmd2 mode_cmd; >>>> struct drm_gem_object *gobj = NULL; >>>> struct radeon_bo *rbo = NULL; >>>> struct device *device = &rdev->pdev->dev; >>>> @@ -201,8 +205,8 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, >>>> if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) >>>> sizes->surface_bpp = 32; >>>> >>>> - mode_cmd.bpp = sizes->surface_bpp; >>>> - mode_cmd.depth = sizes->surface_depth; >>>> + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, >>>> + sizes->surface_depth); >>>> >>>> ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); >>>> rbo = gem_to_radeon_bo(gobj); >>>> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h >>>> index ed0178f..dd429a1 100644 >>>> --- a/drivers/gpu/drm/radeon/radeon_mode.h >>>> +++ b/drivers/gpu/drm/radeon/radeon_mode.h >>>> @@ -645,7 +645,7 @@ extern void radeon_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green >>>> u16 *blue, int regno); >>>> void radeon_framebuffer_init(struct drm_device *dev, >>>> struct radeon_framebuffer *rfb, >>>> - struct drm_mode_fb_cmd *mode_cmd, >>>> + struct drm_mode_fb_cmd2 *mode_cmd, >>>> struct drm_gem_object *obj); >>>> >>>> int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); >>>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c >>>> index 8b14dfd..61a030c 100644 >>>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c >>>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c >>>> @@ -974,7 +974,7 @@ out_err1: >>>> >>>> static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, >>>> struct drm_file *file_priv, >>>> - struct drm_mode_fb_cmd *mode_cmd) >>>> + struct drm_mode_fb_cmd2 *mode_cmd2) >>>> { >>>> struct vmw_private *dev_priv = vmw_priv(dev); >>>> struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; >>>> @@ -982,16 +982,24 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, >>>> struct vmw_surface *surface = NULL; >>>> struct vmw_dma_buffer *bo = NULL; >>>> struct ttm_base_object *user_obj; >>>> + struct drm_mode_fb_cmd mode_cmd; >>>> u64 required_size; >>>> int ret; >>>> >>>> + mode_cmd.width = mode_cmd2->width; >>>> + mode_cmd.height = mode_cmd2->height; >>>> + mode_cmd.pitch = mode_cmd2->pitches[0]; >>>> + mode_cmd.handle = mode_cmd2->handle; >>>> + drm_helper_get_fb_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth, >>>> + &mode_cmd.bpp); >>>> + >>>> /** >>>> * This code should be conditioned on Screen Objects not being used. >>>> * If screen objects are used, we can allocate a GMR to hold the >>>> * requested framebuffer. >>>> */ >>>> >>>> - required_size = mode_cmd->pitch * mode_cmd->height; >>>> + required_size = mode_cmd.pitch * mode_cmd.height; >>>> if (unlikely(required_size > (u64) dev_priv->vram_size)) { >>>> DRM_ERROR("VRAM size is too small for requested mode.\n"); >>>> return NULL; >>>> @@ -1006,7 +1014,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, >>>> * command stream using user-space handles. >>>> */ >>>> >>>> - user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle); >>>> + user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle); >>>> if (unlikely(user_obj == NULL)) { >>>> DRM_ERROR("Could not locate requested kms frame buffer.\n"); >>>> return ERR_PTR(-ENOENT); >>>> @@ -1017,7 +1025,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, >>>> */ >>>> >>>> ret = vmw_user_surface_lookup_handle(dev_priv, tfile, >>>> - mode_cmd->handle, &surface); >>>> + mode_cmd.handle, &surface); >>>> if (ret) >>>> goto try_dmabuf; >>>> >>>> @@ -1025,7 +1033,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, >>>> goto err_not_scanout; >>>> >>>> ret = vmw_kms_new_framebuffer_surface(dev_priv, file_priv, surface, >>>> - &vfb, mode_cmd); >>>> + &vfb, &mode_cmd); >>>> >>>> /* vmw_user_surface_lookup takes one ref so does new_fb */ >>>> vmw_surface_unreference(&surface); >>>> @@ -1041,14 +1049,14 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, >>>> try_dmabuf: >>>> DRM_INFO("%s: trying buffer\n", __func__); >>>> >>>> - ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo); >>>> + ret = vmw_user_dmabuf_lookup(tfile, mode_cmd.handle, &bo); >>>> if (ret) { >>>> DRM_ERROR("failed to find buffer: %i\n", ret); >>>> return ERR_PTR(-ENOENT); >>>> } >>>> >>>> ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb, >>>> - mode_cmd); >>>> + &mode_cmd); >>>> >>>> /* vmw_user_dmabuf_lookup takes one ref so does new_fb */ >>>> vmw_dmabuf_unreference(&bo); >>>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h >>>> index db0b901..e199adf 100644 >>>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h >>>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h >>>> @@ -29,6 +29,7 @@ >>>> #define VMWGFX_KMS_H_ >>>> >>>> #include "drmP.h" >>>> +#include "drm_crtc_helper.h" >>>> #include "vmwgfx_drv.h" >>>> >>>> #define VMWGFX_NUM_DISPLAY_UNITS 8 >>>> diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c >>>> index 3f39a37..1e77229 100644 >>>> --- a/drivers/staging/gma500/framebuffer.c >>>> +++ b/drivers/staging/gma500/framebuffer.c >>>> @@ -546,7 +546,7 @@ out_err1: >>>> */ >>>> static struct drm_framebuffer *psb_user_framebuffer_create >>>> (struct drm_device *dev, struct drm_file *filp, >>>> - struct drm_mode_fb_cmd *cmd) >>>> + struct drm_mode_fb_cmd2 *cmd) >>>> { >>>> struct gtt_range *r; >>>> struct drm_gem_object *obj; >>>> diff --git a/include/drm/drm.h b/include/drm/drm.h >>>> index 2897967..49d94ed 100644 >>>> --- a/include/drm/drm.h >>>> +++ b/include/drm/drm.h >>>> @@ -717,6 +717,7 @@ struct drm_get_cap { >>>> #define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res) >>>> #define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane) >>>> #define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane) >>>> +#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2) >>>> >>>> /** >>>> * Device specific ioctls should only be in their respective headers >>>> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h >>>> index e20867e..84db125 100644 >>>> --- a/include/drm/drm_crtc.h >>>> +++ b/include/drm/drm_crtc.h >>>> @@ -29,6 +29,7 @@ >>>> #include <linux/spinlock.h> >>>> #include <linux/types.h> >>>> #include <linux/idr.h> >>>> +#include <linux/videodev2.h> /* for plane formats */ >>>> >>>> #include <linux/fb.h> >>>> >>>> @@ -246,6 +247,7 @@ struct drm_framebuffer { >>>> unsigned int depth; >>>> int bits_per_pixel; >>>> int flags; >>>> + uint32_t pixel_format; /* fourcc format */ >>>> struct list_head filp_head; >>>> /* if you are using the helper */ >>>> void *helper_private; >>>> @@ -619,7 +621,7 @@ struct drm_mode_set { >>>> * struct drm_mode_config_funcs - configure CRTCs for a given screen layout >>>> */ >>>> struct drm_mode_config_funcs { >>>> - struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); >>>> + struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd); >>>> void (*output_poll_changed)(struct drm_device *dev); >>>> }; >>>> >>>> @@ -837,6 +839,9 @@ extern int drm_mode_cursor_ioctl(struct drm_device *dev, >>>> void *data, struct drm_file *file_priv); >>>> extern int drm_mode_addfb(struct drm_device *dev, >>>> void *data, struct drm_file *file_priv); >>>> +extern int drm_mode_addfb2(struct drm_device *dev, >>>> + void *data, struct drm_file *file_priv); >>>> +extern uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); >>>> extern int drm_mode_rmfb(struct drm_device *dev, >>>> void *data, struct drm_file *file_priv); >>>> extern int drm_mode_getfb(struct drm_device *dev, >>>> diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h >>>> index 73b0712..b4abb33 100644 >>>> --- a/include/drm/drm_crtc_helper.h >>>> +++ b/include/drm/drm_crtc_helper.h >>>> @@ -116,8 +116,10 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); >>>> >>>> extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode); >>>> >>>> +extern void drm_helper_get_fb_bpp_depth(uint32_t format, unsigned int *depth, >>>> + int *bpp); >>>> extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, >>>> - struct drm_mode_fb_cmd *mode_cmd); >>>> + struct drm_mode_fb_cmd2 *mode_cmd); >>>> >>>> static inline void drm_crtc_helper_add(struct drm_crtc *crtc, >>>> const struct drm_crtc_helper_funcs *funcs) >>>> diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h >>>> index 07711b0..3cfa160 100644 >>>> --- a/include/drm/drm_mode.h >>>> +++ b/include/drm/drm_mode.h >>>> @@ -27,6 +27,8 @@ >>>> #ifndef _DRM_MODE_H >>>> #define _DRM_MODE_H >>>> >>>> +#include <linux/videodev2.h> >>>> + >>>> #define DRM_DISPLAY_INFO_LEN 32 >>>> #define DRM_CONNECTOR_NAME_LEN 32 >>>> #define DRM_DISPLAY_MODE_LEN 32 >>>> @@ -136,7 +138,6 @@ struct drm_mode_set_plane { >>>> }; >>>> >>>> struct drm_mode_get_plane { >>>> - __u64 format_type_ptr; >>>> __u32 plane_id; >>>> >>>> __u32 crtc_id; >>>> @@ -146,6 +147,7 @@ struct drm_mode_get_plane { >>>> __u32 gamma_size; >>>> >>>> __u32 count_format_types; >>>> + __u64 format_type_ptr; >>>> }; >>>> >>>> struct drm_mode_get_plane_res { >>>> @@ -262,6 +264,30 @@ struct drm_mode_fb_cmd { >>>> __u32 handle; >>>> }; >>>> >>>> +struct drm_mode_fb_cmd2 { >>>> + __u32 fb_id; >>>> + __u32 width, height; >>>> + __u32 pixel_format; /* fourcc code from videodev2.h */ >>>> + >>>> + /* >>>> + * In case of planar formats, this ioctl allows one >>>> + * buffer object with offets and pitches per plane. >>>> + * The pitch and offset order is dictated by the fourcc, >>>> + * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: >>>> + * >>>> + * YUV 4:2:0 image with a plane of 8 bit Y samples >>>> + * followed by an interleaved U/V plane containing >>>> + * 8 bit 2x2 subsampled colour difference samples. >>>> + * >>>> + * So it would consist of Y as offset[0] and UV as >>>> + * offeset[1]. Note that offset[0] will generally >>>> + * be 0. >>>> + */ >>>> + __u32 handle; >>>> + __u32 pitches[4]; /* pitch for each plane */ >>>> + __u32 offsets[4]; /* offset of each plane */ >>>> +}; >>>> + >>>> #define DRM_MODE_FB_DIRTY_ANNOTATE_COPY 0x01 >>>> #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02 >>>> #define DRM_MODE_FB_DIRTY_FLAGS 0x03 >>>> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h >>>> index fca24cc..6da4ab4 100644 >>>> --- a/include/linux/videodev2.h >>>> +++ b/include/linux/videodev2.h >>>> @@ -412,6 +412,7 @@ struct v4l2_pix_format { >>>> #define V4L2_PIX_FMT_KONICA420 v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */ >>>> #define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ >>>> #define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */ >>>> +#define V4L2_PIX_FMT_INTC_RGB30 v4l2_fourcc('R', 'G', 'B', '0') /* RGB x:10:10:10 */ >>>> >>>> /* >>>> * F O R M A T E N U M E R A T I O N >>>> -- >>>> 1.7.4.1 >>>> >>>> _______________________________________________ >>>> dri-devel mailing list >>>> dri-devel@xxxxxxxxxxxxxxxxxxxxx >>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel >>>> >>> _______________________________________________ >>> dri-devel mailing list >>> dri-devel@xxxxxxxxxxxxxxxxxxxxx >>> http://lists.freedesktop.org/mailman/listinfo/dri-devel >>> >> > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel