Linux Audio

Check our new training course

Loading...
v4.6
 
  1/*
  2 * Copyright (C) 2012 Russell King
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 as
  6 * published by the Free Software Foundation.
  7 */
  8#include <drm/drmP.h>
  9#include <drm/drm_crtc_helper.h>
 10#include <drm/drm_fb_helper.h>
 
 
 
 11#include "armada_drm.h"
 12#include "armada_fb.h"
 13#include "armada_gem.h"
 14#include "armada_hw.h"
 15
 16static void armada_fb_destroy(struct drm_framebuffer *fb)
 17{
 18	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
 19
 20	drm_framebuffer_cleanup(&dfb->fb);
 21	drm_gem_object_unreference_unlocked(&dfb->obj->obj);
 22	kfree(dfb);
 23}
 24
 25static int armada_fb_create_handle(struct drm_framebuffer *fb,
 26	struct drm_file *dfile, unsigned int *handle)
 27{
 28	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(fb);
 29	return drm_gem_handle_create(dfile, &dfb->obj->obj, handle);
 30}
 31
 32static const struct drm_framebuffer_funcs armada_fb_funcs = {
 33	.destroy	= armada_fb_destroy,
 34	.create_handle	= armada_fb_create_handle,
 35};
 36
 37struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
 38	const struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
 39{
 40	struct armada_framebuffer *dfb;
 41	uint8_t format, config;
 42	int ret;
 43
 44	switch (mode->pixel_format) {
 45#define FMT(drm, fmt, mod)		\
 46	case DRM_FORMAT_##drm:		\
 47		format = CFG_##fmt;	\
 48		config = mod;		\
 49		break
 50	FMT(RGB565,	565,		CFG_SWAPRB);
 51	FMT(BGR565,	565,		0);
 52	FMT(ARGB1555,	1555,		CFG_SWAPRB);
 53	FMT(ABGR1555,	1555,		0);
 54	FMT(RGB888,	888PACK,	CFG_SWAPRB);
 55	FMT(BGR888,	888PACK,	0);
 56	FMT(XRGB8888,	X888,		CFG_SWAPRB);
 57	FMT(XBGR8888,	X888,		0);
 58	FMT(ARGB8888,	8888,		CFG_SWAPRB);
 59	FMT(ABGR8888,	8888,		0);
 60	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);
 61	FMT(UYVY,	422PACK,	CFG_YUV2RGB);
 62	FMT(VYUY,	422PACK,	CFG_YUV2RGB | CFG_SWAPUV);
 63	FMT(YVYU,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU);
 64	FMT(YUV422,	422,		CFG_YUV2RGB);
 65	FMT(YVU422,	422,		CFG_YUV2RGB | CFG_SWAPUV);
 66	FMT(YUV420,	420,		CFG_YUV2RGB);
 67	FMT(YVU420,	420,		CFG_YUV2RGB | CFG_SWAPUV);
 68	FMT(C8,		PSEUDO8,	0);
 69#undef FMT
 70	default:
 71		return ERR_PTR(-EINVAL);
 72	}
 73
 74	dfb = kzalloc(sizeof(*dfb), GFP_KERNEL);
 75	if (!dfb) {
 76		DRM_ERROR("failed to allocate Armada fb object\n");
 77		return ERR_PTR(-ENOMEM);
 78	}
 79
 80	dfb->fmt = format;
 81	dfb->mod = config;
 82	dfb->obj = obj;
 83
 84	drm_helper_mode_fill_fb_struct(&dfb->fb, mode);
 85
 86	ret = drm_framebuffer_init(dev, &dfb->fb, &armada_fb_funcs);
 87	if (ret) {
 88		kfree(dfb);
 89		return ERR_PTR(ret);
 90	}
 91
 92	/*
 93	 * Take a reference on our object as we're successful - the
 94	 * caller already holds a reference, which keeps us safe for
 95	 * the above call, but the caller will drop their reference
 96	 * to it.  Hence we need to take our own reference.
 97	 */
 98	drm_gem_object_reference(&obj->obj);
 99
100	return dfb;
101}
102
103static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
104	struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
105{
 
106	struct armada_gem_object *obj;
107	struct armada_framebuffer *dfb;
108	int ret;
109
110	DRM_DEBUG_DRIVER("w%u h%u pf%08x f%u p%u,%u,%u\n",
111		mode->width, mode->height, mode->pixel_format,
112		mode->flags, mode->pitches[0], mode->pitches[1],
113		mode->pitches[2]);
114
115	/* We can only handle a single plane at the moment */
116	if (drm_format_num_planes(mode->pixel_format) > 1 &&
117	    (mode->handles[0] != mode->handles[1] ||
118	     mode->handles[0] != mode->handles[2])) {
119		ret = -EINVAL;
120		goto err;
121	}
122
123	obj = armada_gem_object_lookup(dev, dfile, mode->handles[0]);
124	if (!obj) {
125		ret = -ENOENT;
126		goto err;
127	}
128
129	if (obj->obj.import_attach && !obj->sgt) {
130		ret = armada_gem_map_import(obj);
131		if (ret)
132			goto err_unref;
133	}
134
135	/* Framebuffer objects must have a valid device address for scanout */
136	if (obj->dev_addr == DMA_ERROR_CODE) {
137		ret = -EINVAL;
138		goto err_unref;
139	}
140
141	dfb = armada_framebuffer_create(dev, mode, obj);
142	if (IS_ERR(dfb)) {
143		ret = PTR_ERR(dfb);
144		goto err;
145	}
146
147	drm_gem_object_unreference_unlocked(&obj->obj);
148
149	return &dfb->fb;
150
151 err_unref:
152	drm_gem_object_unreference_unlocked(&obj->obj);
153 err:
154	DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
155	return ERR_PTR(ret);
156}
157
158static void armada_output_poll_changed(struct drm_device *dev)
159{
160	struct armada_private *priv = dev->dev_private;
161	struct drm_fb_helper *fbh = priv->fbdev;
162
163	if (fbh)
164		drm_fb_helper_hotplug_event(fbh);
165}
166
167const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
168	.fb_create		= armada_fb_create,
169	.output_poll_changed	= armada_output_poll_changed,
170};
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2012 Russell King
 
 
 
 
  4 */
  5
  6#include <drm/drm_modeset_helper.h>
  7#include <drm/drm_fb_helper.h>
  8#include <drm/drm_fourcc.h>
  9#include <drm/drm_gem_framebuffer_helper.h>
 10
 11#include "armada_drm.h"
 12#include "armada_fb.h"
 13#include "armada_gem.h"
 14#include "armada_hw.h"
 15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 16static const struct drm_framebuffer_funcs armada_fb_funcs = {
 17	.destroy	= drm_gem_fb_destroy,
 18	.create_handle	= drm_gem_fb_create_handle,
 19};
 20
 21struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
 22	const struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
 23{
 24	struct armada_framebuffer *dfb;
 25	uint8_t format, config;
 26	int ret;
 27
 28	switch (mode->pixel_format) {
 29#define FMT(drm, fmt, mod)		\
 30	case DRM_FORMAT_##drm:		\
 31		format = CFG_##fmt;	\
 32		config = mod;		\
 33		break
 34	FMT(RGB565,	565,		CFG_SWAPRB);
 35	FMT(BGR565,	565,		0);
 36	FMT(ARGB1555,	1555,		CFG_SWAPRB);
 37	FMT(ABGR1555,	1555,		0);
 38	FMT(RGB888,	888PACK,	CFG_SWAPRB);
 39	FMT(BGR888,	888PACK,	0);
 40	FMT(XRGB8888,	X888,		CFG_SWAPRB);
 41	FMT(XBGR8888,	X888,		0);
 42	FMT(ARGB8888,	8888,		CFG_SWAPRB);
 43	FMT(ABGR8888,	8888,		0);
 44	FMT(YUYV,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU | CFG_SWAPUV);
 45	FMT(UYVY,	422PACK,	CFG_YUV2RGB);
 46	FMT(VYUY,	422PACK,	CFG_YUV2RGB | CFG_SWAPUV);
 47	FMT(YVYU,	422PACK,	CFG_YUV2RGB | CFG_SWAPYU);
 48	FMT(YUV422,	422,		CFG_YUV2RGB);
 49	FMT(YVU422,	422,		CFG_YUV2RGB | CFG_SWAPUV);
 50	FMT(YUV420,	420,		CFG_YUV2RGB);
 51	FMT(YVU420,	420,		CFG_YUV2RGB | CFG_SWAPUV);
 52	FMT(C8,		PSEUDO8,	0);
 53#undef FMT
 54	default:
 55		return ERR_PTR(-EINVAL);
 56	}
 57
 58	dfb = kzalloc(sizeof(*dfb), GFP_KERNEL);
 59	if (!dfb) {
 60		DRM_ERROR("failed to allocate Armada fb object\n");
 61		return ERR_PTR(-ENOMEM);
 62	}
 63
 64	dfb->fmt = format;
 65	dfb->mod = config;
 66	dfb->fb.obj[0] = &obj->obj;
 67
 68	drm_helper_mode_fill_fb_struct(dev, &dfb->fb, mode);
 69
 70	ret = drm_framebuffer_init(dev, &dfb->fb, &armada_fb_funcs);
 71	if (ret) {
 72		kfree(dfb);
 73		return ERR_PTR(ret);
 74	}
 75
 76	/*
 77	 * Take a reference on our object as we're successful - the
 78	 * caller already holds a reference, which keeps us safe for
 79	 * the above call, but the caller will drop their reference
 80	 * to it.  Hence we need to take our own reference.
 81	 */
 82	drm_gem_object_get(&obj->obj);
 83
 84	return dfb;
 85}
 86
 87struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
 88	struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
 89{
 90	const struct drm_format_info *info = drm_get_format_info(dev, mode);
 91	struct armada_gem_object *obj;
 92	struct armada_framebuffer *dfb;
 93	int ret;
 94
 95	DRM_DEBUG_DRIVER("w%u h%u pf%08x f%u p%u,%u,%u\n",
 96		mode->width, mode->height, mode->pixel_format,
 97		mode->flags, mode->pitches[0], mode->pitches[1],
 98		mode->pitches[2]);
 99
100	/* We can only handle a single plane at the moment */
101	if (info->num_planes > 1 &&
102	    (mode->handles[0] != mode->handles[1] ||
103	     mode->handles[0] != mode->handles[2])) {
104		ret = -EINVAL;
105		goto err;
106	}
107
108	obj = armada_gem_object_lookup(dfile, mode->handles[0]);
109	if (!obj) {
110		ret = -ENOENT;
111		goto err;
112	}
113
114	if (obj->obj.import_attach && !obj->sgt) {
115		ret = armada_gem_map_import(obj);
116		if (ret)
117			goto err_unref;
118	}
119
120	/* Framebuffer objects must have a valid device address for scanout */
121	if (!obj->mapped) {
122		ret = -EINVAL;
123		goto err_unref;
124	}
125
126	dfb = armada_framebuffer_create(dev, mode, obj);
127	if (IS_ERR(dfb)) {
128		ret = PTR_ERR(dfb);
129		goto err;
130	}
131
132	drm_gem_object_put(&obj->obj);
133
134	return &dfb->fb;
135
136 err_unref:
137	drm_gem_object_put(&obj->obj);
138 err:
139	DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
140	return ERR_PTR(ret);
141}