Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de2ba664 authored by Arto Merilainen's avatar Arto Merilainen Committed by Thierry Reding
Browse files

gpu: host1x: drm: Add memory manager and fb



This patch introduces a memory manager for tegra drm and moves
existing parts to use it. As cma framebuffer helpers can no more
be used, this patch adds also a separate framebuffer driver for
tegra.

Signed-off-by: default avatarArto Merilainen <amerilainen@nvidia.com>
Signed-off-by: default avatarTerje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: default avatarThierry Reding <thierry.reding@avionic-design.de>
Tested-by: default avatarThierry Reding <thierry.reding@avionic-design.de>
Tested-by: default avatarErik Faye-Lund <kusmabite@gmail.com>
Signed-off-by: default avatarThierry Reding <thierry.reding@avionic-design.de>
parent 692e6d7b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -15,4 +15,5 @@ ccflags-$(CONFIG_DRM_TEGRA_DEBUG) += -DDEBUG


host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o
host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o
host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o
obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
+3 −5
Original line number Original line Diff line number Diff line
@@ -2,11 +2,9 @@ config DRM_TEGRA
	bool "NVIDIA Tegra DRM"
	bool "NVIDIA Tegra DRM"
	depends on DRM && OF
	depends on DRM && OF
	select DRM_KMS_HELPER
	select DRM_KMS_HELPER
	select DRM_GEM_CMA_HELPER
	select FB_SYS_FILLRECT
	select DRM_KMS_CMA_HELPER
	select FB_SYS_COPYAREA
	select FB_CFB_FILLRECT
	select FB_SYS_IMAGEBLIT
	select FB_CFB_COPYAREA
	select FB_CFB_IMAGEBLIT
	help
	help
	  Choose this option if you have an NVIDIA Tegra SoC.
	  Choose this option if you have an NVIDIA Tegra SoC.


+12 −11
Original line number Original line Diff line number Diff line
@@ -14,9 +14,10 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/clk/tegra.h>
#include <linux/clk/tegra.h>


#include "drm.h"
#include "dc.h"
#include "host1x_client.h"
#include "host1x_client.h"
#include "dc.h"
#include "drm.h"
#include "gem.h"


struct tegra_plane {
struct tegra_plane {
	struct drm_plane base;
	struct drm_plane base;
@@ -52,9 +53,9 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
	window.bits_per_pixel = fb->bits_per_pixel;
	window.bits_per_pixel = fb->bits_per_pixel;


	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
		struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
		struct tegra_bo *bo = tegra_fb_get_plane(fb, i);


		window.base[i] = gem->paddr + fb->offsets[i];
		window.base[i] = bo->paddr + fb->offsets[i];


		/*
		/*
		 * Tegra doesn't support different strides for U and V planes
		 * Tegra doesn't support different strides for U and V planes
@@ -137,7 +138,7 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
			     struct drm_framebuffer *fb)
			     struct drm_framebuffer *fb)
{
{
	struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, 0);
	struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
	unsigned long value;
	unsigned long value;


	tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
	tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
@@ -145,7 +146,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
	value = fb->offsets[0] + y * fb->pitches[0] +
	value = fb->offsets[0] + y * fb->pitches[0] +
		x * fb->bits_per_pixel / 8;
		x * fb->bits_per_pixel / 8;


	tegra_dc_writel(dc, gem->paddr + value, DC_WINBUF_START_ADDR);
	tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
	tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
	tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);


	value = GENERAL_UPDATE | WIN_A_UPDATE;
	value = GENERAL_UPDATE | WIN_A_UPDATE;
@@ -187,20 +188,20 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc)
{
{
	struct drm_device *drm = dc->base.dev;
	struct drm_device *drm = dc->base.dev;
	struct drm_crtc *crtc = &dc->base;
	struct drm_crtc *crtc = &dc->base;
	struct drm_gem_cma_object *gem;
	unsigned long flags, base;
	unsigned long flags, base;
	struct tegra_bo *bo;


	if (!dc->event)
	if (!dc->event)
		return;
		return;


	gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
	bo = tegra_fb_get_plane(crtc->fb, 0);


	/* check if new start address has been latched */
	/* check if new start address has been latched */
	tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
	tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
	base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
	base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR);
	tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
	tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);


	if (base == gem->paddr + crtc->fb->offsets[0]) {
	if (base == bo->paddr + crtc->fb->offsets[0]) {
		spin_lock_irqsave(&drm->event_lock, flags);
		spin_lock_irqsave(&drm->event_lock, flags);
		drm_send_vblank_event(drm, dc->pipe, dc->event);
		drm_send_vblank_event(drm, dc->pipe, dc->event);
		drm_vblank_put(drm, dc->pipe);
		drm_vblank_put(drm, dc->pipe);
@@ -570,7 +571,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
			       struct drm_display_mode *adjusted,
			       struct drm_display_mode *adjusted,
			       int x, int y, struct drm_framebuffer *old_fb)
			       int x, int y, struct drm_framebuffer *old_fb)
{
{
	struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(crtc->fb, 0);
	struct tegra_bo *bo = tegra_fb_get_plane(crtc->fb, 0);
	struct tegra_dc *dc = to_tegra_dc(crtc);
	struct tegra_dc *dc = to_tegra_dc(crtc);
	struct tegra_dc_window window;
	struct tegra_dc_window window;
	unsigned long div, value;
	unsigned long div, value;
@@ -617,7 +618,7 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
	window.format = tegra_dc_format(crtc->fb->pixel_format);
	window.format = tegra_dc_format(crtc->fb->pixel_format);
	window.bits_per_pixel = crtc->fb->bits_per_pixel;
	window.bits_per_pixel = crtc->fb->bits_per_pixel;
	window.stride[0] = crtc->fb->pitches[0];
	window.stride[0] = crtc->fb->pitches[0];
	window.base[0] = gem->paddr;
	window.base[0] = bo->paddr;


	err = tegra_dc_setup_window(dc, 0, &window);
	err = tegra_dc_setup_window(dc, 0, &window);
	if (err < 0)
	if (err < 0)
+10 −7
Original line number Original line Diff line number Diff line
@@ -15,7 +15,10 @@
#include <asm/dma-iommu.h>
#include <asm/dma-iommu.h>


#include "host1x_client.h"
#include "host1x_client.h"
#include "dev.h"
#include "drm.h"
#include "drm.h"
#include "gem.h"
#include "syncpt.h"


#define DRIVER_NAME "tegra"
#define DRIVER_NAME "tegra"
#define DRIVER_DESC "NVIDIA Tegra graphics"
#define DRIVER_DESC "NVIDIA Tegra graphics"
@@ -281,7 +284,7 @@ static void tegra_drm_lastclose(struct drm_device *drm)
{
{
	struct host1x_drm *host1x = drm->dev_private;
	struct host1x_drm *host1x = drm->dev_private;


	drm_fbdev_cma_restore_mode(host1x->fbdev);
	tegra_fbdev_restore_mode(host1x->fbdev);
}
}


static struct drm_ioctl_desc tegra_drm_ioctls[] = {
static struct drm_ioctl_desc tegra_drm_ioctls[] = {
@@ -292,7 +295,7 @@ static const struct file_operations tegra_drm_fops = {
	.open = drm_open,
	.open = drm_open,
	.release = drm_release,
	.release = drm_release,
	.unlocked_ioctl = drm_ioctl,
	.unlocked_ioctl = drm_ioctl,
	.mmap = drm_gem_cma_mmap,
	.mmap = tegra_drm_mmap,
	.poll = drm_poll,
	.poll = drm_poll,
	.fasync = drm_fasync,
	.fasync = drm_fasync,
	.read = drm_read,
	.read = drm_read,
@@ -408,11 +411,11 @@ struct drm_driver tegra_drm_driver = {
	.debugfs_cleanup = tegra_debugfs_cleanup,
	.debugfs_cleanup = tegra_debugfs_cleanup,
#endif
#endif


	.gem_free_object = drm_gem_cma_free_object,
	.gem_free_object = tegra_bo_free_object,
	.gem_vm_ops = &drm_gem_cma_vm_ops,
	.gem_vm_ops = &tegra_bo_vm_ops,
	.dumb_create = drm_gem_cma_dumb_create,
	.dumb_create = tegra_bo_dumb_create,
	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
	.dumb_map_offset = tegra_bo_dumb_map_offset,
	.dumb_destroy = drm_gem_cma_dumb_destroy,
	.dumb_destroy = tegra_bo_dumb_destroy,


	.ioctls = tegra_drm_ioctls,
	.ioctls = tegra_drm_ioctls,
	.num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
	.num_ioctls = ARRAY_SIZE(tegra_drm_ioctls),
+15 −3
Original line number Original line Diff line number Diff line
@@ -14,10 +14,19 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_edid.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fixed.h>
#include <drm/drm_fixed.h>


struct tegra_fb {
	struct drm_framebuffer base;
	struct tegra_bo **planes;
	unsigned int num_planes;
};

struct tegra_fbdev {
	struct drm_fb_helper base;
	struct tegra_fb *fb;
};

struct host1x_drm {
struct host1x_drm {
	struct drm_device *drm;
	struct drm_device *drm;
	struct device *dev;
	struct device *dev;
@@ -33,7 +42,7 @@ struct host1x_drm {
	struct mutex clients_lock;
	struct mutex clients_lock;
	struct list_head clients;
	struct list_head clients;


	struct drm_fbdev_cma *fbdev;
	struct tegra_fbdev *fbdev;
};
};


struct host1x_client;
struct host1x_client;
@@ -226,8 +235,11 @@ extern int tegra_output_init(struct drm_device *drm, struct tegra_output *output
extern int tegra_output_exit(struct tegra_output *output);
extern int tegra_output_exit(struct tegra_output *output);


/* from fb.c */
/* from fb.c */
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
				    unsigned int index);
extern int tegra_drm_fb_init(struct drm_device *drm);
extern int tegra_drm_fb_init(struct drm_device *drm);
extern void tegra_drm_fb_exit(struct drm_device *drm);
extern void tegra_drm_fb_exit(struct drm_device *drm);
extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);


extern struct drm_driver tegra_drm_driver;
extern struct drm_driver tegra_drm_driver;


Loading