/*
 * Copyright (C) 2013 Google, Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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.
 *
 */

#include <linux/vmalloc.h>

#include <video/adf.h>
#include <video/adf_client.h>
#include <video/adf_fbdev.h>
#include <video/adf_format.h>

#include "adf.h"

struct adf_fbdev_format {
	u32 fourcc;
	u32 bpp;
	u32 r_length;
	u32 g_length;
	u32 b_length;
	u32 a_length;
	u32 r_offset;
	u32 g_offset;
	u32 b_offset;
	u32 a_offset;
};

static const struct adf_fbdev_format format_table[] = {
	{DRM_FORMAT_RGB332, 8, 3, 3, 2, 0, 5, 2, 0, 0},
	{DRM_FORMAT_BGR233, 8, 3, 3, 2, 0, 0, 3, 5, 0},

	{DRM_FORMAT_XRGB4444, 16, 4, 4, 4, 0, 8, 4, 0, 0},
	{DRM_FORMAT_XBGR4444, 16, 4, 4, 4, 0, 0, 4, 8, 0},
	{DRM_FORMAT_RGBX4444, 16, 4, 4, 4, 0, 12, 8, 4, 0},
	{DRM_FORMAT_BGRX4444, 16, 4, 4, 4, 0, 0, 4, 8, 0},

	{DRM_FORMAT_ARGB4444, 16, 4, 4, 4, 4, 8, 4, 0, 12},
	{DRM_FORMAT_ABGR4444, 16, 4, 4, 4, 4, 0, 4, 8, 12},
	{DRM_FORMAT_RGBA4444, 16, 4, 4, 4, 4, 12, 8, 4, 0},
	{DRM_FORMAT_BGRA4444, 16, 4, 4, 4, 4, 0, 4, 8, 0},

	{DRM_FORMAT_XRGB1555, 16, 5, 5, 5, 0, 10, 5, 0, 0},
	{DRM_FORMAT_XBGR1555, 16, 5, 5, 5, 0, 0, 5, 10, 0},
	{DRM_FORMAT_RGBX5551, 16, 5, 5, 5, 0, 11, 6, 1, 0},
	{DRM_FORMAT_BGRX5551, 16, 5, 5, 5, 0, 1, 6, 11, 0},

	{DRM_FORMAT_ARGB1555, 16, 5, 5, 5, 1, 10, 5, 0, 15},
	{DRM_FORMAT_ABGR1555, 16, 5, 5, 5, 1, 0, 5, 10, 15},
	{DRM_FORMAT_RGBA5551, 16, 5, 5, 5, 1, 11, 6, 1, 0},
	{DRM_FORMAT_BGRA5551, 16, 5, 5, 5, 1, 1, 6, 11, 0},

	{DRM_FORMAT_RGB565, 16, 5, 6, 5, 0, 11, 5, 0, 0},
	{DRM_FORMAT_BGR565, 16, 5, 6, 5, 0, 0, 5, 11, 0},

	{DRM_FORMAT_RGB888, 24, 8, 8, 8, 0, 16, 8, 0, 0},
	{DRM_FORMAT_BGR888, 24, 8, 8, 8, 0, 0, 8, 16, 0},

	{DRM_FORMAT_XRGB8888, 32, 8, 8, 8, 0, 16, 8, 0, 0},
	{DRM_FORMAT_XBGR8888, 32, 8, 8, 8, 0, 0, 8, 16, 0},
	{DRM_FORMAT_RGBX8888, 32, 8, 8, 8, 0, 24, 16, 8, 0},
	{DRM_FORMAT_BGRX8888, 32, 8, 8, 8, 0, 8, 16, 24, 0},

	{DRM_FORMAT_ARGB8888, 32, 8, 8, 8, 8, 16, 8, 0, 24},
	{DRM_FORMAT_ABGR8888, 32, 8, 8, 8, 8, 0, 8, 16, 24},
	{DRM_FORMAT_RGBA8888, 32, 8, 8, 8, 8, 24, 16, 8, 0},
	{DRM_FORMAT_BGRA8888, 32, 8, 8, 8, 8, 8, 16, 24, 0},

	{DRM_FORMAT_XRGB2101010, 32, 10, 10, 10, 0, 20, 10, 0, 0},
	{DRM_FORMAT_XBGR2101010, 32, 10, 10, 10, 0, 0, 10, 20, 0},
	{DRM_FORMAT_RGBX1010102, 32, 10, 10, 10, 0, 22, 12, 2, 0},
	{DRM_FORMAT_BGRX1010102, 32, 10, 10, 10, 0, 2, 12, 22, 0},

	{DRM_FORMAT_ARGB2101010, 32, 10, 10, 10, 2, 20, 10, 0, 30},
	{DRM_FORMAT_ABGR2101010, 32, 10, 10, 10, 2, 0, 10, 20, 30},
	{DRM_FORMAT_RGBA1010102, 32, 10, 10, 10, 2, 22, 12, 2, 0},
	{DRM_FORMAT_BGRA1010102, 32, 10, 10, 10, 2, 2, 12, 22, 0},
};

static u32 drm_fourcc_from_fb_var(struct fb_var_screeninfo *var)
{
	size_t i;
	for (i = 0; i < ARRAY_SIZE(format_table); i++) {
		const struct adf_fbdev_format *f = &format_table[i];
		if (var->red.length == f->r_length &&
			var->red.offset == f->r_offset &&
			var->green.length == f->g_length &&
			var->green.offset == f->g_offset &&
			var->blue.length == f->b_length &&
			var->blue.offset == f->b_offset &&
			var->transp.length == f->a_length &&
			(var->transp.length == 0 ||
					var->transp.offset == f->a_offset))
			return f->fourcc;
	}

	return 0;
}

static const struct adf_fbdev_format *fbdev_format_info(u32 format)
{
	size_t i;
	for (i = 0; i < ARRAY_SIZE(format_table); i++) {
		const struct adf_fbdev_format *f = &format_table[i];
		if (f->fourcc == format)
			return f;
	}

	BUG();
}

void adf_modeinfo_to_fb_videomode(const struct drm_mode_modeinfo *mode,
		struct fb_videomode *vmode)
{
	memset(vmode, 0, sizeof(*vmode));

	vmode->refresh = mode->vrefresh;

	vmode->xres = mode->hdisplay;
	vmode->yres = mode->vdisplay;

	vmode->pixclock = mode->clock ? KHZ2PICOS(mode->clock) : 0;
	vmode->left_margin = mode->htotal - mode->hsync_end;
	vmode->right_margin = mode->hsync_start - mode->hdisplay;
	vmode->upper_margin = mode->vtotal - mode->vsync_end;
	vmode->lower_margin = mode->vsync_start - mode->vdisplay;
	vmode->hsync_len = mode->hsync_end - mode->hsync_start;
	vmode->vsync_len = mode->vsync_end - mode->vsync_start;

	vmode->sync = 0;
	if (mode->flags | DRM_MODE_FLAG_PHSYNC)
		vmode->sync |= FB_SYNC_HOR_HIGH_ACT;
	if (mode->flags | DRM_MODE_FLAG_PVSYNC)
		vmode->sync |= FB_SYNC_VERT_HIGH_ACT;
	if (mode->flags | DRM_MODE_FLAG_PCSYNC)
		vmode->sync |= FB_SYNC_COMP_HIGH_ACT;
	if (mode->flags | DRM_MODE_FLAG_BCAST)
		vmode->sync |= FB_SYNC_BROADCAST;

	vmode->vmode = 0;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		vmode->vmode |= FB_VMODE_INTERLACED;
	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
		vmode->vmode |= FB_VMODE_DOUBLE;
}
EXPORT_SYMBOL(adf_modeinfo_to_fb_videomode);

void adf_modeinfo_from_fb_videomode(const struct fb_videomode *vmode,
		struct drm_mode_modeinfo *mode)
{
	memset(mode, 0, sizeof(*mode));

	mode->hdisplay = vmode->xres;
	mode->hsync_start = mode->hdisplay + vmode->right_margin;
	mode->hsync_end = mode->hsync_start + vmode->hsync_len;
	mode->htotal = mode->hsync_end + vmode->left_margin;

	mode->vdisplay = vmode->yres;
	mode->vsync_start = mode->vdisplay + vmode->lower_margin;
	mode->vsync_end = mode->vsync_start + vmode->vsync_len;
	mode->vtotal = mode->vsync_end + vmode->upper_margin;

	mode->clock = vmode->pixclock ? PICOS2KHZ(vmode->pixclock) : 0;

	mode->flags = 0;
	if (vmode->sync & FB_SYNC_HOR_HIGH_ACT)
		mode->flags |= DRM_MODE_FLAG_PHSYNC;
	if (vmode->sync & FB_SYNC_VERT_HIGH_ACT)
		mode->flags |= DRM_MODE_FLAG_PVSYNC;
	if (vmode->sync & FB_SYNC_COMP_HIGH_ACT)
		mode->flags |= DRM_MODE_FLAG_PCSYNC;
	if (vmode->sync & FB_SYNC_BROADCAST)
		mode->flags |= DRM_MODE_FLAG_BCAST;
	if (vmode->vmode & FB_VMODE_INTERLACED)
		mode->flags |= DRM_MODE_FLAG_INTERLACE;
	if (vmode->vmode & FB_VMODE_DOUBLE)
		mode->flags |= DRM_MODE_FLAG_DBLSCAN;

	if (vmode->refresh)
		mode->vrefresh = vmode->refresh;
	else
		adf_modeinfo_set_vrefresh(mode);

	if (vmode->name)
		strlcpy(mode->name, vmode->name, sizeof(mode->name));
	else
		adf_modeinfo_set_name(mode);
}
EXPORT_SYMBOL(adf_modeinfo_from_fb_videomode);

static int adf_fbdev_post(struct adf_fbdev *fbdev)
{
	struct adf_buffer buf;
	struct sync_fence *complete_fence;
	int ret = 0;

	memset(&buf, 0, sizeof(buf));
	buf.overlay_engine = fbdev->eng;
	buf.w = fbdev->info->var.xres;
	buf.h = fbdev->info->var.yres;
	buf.format = fbdev->format;
	buf.dma_bufs[0] = fbdev->dma_buf;
	buf.offset[0] = fbdev->offset +
			fbdev->info->var.yoffset * fbdev->pitch +
			fbdev->info->var.xoffset *
			(fbdev->info->var.bits_per_pixel / 8);
	buf.pitch[0] = fbdev->pitch;
	buf.n_planes = 1;

	complete_fence = adf_interface_simple_post(fbdev->intf, &buf);
	if (IS_ERR(complete_fence)) {
		ret = PTR_ERR(complete_fence);
		goto done;
	}

	sync_fence_put(complete_fence);
done:
	return ret;
}

static const u16 vga_palette[][3] = {
	{0x0000, 0x0000, 0x0000},
	{0x0000, 0x0000, 0xAAAA},
	{0x0000, 0xAAAA, 0x0000},
	{0x0000, 0xAAAA, 0xAAAA},
	{0xAAAA, 0x0000, 0x0000},
	{0xAAAA, 0x0000, 0xAAAA},
	{0xAAAA, 0x5555, 0x0000},
	{0xAAAA, 0xAAAA, 0xAAAA},
	{0x5555, 0x5555, 0x5555},
	{0x5555, 0x5555, 0xFFFF},
	{0x5555, 0xFFFF, 0x5555},
	{0x5555, 0xFFFF, 0xFFFF},
	{0xFFFF, 0x5555, 0x5555},
	{0xFFFF, 0x5555, 0xFFFF},
	{0xFFFF, 0xFFFF, 0x5555},
	{0xFFFF, 0xFFFF, 0xFFFF},
};

static int adf_fb_alloc(struct adf_fbdev *fbdev)
{
	int ret;

	ret = adf_interface_simple_buffer_alloc(fbdev->intf,
			fbdev->default_xres_virtual,
			fbdev->default_yres_virtual,
			fbdev->default_format,
			&fbdev->dma_buf, &fbdev->offset, &fbdev->pitch);
	if (ret < 0) {
		dev_err(fbdev->info->dev, "allocating fb failed: %d\n", ret);
		return ret;
	}

	fbdev->vaddr = dma_buf_vmap(fbdev->dma_buf);
	if (!fbdev->vaddr) {
		ret = -ENOMEM;
		dev_err(fbdev->info->dev, "vmapping fb failed\n");
		goto err_vmap;
	}
	fbdev->info->fix.line_length = fbdev->pitch;
	fbdev->info->var.xres_virtual = fbdev->default_xres_virtual;
	fbdev->info->var.yres_virtual = fbdev->default_yres_virtual;
	fbdev->info->fix.smem_len = fbdev->dma_buf->size;
	fbdev->info->screen_base = fbdev->vaddr;

	return 0;

err_vmap:
	dma_buf_put(fbdev->dma_buf);
	return ret;
}

static void adf_fb_destroy(struct adf_fbdev *fbdev)
{
	dma_buf_vunmap(fbdev->dma_buf, fbdev->vaddr);
	dma_buf_put(fbdev->dma_buf);
}

static void adf_fbdev_set_format(struct adf_fbdev *fbdev, u32 format)
{
	size_t i;
	const struct adf_fbdev_format *info = fbdev_format_info(format);
	for (i = 0; i < ARRAY_SIZE(vga_palette); i++) {
		u16 r = vga_palette[i][0];
		u16 g = vga_palette[i][1];
		u16 b = vga_palette[i][2];

		r >>= (16 - info->r_length);
		g >>= (16 - info->g_length);
		b >>= (16 - info->b_length);

		fbdev->pseudo_palette[i] =
			(r << info->r_offset) |
			(g << info->g_offset) |
			(b << info->b_offset);

		if (info->a_length) {
			u16 a = BIT(info->a_length) - 1;
			fbdev->pseudo_palette[i] |= (a << info->a_offset);
		}
	}

	fbdev->info->var.bits_per_pixel = adf_format_bpp(format);
	fbdev->info->var.red.length = info->r_length;
	fbdev->info->var.red.offset = info->r_offset;
	fbdev->info->var.green.length = info->g_length;
	fbdev->info->var.green.offset = info->g_offset;
	fbdev->info->var.blue.length = info->b_length;
	fbdev->info->var.blue.offset = info->b_offset;
	fbdev->info->var.transp.length = info->a_length;
	fbdev->info->var.transp.offset = info->a_offset;
	fbdev->format = format;
}

static void adf_fbdev_fill_modelist(struct adf_fbdev *fbdev)
{
	struct drm_mode_modeinfo *modelist;
	struct fb_videomode fbmode;
	size_t n_modes, i;
	int ret = 0;

	n_modes = adf_interface_modelist(fbdev->intf, NULL, 0);
	modelist = kzalloc(sizeof(modelist[0]) * n_modes, GFP_KERNEL);
	if (!modelist) {
		dev_warn(fbdev->info->dev, "allocating new modelist failed; keeping old modelist\n");
		return;
	}
	adf_interface_modelist(fbdev->intf, modelist, n_modes);

	fb_destroy_modelist(&fbdev->info->modelist);

	for (i = 0; i < n_modes; i++) {
		adf_modeinfo_to_fb_videomode(&modelist[i], &fbmode);
		ret = fb_add_videomode(&fbmode, &fbdev->info->modelist);
		if (ret < 0)
			dev_warn(fbdev->info->dev, "adding mode %s to modelist failed: %d\n",
					modelist[i].name, ret);
	}

	kfree(modelist);
}

/**
 * adf_fbdev_open - default implementation of fbdev open op
 */
int adf_fbdev_open(struct fb_info *info, int user)
{
	struct adf_fbdev *fbdev = info->par;
	int ret;

	if (!fbdev->open) {
		struct drm_mode_modeinfo mode;
		struct fb_videomode fbmode;
		struct adf_device *dev = adf_interface_parent(fbdev->intf);

		ret = adf_device_attach(dev, fbdev->eng, fbdev->intf);
		if (ret < 0 && ret != -EALREADY)
			return ret;

		ret = adf_fb_alloc(fbdev);
		if (ret < 0)
			return ret;

		adf_interface_current_mode(fbdev->intf, &mode);
		adf_modeinfo_to_fb_videomode(&mode, &fbmode);
		fb_videomode_to_var(&fbdev->info->var, &fbmode);

		adf_fbdev_set_format(fbdev, fbdev->default_format);
		adf_fbdev_fill_modelist(fbdev);
	}

	ret = adf_fbdev_post(fbdev);
	if (ret < 0) {
		if (!fbdev->open)
			adf_fb_destroy(fbdev);
		return ret;
	}

	fbdev->open = true;
	return 0;
}
EXPORT_SYMBOL(adf_fbdev_open);

/**
 * adf_fbdev_release - default implementation of fbdev release op
 */
int adf_fbdev_release(struct fb_info *info, int user)
{
	struct adf_fbdev *fbdev = info->par;
	adf_fb_destroy(fbdev);
	fbdev->open = false;
	return 0;
}
EXPORT_SYMBOL(adf_fbdev_release);

/**
 * adf_fbdev_check_var - default implementation of fbdev check_var op
 */
int adf_fbdev_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
	struct adf_fbdev *fbdev = info->par;
	bool valid_format = true;
	u32 format = drm_fourcc_from_fb_var(var);
	u32 pitch = var->xres_virtual * var->bits_per_pixel / 8;

	if (!format) {
		dev_dbg(info->dev, "%s: unrecognized format\n", __func__);
		valid_format = false;
	}

	if (valid_format && var->grayscale) {
		dev_dbg(info->dev, "%s: grayscale modes not supported\n",
				__func__);
		valid_format = false;
	}

	if (valid_format && var->nonstd) {
		dev_dbg(info->dev, "%s: nonstandard formats not supported\n",
				__func__);
		valid_format = false;
	}

	if (valid_format && !adf_overlay_engine_supports_format(fbdev->eng,
			format)) {
		char format_str[ADF_FORMAT_STR_SIZE];
		adf_format_str(format, format_str);
		dev_dbg(info->dev, "%s: format %s not supported by overlay engine %s\n",
				__func__, format_str, fbdev->eng->base.name);
		valid_format = false;
	}

	if (valid_format && pitch > fbdev->pitch) {
		dev_dbg(info->dev, "%s: fb pitch too small for var (pitch = %u, xres_virtual = %u, bits_per_pixel = %u)\n",
				__func__, fbdev->pitch, var->xres_virtual,
				var->bits_per_pixel);
		valid_format = false;
	}

	if (valid_format && var->yres_virtual > fbdev->default_yres_virtual) {
		dev_dbg(info->dev, "%s: fb height too small for var (h = %u, yres_virtual = %u)\n",
				__func__, fbdev->default_yres_virtual,
				var->yres_virtual);
		valid_format = false;
	}

	if (valid_format) {
		var->activate = info->var.activate;
		var->height = info->var.height;
		var->width = info->var.width;
		var->accel_flags = info->var.accel_flags;
		var->rotate = info->var.rotate;
		var->colorspace = info->var.colorspace;
		/* userspace can't change these */
	} else {
		/* if any part of the format is invalid then fixing it up is
		   impractical, so save just the modesetting bits and
		   overwrite everything else */
		struct fb_videomode mode;
		fb_var_to_videomode(&mode, var);
		memcpy(var, &info->var, sizeof(*var));
		fb_videomode_to_var(var, &mode);
	}

	return 0;
}
EXPORT_SYMBOL(adf_fbdev_check_var);

/**
 * adf_fbdev_set_par - default implementation of fbdev set_par op
 */
int adf_fbdev_set_par(struct fb_info *info)
{
	struct adf_fbdev *fbdev = info->par;
	struct adf_interface *intf = fbdev->intf;
	struct fb_videomode vmode;
	struct drm_mode_modeinfo mode;
	int ret;
	u32 format = drm_fourcc_from_fb_var(&info->var);

	fb_var_to_videomode(&vmode, &info->var);
	adf_modeinfo_from_fb_videomode(&vmode, &mode);
	ret = adf_interface_set_mode(intf, &mode);
	if (ret < 0)
		return ret;

	ret = adf_fbdev_post(fbdev);
	if (ret < 0)
		return ret;

	if (format != fbdev->format)
		adf_fbdev_set_format(fbdev, format);

	return 0;
}
EXPORT_SYMBOL(adf_fbdev_set_par);

/**
 * adf_fbdev_blank - default implementation of fbdev blank op
 */
int adf_fbdev_blank(int blank, struct fb_info *info)
{
	struct adf_fbdev *fbdev = info->par;
	struct adf_interface *intf = fbdev->intf;
	u8 dpms_state;

	switch (blank) {
	case FB_BLANK_UNBLANK:
		dpms_state = DRM_MODE_DPMS_ON;
		break;
	case FB_BLANK_NORMAL:
		dpms_state = DRM_MODE_DPMS_STANDBY;
		break;
	case FB_BLANK_VSYNC_SUSPEND:
		dpms_state = DRM_MODE_DPMS_SUSPEND;
		break;
	case FB_BLANK_HSYNC_SUSPEND:
		dpms_state = DRM_MODE_DPMS_STANDBY;
		break;
	case FB_BLANK_POWERDOWN:
		dpms_state = DRM_MODE_DPMS_OFF;
		break;
	default:
		return -EINVAL;
	}

	return adf_interface_blank(intf, dpms_state);
}
EXPORT_SYMBOL(adf_fbdev_blank);

/**
 * adf_fbdev_pan_display - default implementation of fbdev pan_display op
 */
int adf_fbdev_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
	struct adf_fbdev *fbdev = info->par;
	return adf_fbdev_post(fbdev);
}
EXPORT_SYMBOL(adf_fbdev_pan_display);

/**
 * adf_fbdev_mmap - default implementation of fbdev mmap op
 */
int adf_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
	struct adf_fbdev *fbdev = info->par;

	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
	return dma_buf_mmap(fbdev->dma_buf, vma, 0);
}
EXPORT_SYMBOL(adf_fbdev_mmap);

/**
 * adf_fbdev_init - initialize helper to wrap ADF device in fbdev API
 *
 * @fbdev: the fbdev helper
 * @interface: the ADF interface that will display the framebuffer
 * @eng: the ADF overlay engine that will scan out the framebuffer
 * @xres_virtual: the virtual width of the framebuffer
 * @yres_virtual: the virtual height of the framebuffer
 * @format: the format of the framebuffer
 * @fbops: the device's fbdev ops
 * @fmt: formatting for the framebuffer identification string
 * @...: variable arguments
 *
 * @format must be a standard, non-indexed RGB format, i.e.,
 * adf_format_is_rgb(@format) && @format != @DRM_FORMAT_C8.
 *
 * Returns 0 on success or -errno on failure.
 */
int adf_fbdev_init(struct adf_fbdev *fbdev, struct adf_interface *interface,
		struct adf_overlay_engine *eng,
		u16 xres_virtual, u16 yres_virtual, u32 format,
		struct fb_ops *fbops, const char *fmt, ...)
{
	struct adf_device *parent = adf_interface_parent(interface);
	struct device *dev = &parent->base.dev;
	u16 width_mm, height_mm;
	va_list args;
	int ret;

	if (!adf_format_is_rgb(format) ||
			format == DRM_FORMAT_C8) {
		dev_err(dev, "fbdev helper does not support format %u\n",
				format);
		return -EINVAL;
	}

	memset(fbdev, 0, sizeof(*fbdev));
	fbdev->intf = interface;
	fbdev->eng = eng;
	fbdev->info = framebuffer_alloc(0, dev);
	if (!fbdev->info) {
		dev_err(dev, "allocating framebuffer device failed\n");
		return -ENOMEM;
	}
	fbdev->default_xres_virtual = xres_virtual;
	fbdev->default_yres_virtual = yres_virtual;
	fbdev->default_format = format;

	fbdev->info->flags = FBINFO_FLAG_DEFAULT;
	ret = adf_interface_get_screen_size(interface, &width_mm, &height_mm);
	if (ret < 0) {
		width_mm = 0;
		height_mm = 0;
	}
	fbdev->info->var.width = width_mm;
	fbdev->info->var.height = height_mm;
	fbdev->info->var.activate = FB_ACTIVATE_VBL;
	va_start(args, fmt);
	vsnprintf(fbdev->info->fix.id, sizeof(fbdev->info->fix.id), fmt, args);
	va_end(args);
	fbdev->info->fix.type = FB_TYPE_PACKED_PIXELS;
	fbdev->info->fix.visual = FB_VISUAL_TRUECOLOR;
	fbdev->info->fix.xpanstep = 1;
	fbdev->info->fix.ypanstep = 1;
	INIT_LIST_HEAD(&fbdev->info->modelist);
	fbdev->info->fbops = fbops;
	fbdev->info->pseudo_palette = fbdev->pseudo_palette;
	fbdev->info->par = fbdev;

	ret = register_framebuffer(fbdev->info);
	if (ret < 0) {
		dev_err(dev, "registering framebuffer failed: %d\n", ret);
		return ret;
	}

	return 0;
}
EXPORT_SYMBOL(adf_fbdev_init);

/**
 * adf_fbdev_destroy - destroy helper to wrap ADF device in fbdev API
 *
 * @fbdev: the fbdev helper
 */
void adf_fbdev_destroy(struct adf_fbdev *fbdev)
{
	unregister_framebuffer(fbdev->info);
	if (WARN_ON(fbdev->open))
		adf_fb_destroy(fbdev);
	framebuffer_release(fbdev->info);
}
EXPORT_SYMBOL(adf_fbdev_destroy);
