2 * drivers/staging/omapdrm/omap_fbdev.c
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Rob Clark <rob@ti.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "drm_fb_helper.h"
26 * fbdev funcs, to implement legacy fbdev interface on top of drm driver
29 #define to_omap_fbdev(x) container_of(x, struct omap_fbdev, base)
32 struct drm_fb_helper base;
33 struct drm_framebuffer *fb;
36 static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h);
38 static ssize_t omap_fbdev_write(struct fb_info *fbi, const char __user *buf,
39 size_t count, loff_t *ppos)
43 res = fb_sys_write(fbi, buf, count, ppos);
44 omap_fbdev_flush(fbi, 0, 0, fbi->var.xres, fbi->var.yres);
49 static void omap_fbdev_fillrect(struct fb_info *fbi,
50 const struct fb_fillrect *rect)
52 sys_fillrect(fbi, rect);
53 omap_fbdev_flush(fbi, rect->dx, rect->dy, rect->width, rect->height);
56 static void omap_fbdev_copyarea(struct fb_info *fbi,
57 const struct fb_copyarea *area)
59 sys_copyarea(fbi, area);
60 omap_fbdev_flush(fbi, area->dx, area->dy, area->width, area->height);
63 static void omap_fbdev_imageblit(struct fb_info *fbi,
64 const struct fb_image *image)
66 sys_imageblit(fbi, image);
67 omap_fbdev_flush(fbi, image->dx, image->dy,
68 image->width, image->height);
71 static struct fb_ops omap_fb_ops = {
74 /* Note: to properly handle manual update displays, we wrap the
75 * basic fbdev ops which write to the framebuffer
77 .fb_read = fb_sys_read,
78 .fb_write = omap_fbdev_write,
79 .fb_fillrect = omap_fbdev_fillrect,
80 .fb_copyarea = omap_fbdev_copyarea,
81 .fb_imageblit = omap_fbdev_imageblit,
83 .fb_check_var = drm_fb_helper_check_var,
84 .fb_set_par = drm_fb_helper_set_par,
85 .fb_pan_display = drm_fb_helper_pan_display,
86 .fb_blank = drm_fb_helper_blank,
87 .fb_setcmap = drm_fb_helper_setcmap,
89 .fb_debug_enter = drm_fb_helper_debug_enter,
90 .fb_debug_leave = drm_fb_helper_debug_leave,
93 static int omap_fbdev_create(struct drm_fb_helper *helper,
94 struct drm_fb_helper_surface_size *sizes)
96 struct omap_fbdev *fbdev = to_omap_fbdev(helper);
97 struct drm_device *dev = helper->dev;
98 struct drm_framebuffer *fb = NULL;
99 struct fb_info *fbi = NULL;
100 struct drm_mode_fb_cmd mode_cmd = {0};
103 int size, screen_width;
106 /* only doing ARGB32 since this is what is needed to alpha-blend
107 * with video overlays:
109 sizes->surface_bpp = 32;
110 sizes->surface_depth = 32;
112 DBG("create fbdev: %dx%d@%d", sizes->surface_width,
113 sizes->surface_height, sizes->surface_bpp);
115 mode_cmd.width = sizes->surface_width;
116 mode_cmd.height = sizes->surface_height;
118 mode_cmd.bpp = sizes->surface_bpp;
119 mode_cmd.depth = sizes->surface_depth;
121 fb = omap_framebuffer_init(dev, &mode_cmd, NULL);
123 dev_err(dev->dev, "failed to allocate fb\n");
128 mutex_lock(&dev->struct_mutex);
130 fbi = framebuffer_alloc(0, dev->dev);
132 dev_err(dev->dev, "failed to allocate fb info\n");
137 DBG("fbi=%p, dev=%p", fbi, dev);
144 fbi->flags = FBINFO_DEFAULT;
145 fbi->fbops = &omap_fb_ops;
147 strcpy(fbi->fix.id, MODULE_NAME);
149 ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
155 drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
156 drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
158 size = omap_framebuffer_get_buffer(fb, 0, 0,
159 &vaddr, &paddr, &screen_width);
161 dev->mode_config.fb_base = paddr;
163 fbi->screen_base = vaddr;
164 fbi->screen_size = size;
165 fbi->fix.smem_start = paddr;
166 fbi->fix.smem_len = size;
168 DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres);
169 DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height);
171 mutex_unlock(&dev->struct_mutex);
176 mutex_unlock(&dev->struct_mutex);
181 framebuffer_release(fbi);
183 fb->funcs->destroy(fb);
189 static void omap_crtc_fb_gamma_set(struct drm_crtc *crtc,
190 u16 red, u16 green, u16 blue, int regno)
192 DBG("fbdev: set gamma");
195 static void omap_crtc_fb_gamma_get(struct drm_crtc *crtc,
196 u16 *red, u16 *green, u16 *blue, int regno)
198 DBG("fbdev: get gamma");
201 static int omap_fbdev_probe(struct drm_fb_helper *helper,
202 struct drm_fb_helper_surface_size *sizes)
208 ret = omap_fbdev_create(helper, sizes);
216 static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
217 .gamma_set = omap_crtc_fb_gamma_set,
218 .gamma_get = omap_crtc_fb_gamma_get,
219 .fb_probe = omap_fbdev_probe,
222 static struct drm_fb_helper *get_fb(struct fb_info *fbi)
224 if (!fbi || strcmp(fbi->fix.id, MODULE_NAME)) {
225 /* these are not the fb's you're looking for */
231 /* flush an area of the framebuffer (in case of manual update display that
232 * is not automatically flushed)
234 static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h)
236 struct drm_fb_helper *helper = get_fb(fbi);
241 VERB("flush fbdev: %d,%d %dx%d, fbi=%p", x, y, w, h, fbi);
243 omap_framebuffer_flush(helper->fb, x, y, w, h);
246 /* initialize fbdev helper */
247 struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
249 struct omap_drm_private *priv = dev->dev_private;
250 struct omap_fbdev *fbdev = NULL;
251 struct drm_fb_helper *helper;
254 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
256 dev_err(dev->dev, "could not allocate fbdev\n");
260 helper = &fbdev->base;
262 helper->funcs = &omap_fb_helper_funcs;
264 ret = drm_fb_helper_init(dev, helper,
265 priv->num_crtcs, priv->num_connectors);
267 dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret);
271 drm_fb_helper_single_add_all_connectors(helper);
272 drm_fb_helper_initial_config(helper, 32);
274 priv->fbdev = helper;
283 void omap_fbdev_free(struct drm_device *dev)
285 struct omap_drm_private *priv = dev->dev_private;
286 struct drm_fb_helper *helper = priv->fbdev;
287 struct omap_fbdev *fbdev;
294 unregister_framebuffer(fbi);
295 framebuffer_release(fbi);
297 drm_fb_helper_fini(helper);
299 fbdev = to_omap_fbdev(priv->fbdev);