linux/drivers/gpu/drm/xylon/xylon_fb.c
<<
>>
Prefs
   1/*
   2 * Xylon DRM driver fb functions
   3 *
   4 * Copyright (C) 2014 Xylon d.o.o.
   5 * Author: Davor Joja <davor.joja@logicbricks.com>
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <drm/drmP.h>
  18#include <drm/drm_crtc_helper.h>
  19#include <drm/drm_gem.h>
  20
  21#include "xylon_crtc.h"
  22#include "xylon_drv.h"
  23#include "xylon_fb.h"
  24#include "xylon_fbdev.h"
  25
  26#define fb_to_xylon_drm_fb(x) container_of(x, struct xylon_drm_fb, fb)
  27
  28struct xylon_drm_fb {
  29        struct drm_framebuffer fb;
  30        struct drm_gem_object *obj;
  31};
  32
  33static void xylon_drm_fb_destroy(struct drm_framebuffer *fb)
  34{
  35        struct drm_gem_object *obj;
  36        struct xylon_drm_fb *xfb = fb_to_xylon_drm_fb(fb);
  37
  38        drm_framebuffer_cleanup(fb);
  39
  40        obj = xfb->obj;
  41        if (obj)
  42                drm_gem_object_unreference_unlocked(obj);
  43
  44        kfree(xfb);
  45}
  46
  47static int xylon_drm_fb_create_handle(struct drm_framebuffer *fb,
  48                                      struct drm_file *file_priv,
  49                                      unsigned int *handle)
  50{
  51        struct xylon_drm_fb *xfb = fb_to_xylon_drm_fb(fb);
  52
  53        return drm_gem_handle_create(file_priv, xfb->obj, handle);
  54}
  55
  56static struct drm_framebuffer_funcs xylon_fb_funcs = {
  57        .destroy = xylon_drm_fb_destroy,
  58        .create_handle = xylon_drm_fb_create_handle,
  59};
  60
  61struct drm_framebuffer *xylon_drm_fb_init(struct drm_device *dev,
  62                                          struct drm_mode_fb_cmd2 *mode_cmd,
  63                                          struct drm_gem_object *obj)
  64{
  65        struct drm_framebuffer *fb;
  66        struct xylon_drm_fb *xfb;
  67        int ret;
  68
  69        xfb = kzalloc(sizeof(*xfb), GFP_KERNEL);
  70        if (!xfb) {
  71                DRM_ERROR("failed allocate framebuffer\n");
  72                return ERR_PTR(-ENOMEM);
  73        }
  74
  75        xfb->obj = obj;
  76
  77        fb = &xfb->fb;
  78
  79        drm_helper_mode_fill_fb_struct(fb, mode_cmd);
  80
  81        ret = drm_framebuffer_init(dev, fb, &xylon_fb_funcs);
  82        if (ret) {
  83                DRM_ERROR("failed framebuffer init\n");
  84                goto err;
  85        }
  86
  87        return fb;
  88
  89err:
  90        xylon_drm_fb_destroy(fb);
  91
  92        return ERR_PTR(ret);
  93}
  94
  95struct drm_gem_object *xylon_drm_fb_get_gem_obj(struct drm_framebuffer *fb)
  96{
  97        struct xylon_drm_fb *xfb = fb_to_xylon_drm_fb(fb);
  98
  99        return xfb->obj;
 100}
 101
 102static struct drm_framebuffer *
 103xylon_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
 104                    struct drm_mode_fb_cmd2 *mode_cmd)
 105{
 106        struct drm_gem_object *obj;
 107        struct xylon_drm_device *xdev = dev->dev_private;
 108        bool res;
 109
 110        res = xylon_drm_crtc_check_format(xdev->crtc, mode_cmd->pixel_format);
 111        if (!res) {
 112                DRM_ERROR("unsupported pixel format %08x\n",
 113                          mode_cmd->pixel_format);
 114                return ERR_PTR(-EINVAL);
 115        }
 116
 117        obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
 118        if (!obj)
 119                return ERR_PTR(-EINVAL);
 120
 121        return xylon_drm_fb_init(dev, mode_cmd, obj);
 122}
 123
 124static void xylon_drm_output_poll_changed(struct drm_device *dev)
 125{
 126        struct xylon_drm_device *xdev = dev->dev_private;
 127
 128        xylon_drm_fbdev_hotplug_event(xdev->fbdev);
 129}
 130
 131static const struct drm_mode_config_funcs xylon_drm_mode_config_funcs = {
 132        .fb_create = xylon_drm_fb_create,
 133        .output_poll_changed = xylon_drm_output_poll_changed,
 134};
 135
 136void xylon_drm_mode_config_init(struct drm_device *dev)
 137{
 138        struct xylon_drm_device *xdev = dev->dev_private;
 139
 140        xylon_drm_crtc_get_fix_parameters(xdev->crtc);
 141
 142        dev->mode_config.funcs = &xylon_drm_mode_config_funcs;
 143}
 144