File Index
Files and directories
Sign in
FILE

fb.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/tegra/fb.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2012-2013 Avionic Design GmbH
  4 * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
  5 *
  6 * Based on the KMS/FB DMA helpers
  7 *   Copyright (C) 2012 Analog Devices Inc.
  8 */
  9
 10#include <linux/console.h>
 11
 12#include <drm/drm_fourcc.h>
 13#include <drm/drm_framebuffer.h>
 14#include <drm/drm_gem_framebuffer_helper.h>
 15#include <drm/drm_modeset_helper.h>
 16#include <drm/drm_print.h>
 17
 18#include "drm.h"
 19#include "gem.h"
 20
 21struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
 22				    unsigned int index)
 23{
 24	return to_tegra_bo(drm_gem_fb_get_obj(framebuffer, index));
 25}
 26
 27bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer)
 28{
 29	struct tegra_bo *bo = tegra_fb_get_plane(framebuffer, 0);
 30
 31	if (bo->flags & TEGRA_BO_BOTTOM_UP)
 32		return true;
 33
 34	return false;
 35}
 36
 37int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
 38			struct tegra_bo_tiling *tiling)
 39{
 40	uint64_t modifier = framebuffer->modifier;
 41
 42	if (fourcc_mod_is_vendor(modifier, NVIDIA)) {
 43		if ((modifier & DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT) == 0)
 44			tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_TEGRA;
 45		else
 46			tiling->sector_layout = TEGRA_BO_SECTOR_LAYOUT_GPU;
 47
 48		modifier &= ~DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT;
 49	}
 50
 51	switch (modifier) {
 52	case DRM_FORMAT_MOD_LINEAR:
 53		tiling->mode = TEGRA_BO_TILING_MODE_PITCH;
 54		tiling->value = 0;
 55		break;
 56
 57	case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED:
 58		tiling->mode = TEGRA_BO_TILING_MODE_TILED;
 59		tiling->value = 0;
 60		break;
 61
 62	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0):
 63		tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
 64		tiling->value = 0;
 65		break;
 66
 67	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1):
 68		tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
 69		tiling->value = 1;
 70		break;
 71
 72	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2):
 73		tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
 74		tiling->value = 2;
 75		break;
 76
 77	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3):
 78		tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
 79		tiling->value = 3;
 80		break;
 81
 82	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4):
 83		tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
 84		tiling->value = 4;
 85		break;
 86
 87	case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5):
 88		tiling->mode = TEGRA_BO_TILING_MODE_BLOCK;
 89		tiling->value = 5;
 90		break;
 91
 92	default:
 93		DRM_DEBUG_KMS("unknown format modifier: %llx\n", modifier);
 94		return -EINVAL;
 95	}
 96
 97	return 0;
 98}
 99
100static const struct drm_framebuffer_funcs tegra_fb_funcs = {
101	.destroy = drm_gem_fb_destroy,
102	.create_handle = drm_gem_fb_create_handle,
103};
104
105struct drm_framebuffer *tegra_fb_alloc(struct drm_device *drm,
106				       const struct drm_format_info *info,
107				       const struct drm_mode_fb_cmd2 *mode_cmd,
108				       struct tegra_bo **planes,
109				       unsigned int num_planes)
110{
111	struct drm_framebuffer *fb;
112	unsigned int i;
113	int err;
114
115	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
116	if (!fb)
117		return ERR_PTR(-ENOMEM);
118
119	drm_helper_mode_fill_fb_struct(drm, fb, info, mode_cmd);
120
121	for (i = 0; i < fb->format->num_planes; i++)
122		fb->obj[i] = &planes[i]->gem;
123
124	err = drm_framebuffer_init(drm, fb, &tegra_fb_funcs);
125	if (err < 0) {
126		dev_err(drm->dev, "failed to initialize framebuffer: %d\n",
127			err);
128		kfree(fb);
129		return ERR_PTR(err);
130	}
131
132	return fb;
133}
134
135struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
136					struct drm_file *file,
137					const struct drm_format_info *info,
138					const struct drm_mode_fb_cmd2 *cmd)
139{
140	struct tegra_bo *planes[4];
141	struct drm_gem_object *gem;
142	struct drm_framebuffer *fb;
143	unsigned int i;
144	int err;
145
146	for (i = 0; i < info->num_planes; i++) {
147		unsigned int width = cmd->width / (i ? info->hsub : 1);
148		unsigned int height = cmd->height / (i ? info->vsub : 1);
149		unsigned int size, bpp;
150
151		gem = drm_gem_object_lookup(file, cmd->handles[i]);
152		if (!gem) {
153			err = -ENXIO;
154			goto unreference;
155		}
156
157		bpp = info->cpp[i];
158
159		size = (height - 1) * cmd->pitches[i] +
160		       width * bpp + cmd->offsets[i];
161
162		if (gem->size < size) {
163			err = -EINVAL;
164			drm_gem_object_put(gem);
165			goto unreference;
166		}
167
168		planes[i] = to_tegra_bo(gem);
169	}
170
171	fb = tegra_fb_alloc(drm, info, cmd, planes, i);
172	if (IS_ERR(fb)) {
173		err = PTR_ERR(fb);
174		goto unreference;
175	}
176
177	return fb;
178
179unreference:
180	while (i--)
181		drm_gem_object_put(&planes[i]->gem);
182
183	return ERR_PTR(err);
184}
~/ Read-only file preview.