Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/* exynos_drm_fbdev.c
  3 *
  4 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  5 * Authors:
  6 *	Inki Dae <inki.dae@samsung.com>
  7 *	Joonyoung Shim <jy0922.shim@samsung.com>
  8 *	Seung-Woo Kim <sw0312.kim@samsung.com>
  9 */
 10
 11#include <linux/fb.h>
 12
 13#include <drm/drm_crtc_helper.h>
 14#include <drm/drm_drv.h>
 15#include <drm/drm_fb_helper.h>
 16#include <drm/drm_framebuffer.h>
 17#include <drm/drm_gem_framebuffer_helper.h>
 18#include <drm/drm_prime.h>
 19#include <drm/exynos_drm.h>
 20
 21#include "exynos_drm_drv.h"
 22#include "exynos_drm_fb.h"
 23#include "exynos_drm_fbdev.h"
 24
 25#define MAX_CONNECTOR		4
 26
 27static int exynos_drm_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 28{
 29	struct drm_fb_helper *helper = info->par;
 30	struct drm_gem_object *obj = drm_gem_fb_get_obj(helper->fb, 0);
 31
 32	return drm_gem_prime_mmap(obj, vma);
 33}
 34
 35static void exynos_drm_fb_destroy(struct fb_info *info)
 36{
 37	struct drm_fb_helper *fb_helper = info->par;
 38	struct drm_framebuffer *fb = fb_helper->fb;
 39
 40	drm_fb_helper_fini(fb_helper);
 41
 42	drm_framebuffer_remove(fb);
 43
 44	drm_client_release(&fb_helper->client);
 45	drm_fb_helper_unprepare(fb_helper);
 46	kfree(fb_helper);
 47}
 48
 49static const struct fb_ops exynos_drm_fb_ops = {
 50	.owner		= THIS_MODULE,
 51	__FB_DEFAULT_DMAMEM_OPS_RDWR,
 52	DRM_FB_HELPER_DEFAULT_OPS,
 53	__FB_DEFAULT_DMAMEM_OPS_DRAW,
 54	.fb_mmap        = exynos_drm_fb_mmap,
 55	.fb_destroy	= exynos_drm_fb_destroy,
 56};
 57
 58static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 59				   struct drm_fb_helper_surface_size *sizes,
 60				   struct exynos_drm_gem *exynos_gem)
 61{
 62	struct fb_info *fbi;
 63	struct drm_framebuffer *fb = helper->fb;
 64	unsigned int size = fb->width * fb->height * fb->format->cpp[0];
 65	unsigned long offset;
 66
 67	fbi = drm_fb_helper_alloc_info(helper);
 68	if (IS_ERR(fbi)) {
 69		DRM_DEV_ERROR(to_dma_dev(helper->dev),
 70			      "failed to allocate fb info.\n");
 71		return PTR_ERR(fbi);
 72	}
 73
 74	fbi->fbops = &exynos_drm_fb_ops;
 75
 76	drm_fb_helper_fill_info(fbi, helper, sizes);
 77
 78	offset = fbi->var.xoffset * fb->format->cpp[0];
 79	offset += fbi->var.yoffset * fb->pitches[0];
 80
 81	fbi->flags |= FBINFO_VIRTFB;
 82	fbi->screen_buffer = exynos_gem->kvaddr + offset;
 83	fbi->screen_size = size;
 84	fbi->fix.smem_len = size;
 85
 86	return 0;
 87}
 88
 89static const struct drm_fb_helper_funcs exynos_drm_fbdev_helper_funcs = {
 90};
 91
 92int exynos_drm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
 93					struct drm_fb_helper_surface_size *sizes)
 94{
 95	struct exynos_drm_gem *exynos_gem;
 96	struct drm_device *dev = helper->dev;
 97	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
 98	unsigned long size;
 99	int ret;
100
101	DRM_DEV_DEBUG_KMS(dev->dev,
102			  "surface width(%d), height(%d) and bpp(%d\n",
103			  sizes->surface_width, sizes->surface_height,
104			  sizes->surface_bpp);
105
106	mode_cmd.width = sizes->surface_width;
107	mode_cmd.height = sizes->surface_height;
108	mode_cmd.pitches[0] = sizes->surface_width * (sizes->surface_bpp >> 3);
109	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
110							  sizes->surface_depth);
111
112	size = mode_cmd.pitches[0] * mode_cmd.height;
113
114	exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_WC, size, true);
115	if (IS_ERR(exynos_gem))
116		return PTR_ERR(exynos_gem);
117
118	helper->fb =
119		exynos_drm_framebuffer_init(dev, &mode_cmd, &exynos_gem, 1);
120	if (IS_ERR(helper->fb)) {
121		DRM_DEV_ERROR(dev->dev, "failed to create drm framebuffer.\n");
122		ret = PTR_ERR(helper->fb);
123		goto err_destroy_gem;
124	}
125	helper->funcs = &exynos_drm_fbdev_helper_funcs;
126
127	ret = exynos_drm_fbdev_update(helper, sizes, exynos_gem);
128	if (ret < 0)
129		goto err_destroy_framebuffer;
130
131	return 0;
132
133err_destroy_framebuffer:
134	drm_framebuffer_cleanup(helper->fb);
135	helper->fb = NULL;
136err_destroy_gem:
137	exynos_drm_gem_destroy(exynos_gem);
138	return ret;
139}