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

Commit cf481068 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch '2016-02-26-st-drm-next' of...

Merge branch '2016-02-26-st-drm-next' of http://git.linaro.org/people/benjamin.gaignard/kernel into drm-next

Here are sti patches for drm-next.
It brings:
  - The support of the atomic_check for the planes and minor fixes for
planes
  - The support of the vendor specific infoframe for HDMI and the
support of 2 HDMI properties related to the connector
  - The support of the DVO solving panel detection issue and timing issue.
  - The support of debugfs for connectors, encoders, crtcs and planes.

* '2016-02-26-st-drm-next' of http://git.linaro.org/people/benjamin.gaignard/kernel: (36 commits)
  drm/sti: use u32 to store DMA addresses
  drm: sti: remove sti_gem_prime_export hack
  drm/sti: add debugfs fps_show/fps_get mechanism for planes
  drm/sti: add debugfs entries for TVOUT encoders
  drm/sti: add debugfs entries for MIXER crtc
  drm/sti: add debugfs entries for VID plane
  drm/sti: add debugfs entries for HQVDP plane
  drm/sti: add debugfs entries for GDP planes
  drm/sti: add debugfs entries for CURSOR plane
  drm/sti: add debugfs entries for HDA connector
  drm/sti: add debugfs entries for DVO connector
  drm/sti: add debugfs entries for HDMI connector
  drm/sti: add hdmi_mode property for HDMI connector
  drm/sti: add colorspace property to the HDMI connector
  drm/sti: add HDMI vendor specific infoframe
  drm/sti: reset infoframe transmission when HDMI is stopped
  drm/sti: HDMI infoframe transmission mode not take into account
  drm/sti: reset HD DACS when HDA connector is created
  drm/sti: fix dvo data_enable signal
  drm/sti: adjust delay for DVO
  ...
parents 9f443bf5 52807ae9
Loading
Loading
Loading
Loading
+44 −34
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include "sti_awg_utils.h"

#define AWG_OPCODE_OFFSET 10
#define AWG_MAX_ARG       0x3ff

enum opcode {
	SET,
@@ -34,6 +35,8 @@ static int awg_generate_instr(enum opcode opcode,
	/* skip, repeat and replay arg should not exceed 1023.
	 * If user wants to exceed this value, the instruction should be
	 * duplicate and arg should be adjust for each duplicated instruction.
	 *
	 * mux_sel is used in case of SAV/EAV synchronization.
	 */

	while (arg_tmp > 0) {
@@ -65,7 +68,7 @@ static int awg_generate_instr(enum opcode opcode,

			mux = 0;
			data_enable = 0;
			arg &= (0x3ff);
			arg &= AWG_MAX_ARG;
			break;
		case REPEAT:
		case REPLAY:
@@ -76,13 +79,13 @@ static int awg_generate_instr(enum opcode opcode,

			mux = 0;
			data_enable = 0;
			arg &= (0x3ff);
			arg &= AWG_MAX_ARG;
			break;
		case JUMP:
			mux = 0;
			data_enable = 0;
			arg |= 0x40; /* for jump instruction 7th bit is 1 */
			arg &= 0x3ff;
			arg &= AWG_MAX_ARG;
			break;
		case STOP:
			arg = 0;
@@ -110,68 +113,75 @@ static int awg_generate_instr(enum opcode opcode,
	return 0;
}

int sti_awg_generate_code_data_enable_mode(
static int awg_generate_line_signal(
		struct awg_code_generation_params *fwparams,
		struct awg_timing *timing)
{
	long int val;
	long int data_en;
	int ret = 0;

	if (timing->trailing_lines > 0) {
		/* skip trailing lines */
		val = timing->blanking_level;
		data_en = 0;
		ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams);

		val = timing->trailing_lines - 1;
		data_en = 0;
		ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams);
	}

	if (timing->trailing_pixels > 0) {
		/* skip trailing pixel */
		val = timing->blanking_level;
		data_en = 0;
		ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);

		val = timing->trailing_pixels - 1;
		data_en = 0;
		ret |= awg_generate_instr(SKIP, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(SKIP, val, 0, 0, fwparams);
	}

	/* set DE signal high */
	val = timing->blanking_level;
	data_en = 1;
	ret |= awg_generate_instr((timing->trailing_pixels > 0) ? SET : RPLSET,
			val, 0, data_en, fwparams);
			val, 0, 1, fwparams);

	if (timing->blanking_pixels > 0) {
		/* skip the number of active pixel */
		val = timing->active_pixels - 1;
		data_en = 1;
		ret |= awg_generate_instr(SKIP, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(SKIP, val, 0, 1, fwparams);

		/* set DE signal low */
		val = timing->blanking_level;
		data_en = 0;
		ret |= awg_generate_instr(SET, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(SET, val, 0, 0, fwparams);
	}

	return ret;
}

int sti_awg_generate_code_data_enable_mode(
		struct awg_code_generation_params *fwparams,
		struct awg_timing *timing)
{
	long int val, tmp_val;
	int ret = 0;

	if (timing->trailing_lines > 0) {
		/* skip trailing lines */
		val = timing->blanking_level;
		ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);

		val = timing->trailing_lines - 1;
		ret |= awg_generate_instr(REPLAY, val, 0, 0, fwparams);
	}

	tmp_val = timing->active_lines - 1;

	while (tmp_val > 0) {
		/* generate DE signal for each line */
		ret |= awg_generate_line_signal(fwparams, timing);
		/* replay the sequence as many active lines defined */
	val = timing->active_lines - 1;
	data_en = 0;
	ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(REPLAY,
					  min_t(int, AWG_MAX_ARG, tmp_val),
					  0, 0, fwparams);
		tmp_val -= AWG_MAX_ARG;
	}

	if (timing->blanking_lines > 0) {
		/* skip blanking lines */
		val = timing->blanking_level;
		data_en = 0;
		ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);

		val = timing->blanking_lines - 1;
		data_en = 0;
		ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams);
		ret |= awg_generate_instr(REPLAY, val, 0, 0, fwparams);
	}

	return ret;
+2 −2
Original line number Diff line number Diff line
@@ -75,13 +75,13 @@ static int sti_compositor_bind(struct device *dev,
		switch (desc[i].type) {
		case STI_VID_SUBDEV:
			compo->vid[vid_id++] =
			    sti_vid_create(compo->dev, desc[i].id,
			    sti_vid_create(compo->dev, drm_dev, desc[i].id,
					   compo->regs + desc[i].offset);
			break;
		case STI_MIXER_MAIN_SUBDEV:
		case STI_MIXER_AUX_SUBDEV:
			compo->mixer[mixer_id++] =
			    sti_mixer_create(compo->dev, desc[i].id,
			    sti_mixer_create(compo->dev, drm_dev, desc[i].id,
					     compo->regs + desc[i].offset);
			break;
		case STI_GPD_SUBDEV:
+9 −0
Original line number Diff line number Diff line
@@ -51,6 +51,15 @@ static void sti_crtc_disabling(struct drm_crtc *crtc)
	mixer->status = STI_MIXER_DISABLING;
}

static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
				const struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode)
{
	/* accept the provided drm_display_mode, do not fix it up */
	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
	return true;
}

static int
sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
{
+144 −40
Original line number Diff line number Diff line
@@ -5,12 +5,10 @@
 *          for STMicroelectronics.
 * License terms:  GNU General Public License (GPL), version 2
 */
#include <drm/drmP.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h>

#include "sti_compositor.h"
#include "sti_cursor.h"
@@ -74,6 +72,82 @@ static const uint32_t cursor_supported_formats[] = {

#define to_sti_cursor(x) container_of(x, struct sti_cursor, plane)

#define DBGFS_DUMP(reg) seq_printf(s, "\n  %-25s 0x%08X", #reg, \
				   readl(cursor->regs + reg))

static void cursor_dbg_vpo(struct seq_file *s, u32 val)
{
	seq_printf(s, "\txdo:%4d\tydo:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF);
}

static void cursor_dbg_size(struct seq_file *s, u32 val)
{
	seq_printf(s, "\t%d x %d", val & 0x07FF, (val >> 16) & 0x07FF);
}

static void cursor_dbg_pml(struct seq_file *s,
			   struct sti_cursor *cursor, u32 val)
{
	if (cursor->pixmap.paddr == val)
		seq_printf(s, "\tVirt @: %p", cursor->pixmap.base);
}

static void cursor_dbg_cml(struct seq_file *s,
			   struct sti_cursor *cursor, u32 val)
{
	if (cursor->clut_paddr == val)
		seq_printf(s, "\tVirt @: %p", cursor->clut);
}

static int cursor_dbg_show(struct seq_file *s, void *data)
{
	struct drm_info_node *node = s->private;
	struct sti_cursor *cursor = (struct sti_cursor *)node->info_ent->data;
	struct drm_device *dev = node->minor->dev;
	int ret;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	seq_printf(s, "%s: (vaddr = 0x%p)",
		   sti_plane_to_str(&cursor->plane), cursor->regs);

	DBGFS_DUMP(CUR_CTL);
	DBGFS_DUMP(CUR_VPO);
	cursor_dbg_vpo(s, readl(cursor->regs + CUR_VPO));
	DBGFS_DUMP(CUR_PML);
	cursor_dbg_pml(s, cursor, readl(cursor->regs + CUR_PML));
	DBGFS_DUMP(CUR_PMP);
	DBGFS_DUMP(CUR_SIZE);
	cursor_dbg_size(s, readl(cursor->regs + CUR_SIZE));
	DBGFS_DUMP(CUR_CML);
	cursor_dbg_cml(s, cursor, readl(cursor->regs + CUR_CML));
	DBGFS_DUMP(CUR_AWS);
	DBGFS_DUMP(CUR_AWE);
	seq_puts(s, "\n");

	mutex_unlock(&dev->struct_mutex);
	return 0;
}

static struct drm_info_list cursor_debugfs_files[] = {
	{ "cursor", cursor_dbg_show, 0, NULL },
};

static int cursor_debugfs_init(struct sti_cursor *cursor,
			       struct drm_minor *minor)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(cursor_debugfs_files); i++)
		cursor_debugfs_files[i].data = cursor;

	return drm_debugfs_create_files(cursor_debugfs_files,
					ARRAY_SIZE(cursor_debugfs_files),
					minor->debugfs_root, minor);
}

static void sti_cursor_argb8888_to_clut8(struct sti_cursor *cursor, u32 *src)
{
	u8  *dst = cursor->pixmap.base;
@@ -110,35 +184,31 @@ static void sti_cursor_init(struct sti_cursor *cursor)
						  (b * 5);
}

static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
				     struct drm_plane_state *oldstate)
static int sti_cursor_atomic_check(struct drm_plane *drm_plane,
				   struct drm_plane_state *state)
{
	struct drm_plane_state *state = drm_plane->state;
	struct sti_plane *plane = to_sti_plane(drm_plane);
	struct sti_cursor *cursor = to_sti_cursor(plane);
	struct drm_crtc *crtc = state->crtc;
	struct sti_mixer *mixer = to_sti_mixer(crtc);
	struct drm_framebuffer *fb = state->fb;
	struct drm_display_mode *mode = &crtc->mode;
	int dst_x = state->crtc_x;
	int dst_y = state->crtc_y;
	int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
	int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
	struct drm_crtc_state *crtc_state;
	struct drm_display_mode *mode;
	int dst_x, dst_y, dst_w, dst_h;
	int src_w, src_h;

	/* no need for further checks if the plane is being disabled */
	if (!crtc || !fb)
		return 0;

	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
	mode = &crtc_state->mode;
	dst_x = state->crtc_x;
	dst_y = state->crtc_y;
	dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
	dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
	/* src_x are in 16.16 format */
	int src_w = state->src_w >> 16;
	int src_h = state->src_h >> 16;
	bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
	struct drm_gem_cma_object *cma_obj;
	u32 y, x;
	u32 val;

	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
		      crtc->base.id, sti_mixer_to_str(mixer),
		      drm_plane->base.id, sti_plane_to_str(plane));
	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", dst_w, dst_h, dst_x, dst_y);

	dev_dbg(cursor->dev, "%s %s\n", __func__,
		sti_plane_to_str(plane));
	src_w = state->src_w >> 16;
	src_h = state->src_h >> 16;

	if (src_w < STI_CURS_MIN_SIZE ||
	    src_h < STI_CURS_MIN_SIZE ||
@@ -146,7 +216,7 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
	    src_h > STI_CURS_MAX_SIZE) {
		DRM_ERROR("Invalid cursor size (%dx%d)\n",
				src_w, src_h);
		return;
		return -EINVAL;
	}

	/* If the cursor size has changed, re-allocated the pixmap */
@@ -170,16 +240,46 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
							GFP_KERNEL | GFP_DMA);
		if (!cursor->pixmap.base) {
			DRM_ERROR("Failed to allocate memory for pixmap\n");
			return;
			return -EINVAL;
		}
	}

	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
	if (!cma_obj) {
	if (!drm_fb_cma_get_gem_obj(fb, 0)) {
		DRM_ERROR("Can't get CMA GEM object for fb\n");
		return;
		return -EINVAL;
	}

	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
		      crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)),
		      drm_plane->base.id, sti_plane_to_str(plane));
	DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", dst_w, dst_h, dst_x, dst_y);

	return 0;
}

static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
				     struct drm_plane_state *oldstate)
{
	struct drm_plane_state *state = drm_plane->state;
	struct sti_plane *plane = to_sti_plane(drm_plane);
	struct sti_cursor *cursor = to_sti_cursor(plane);
	struct drm_crtc *crtc = state->crtc;
	struct drm_framebuffer *fb = state->fb;
	struct drm_display_mode *mode;
	int dst_x, dst_y;
	struct drm_gem_cma_object *cma_obj;
	u32 y, x;
	u32 val;

	if (!crtc || !fb)
		return;

	mode = &crtc->mode;
	dst_x = state->crtc_x;
	dst_y = state->crtc_y;

	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);

	/* Convert ARGB8888 to CLUT8 */
	sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr);

@@ -193,21 +293,21 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
	val = y << 16 | x;
	writel(val, cursor->regs + CUR_AWE);

	if (first_prepare) {
		/* Set and fetch CLUT */
		writel(cursor->clut_paddr, cursor->regs + CUR_CML);
		writel(CUR_CTL_CLUT_UPDATE, cursor->regs + CUR_CTL);
	}

	/* Set memory location, size, and position */
	writel(cursor->pixmap.paddr, cursor->regs + CUR_PML);
	writel(cursor->width, cursor->regs + CUR_PMP);
	writel(cursor->height << 16 | cursor->width, cursor->regs + CUR_SIZE);

	y = sti_vtg_get_line_number(*mode, dst_y);
	x = sti_vtg_get_pixel_number(*mode, dst_y);
	x = sti_vtg_get_pixel_number(*mode, dst_x);
	writel((y << 16) | x, cursor->regs + CUR_VPO);

	/* Set and fetch CLUT */
	writel(cursor->clut_paddr, cursor->regs + CUR_CML);
	writel(CUR_CTL_CLUT_UPDATE, cursor->regs + CUR_CTL);

	sti_plane_update_fps(plane, true, false);

	plane->status = STI_PLANE_UPDATED;
}

@@ -215,7 +315,6 @@ static void sti_cursor_atomic_disable(struct drm_plane *drm_plane,
				      struct drm_plane_state *oldstate)
{
	struct sti_plane *plane = to_sti_plane(drm_plane);
	struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc);

	if (!drm_plane->crtc) {
		DRM_DEBUG_DRIVER("drm plane:%d not enabled\n",
@@ -224,13 +323,15 @@ static void sti_cursor_atomic_disable(struct drm_plane *drm_plane,
	}

	DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
			 drm_plane->crtc->base.id, sti_mixer_to_str(mixer),
			 drm_plane->crtc->base.id,
			 sti_mixer_to_str(to_sti_mixer(drm_plane->crtc)),
			 drm_plane->base.id, sti_plane_to_str(plane));

	plane->status = STI_PLANE_DISABLING;
}

static const struct drm_plane_helper_funcs sti_cursor_helpers_funcs = {
	.atomic_check = sti_cursor_atomic_check,
	.atomic_update = sti_cursor_atomic_update,
	.atomic_disable = sti_cursor_atomic_disable,
};
@@ -283,6 +384,9 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,

	sti_plane_init_property(&cursor->plane, DRM_PLANE_TYPE_CURSOR);

	if (cursor_debugfs_init(cursor, drm_dev->primary))
		DRM_ERROR("CURSOR debugfs setup failed\n");

	return &cursor->plane.drm_plane;

err_plane:
+130 −11
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include "sti_crtc.h"
#include "sti_drv.h"
#include "sti_plane.h"

#define DRIVER_NAME	"sti"
#define DRIVER_DESC	"STMicroelectronics SoC DRM"
@@ -30,6 +31,130 @@
#define STI_MAX_FB_HEIGHT	4096
#define STI_MAX_FB_WIDTH	4096

static int sti_drm_fps_get(void *data, u64 *val)
{
	struct drm_device *drm_dev = data;
	struct drm_plane *p;
	unsigned int i = 0;

	*val = 0;
	list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
		struct sti_plane *plane = to_sti_plane(p);

		*val |= plane->fps_info.output << i;
		i++;
	}

	return 0;
}

static int sti_drm_fps_set(void *data, u64 val)
{
	struct drm_device *drm_dev = data;
	struct drm_plane *p;
	unsigned int i = 0;

	list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
		struct sti_plane *plane = to_sti_plane(p);

		plane->fps_info.output = (val >> i) & 1;
		i++;
	}

	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(sti_drm_fps_fops,
			sti_drm_fps_get, sti_drm_fps_set, "%llu\n");

static int sti_drm_fps_dbg_show(struct seq_file *s, void *data)
{
	struct drm_info_node *node = s->private;
	struct drm_device *dev = node->minor->dev;
	struct drm_plane *p;
	int ret;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	list_for_each_entry(p, &dev->mode_config.plane_list, head) {
		struct sti_plane *plane = to_sti_plane(p);

		seq_printf(s, "%s%s\n",
			   plane->fps_info.fps_str,
			   plane->fps_info.fips_str);
	}

	mutex_unlock(&dev->struct_mutex);
	return 0;
}

static struct drm_info_list sti_drm_dbg_list[] = {
	{"fps_get", sti_drm_fps_dbg_show, 0},
};

static int sti_drm_debugfs_create(struct dentry *root,
				  struct drm_minor *minor,
				  const char *name,
				  const struct file_operations *fops)
{
	struct drm_device *dev = minor->dev;
	struct drm_info_node *node;
	struct dentry *ent;

	ent = debugfs_create_file(name, S_IRUGO | S_IWUSR, root, dev, fops);
	if (IS_ERR(ent))
		return PTR_ERR(ent);

	node = kmalloc(sizeof(*node), GFP_KERNEL);
	if (!node) {
		debugfs_remove(ent);
		return -ENOMEM;
	}

	node->minor = minor;
	node->dent = ent;
	node->info_ent = (void *)fops;

	mutex_lock(&minor->debugfs_lock);
	list_add(&node->list, &minor->debugfs_list);
	mutex_unlock(&minor->debugfs_lock);

	return 0;
}

static int sti_drm_dbg_init(struct drm_minor *minor)
{
	int ret;

	ret = drm_debugfs_create_files(sti_drm_dbg_list,
				       ARRAY_SIZE(sti_drm_dbg_list),
				       minor->debugfs_root, minor);
	if (ret)
		goto err;

	ret = sti_drm_debugfs_create(minor->debugfs_root, minor, "fps_show",
				     &sti_drm_fps_fops);
	if (ret)
		goto err;

	DRM_INFO("%s: debugfs installed\n", DRIVER_NAME);
	return 0;
err:
	DRM_ERROR("%s: cannot install debugfs\n", DRIVER_NAME);
	return ret;
}

void sti_drm_dbg_cleanup(struct drm_minor *minor)
{
	drm_debugfs_remove_files(sti_drm_dbg_list,
				 ARRAY_SIZE(sti_drm_dbg_list), minor);

	drm_debugfs_remove_files((struct drm_info_list *)&sti_drm_fps_fops,
				 1, minor);
}

static void sti_atomic_schedule(struct sti_private *private,
				struct drm_atomic_state *state)
{
@@ -181,18 +306,9 @@ static const struct file_operations sti_driver_fops = {
	.release = drm_release,
};

static struct dma_buf *sti_gem_prime_export(struct drm_device *dev,
					    struct drm_gem_object *obj,
					    int flags)
{
	/* we want to be able to write in mmapped buffer */
	flags |= O_RDWR;
	return drm_gem_prime_export(dev, obj, flags);
}

static struct drm_driver sti_driver = {
	.driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
	    DRIVER_GEM | DRIVER_PRIME,
	    DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
	.load = sti_load,
	.gem_free_object = drm_gem_cma_free_object,
	.gem_vm_ops = &drm_gem_cma_vm_ops,
@@ -207,7 +323,7 @@ static struct drm_driver sti_driver = {

	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
	.gem_prime_export = sti_gem_prime_export,
	.gem_prime_export = drm_gem_prime_export,
	.gem_prime_import = drm_gem_prime_import,
	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
@@ -215,6 +331,9 @@ static struct drm_driver sti_driver = {
	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
	.gem_prime_mmap = drm_gem_cma_prime_mmap,

	.debugfs_init = sti_drm_dbg_init,
	.debugfs_cleanup = sti_drm_dbg_cleanup,

	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
Loading