aboutsummaryrefslogtreecommitdiffstats
<
###########################################################################
# Copyright 2015, 2016, 2017 IoT.bzh
#
# author: Romain Forlot <romain.forlot@iot.bzh>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
###########################################################################

CMAKE_MINIMUM_REQUIRED(VERSION 3.3)

include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake)
='n260' href='#n260'>260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
From a687bfb7343b33992f92e86c234718c3e21144a0 Mon Sep 17 00:00:00 2001
From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
Date: Tue, 14 Nov 2017 01:47:11 -0800
Subject: [PATCH] media: rcar-imr: IMR driver updates for raw DL

IMR driver updates for raw DL

Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
---
 drivers/media/platform/rcar_imr.c | 209 ++++++++++++++++++++++++++++++--------
 include/uapi/linux/rcar-imr.h     |  16 +--
 2 files changed, 175 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c
index 30c6742..9b601da 100644
--- a/drivers/media/platform/rcar_imr.c
+++ b/drivers/media/platform/rcar_imr.c
@@ -94,6 +94,7 @@ struct imr_device {
 	struct v4l2_device      v4l2_dev;
 	struct video_device     video_dev;
 	struct v4l2_m2m_dev    *m2m_dev;
+	struct device          *alloc_dev;
 
 	/* ...do we need that counter really? framework counts fh structures for us - tbd */
 	int                     refcount;
@@ -117,6 +118,9 @@ struct imr_ctx {
 	/* ...cropping parameters (in pixels) */
 	u16                     crop[4];
 
+	/* ...solid color code */
+	u32                     color;
+
 	/* ...number of active configurations (debugging) */
 	u32                     cfg_num;
 };
@@ -192,6 +196,7 @@ struct imr_ctx {
 
 #define IMR_TRICR                       0x6C
 #define IMR_TRIC_YCFORM                 (1 << 31)
+#define IMR_TRICR2                      0xA0
 
 #define IMR_UVDPOR                      0x70
 #define IMR_SUSR                        0x74
@@ -212,6 +217,8 @@ struct imr_ctx {
 #define IMR_CPDP_UBDPO_SHIFT            4
 #define IMR_CPDP_VRDPO_SHIFT            0
 
+#define IMR_TPOR                        0xF0
+
 /*******************************************************************************
  * Auxiliary helpers
  ******************************************************************************/
@@ -404,11 +411,16 @@ static int imr_queue_setup(struct vb2_queue *vq,
 		return -EINVAL;
 	}
 
+	/* ...specify default allocator */
+	alloc_devs[0] = ctx->imr->alloc_dev;
+
 	return 0;
 }
 
 static int imr_buf_prepare(struct vb2_buffer *vb)
 {
+	struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
 	/* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */
 	return 0;
 }
@@ -441,9 +453,10 @@ static void imr_buf_finish(struct vb2_buffer *vb)
 	WARN_ON(!mutex_is_locked(&ctx->imr->mutex));
 
 	/* ...any special processing of completed buffer? - tbd */
-	v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n",
+	v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done (err: %d) (ctx=%p)\n",
 			q->is_output ? "in" : "out",
-			vb2_dma_contig_plane_dma_addr(vb, 0));
+			vb2_dma_contig_plane_dma_addr(vb, 0),
+			vb->state, ctx);
 
 	/* ...unref configuration pointer as needed */
 	if (q->is_output)
@@ -568,6 +581,11 @@ static inline u16 __imr_auto_sg_dg_tcm(u32 type)
 		(type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0);
 }
 
+static inline u16 __imr_bfe_tme(u32 type)
+{
+	return (type & IMR_MAP_TME ? IMR_TRIM_TME : 0) | (type & IMR_MAP_BFE ? IMR_TRIM_BFE : 0);
+}
+
 static inline u16 __imr_uvdp(u32 type)
 {
 	return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0);
@@ -674,15 +692,14 @@ static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh
  ******************************************************************************/
 
 /* ...calculate length of a type "c" mapping */
-static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size)
+static inline u32 imr_tri_type_c_get_length(int num, int item_size)
 {
-	return ((4 + 3 * item_size) * vbo->num + 4);
+	return ((4 + 3 * item_size) * num + 4);
 }
 
 /* ...set a VBO mapping using absolute coordinates */
-static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size)
+static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, int num, int item_size)
 {
-	int     num = vbo->num;
 	int     i;
 
 	/* ...prepare list of triangles to draw */
@@ -732,6 +749,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 	int     h = ctx->queue[0].fmt.height;
 	int     W = ctx->queue[1].fmt.width;
 	int     H = ctx->queue[1].fmt.height;
+	u32     tricr = ctx->color & 0xFFFFFF;
 
 	v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type);
 
@@ -739,11 +757,17 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 	*dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF);
 
 	/* ...set automatic source / destination coordinates generation flags */
-	*dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME);
+	*dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | __imr_bfe_tme(type));
+
+	/* ...that's probably not needed? - tbd */
+	*dl++ = IMR_OP_SYNCM;
 
 	/* ...set source / destination coordinate precision */
 	*dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type));
 
+	/* ...that's probably not needed? - tbd */
+	*dl++ = IMR_OP_SYNCM;
+
 	/* ...set luminance/chromacity correction parameters precision */
 	*dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type));
 
@@ -776,14 +800,12 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 		}
 	} else {
 		u16		src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0);
-		u32		dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0);
 
 		/* ...interleaved input; output is either interleaved or planar */
 		*dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt);
 
 		/* ...destination is always YUYV or UYVY */
-		*dl++ = IMR_OP_WTL(IMR_TRICR, 1);
-		*dl++ = dst_fmt;
+		tricr |= (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0);
 
 		/* ...set precision of Y/UV planes and required correction */
 		*dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type));
@@ -810,6 +832,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 	*dl++ = ((w - 2) << 16) | (w - 1);
 	*dl++ = h - 1;
 
+	/* ...set triangle single color */
+	*dl++ = IMR_OP_WTL(IMR_TRICR, 1);
+	*dl++ = tricr;
+
 	/* ...invoke subroutine for triangles drawing */
 	*dl++ = IMR_OP_GOSUB;
 	*dl++ = subaddr;
@@ -852,7 +878,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
 {
 	struct imr_device      *imr = ctx->imr;
 	struct imr_mesh        *mesh;
-	struct imr_vbo         *vbo;
+	int                     vbo_num;
 	struct imr_cfg         *cfg;
 	void                   *buf, *map;
 	u32                     type;
@@ -925,13 +951,6 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
 			tri_length = imr_tri_type_a_get_length(mesh, item_size);
 		}
 	} else {
-		/* ...assure we have proper VBO descriptor */
-		if (length < sizeof(struct imr_vbo)) {
-			v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length);
-			ret = -EINVAL;
-			goto out;
-		}
-
 		/* ...make sure there is no automatic-generation flags */
 		if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) {
 			v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type);
@@ -939,22 +958,23 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
 			goto out;
 		}
 
-		vbo = (struct imr_vbo *)buf;
-		length -= sizeof(struct imr_vbo);
-		map = buf + sizeof(struct imr_vbo);
+		map = buf;
 
 		/* ...vertex is given with absolute coordinates */
 		item_size += 8;
 
+		/* ...calculate total number of triangles */
+		vbo_num = length / (3 * item_size);
+
 		/* ...check the length is sane */
-		if (length != vbo->num * 3 * item_size) {
-			v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length);
+		if (length != vbo_num * 3 * item_size) {
+			v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo_num, item_size, length);
 			ret = -EINVAL;
 			goto out;
 		}
 
 		/* ...calculate size of trangles drawing subroutine */
-		tri_length = imr_tri_type_c_get_length(vbo, item_size);
+		tri_length = imr_tri_type_c_get_length(vbo_num, item_size);
 	}
 
 	/* ...DL main program shall start with 8-byte aligned address */
@@ -975,13 +995,16 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
 	imr_cfg_unref(ctx, ctx->cfg);
 
 	/* ...create new configuration */
-	ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset);
+	cfg = imr_cfg_create(ctx, dl_size, dl_start_offset);
 	if (IS_ERR(cfg)) {
 		ret = PTR_ERR(cfg);
+		ctx->cfg = NULL;
 		v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret);
 		goto out;
 	}
 
+	ctx->cfg = cfg;
+
 	/* ...get pointer to the new display list */
 	dl_vaddr = cfg->dl_vaddr;
 	dl_dma_addr = cfg->dl_dma_addr;
@@ -994,7 +1017,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
 			imr_tri_set_type_a(dl_vaddr, map, mesh, item_size);
 		}
 	} else {
-		imr_tri_set_type_c(dl_vaddr, map, vbo, item_size);
+		imr_tri_set_type_c(dl_vaddr, map, vbo_num, item_size);
 	}
 
 	/* ...prepare main DL-program */
@@ -1020,6 +1043,66 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
 	return ret;
 }
 
+/* ...set mapping data (function called with video device lock held) */
+static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc)
+{
+	struct imr_device      *imr = ctx->imr;
+	u32                     type = desc->type;
+	u32                     length = desc->size;
+	struct imr_cfg         *cfg;
+	void                   *dl_vaddr;
+	u32                     dl_size;
+	u32                     dl_start_offset;
+	dma_addr_t              dl_dma_addr;
+
+	/* ...calculate main routine length */
+	dl_size = imr_dl_program_length(ctx);
+	if (!dl_size) {
+		v4l2_err(&imr->v4l2_dev, "format configuration error\n");
+		return -EINVAL;
+	}
+
+	/* ...unref current configuration (will not be used by subsequent jobs) */
+	imr_cfg_unref(ctx, ctx->cfg);
+
+	/* ...create new configuration (starts with zero offset) */
+	cfg = imr_cfg_create(ctx, dl_size, 0);
+	if (IS_ERR(cfg)) {
+		ctx->cfg = NULL;
+		v4l2_err(&imr->v4l2_dev, "failed to create configuration: %ld\n", PTR_ERR(cfg));
+		return PTR_ERR(cfg);
+	}
+
+	ctx->cfg = cfg;
+
+	/* ...get pointer to the new display list */
+	dl_vaddr = cfg->dl_vaddr;
+
+	/* ...prepare main DL-program */
+	imr_dl_program_setup(ctx, cfg, type, dl_vaddr, (u32)(uintptr_t)desc->data);
+
+	/* ...update cropping parameters */
+	cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0);
+
+	/* ...display list updated successfully */
+	v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n",
+		cfg->id, (u32)dl_dma_addr, dl_size, 0);
+
+	if (debug >= 4)
+		print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset);
+
+	/* ...success */
+	return 0;
+}
+
+/* ...set mapping data (function called with video device lock held) */
+static int imr_ioctl_color(struct imr_ctx *ctx, u32 color)
+{
+	ctx->color = color;
+
+	return 0;
+}
+
 /*******************************************************************************
  * V4L2 I/O controls
  ******************************************************************************/
@@ -1183,7 +1266,7 @@ static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	WARN_ON(!mutex_is_locked(&ctx->imr->mutex));
 
 	/* ...verify the configuration is complete */
-	if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) {
+	if (!ctx->cfg) {
 		v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n");
 		return -EINVAL;
 	}
@@ -1265,6 +1348,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i
 		/* ...set mesh data */
 		return imr_ioctl_map(ctx, (struct imr_map_desc *)arg);
 
+	case VIDIOC_IMR_MESH_RAW:
+		/* ...set mesh data */
+		return imr_ioctl_map_raw(ctx, (struct imr_map_desc *)arg);
+
+	case VIDIOC_IMR_COLOR:
+		/* ...set solid color code */
+		return imr_ioctl_color(ctx, *(u32 *)arg);
+
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -1326,6 +1417,9 @@ static int imr_open(struct file *file)
 	/* ...set default cropping parameters */
 	ctx->crop[1] = ctx->crop[3] = 0x3FF;
 
+	/* ...set default color */
+	ctx->color = 0x808080;
+
 	/* ...initialize M2M processing context */
 	ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init);
 	if (IS_ERR(ctx->m2m_ctx)) {
@@ -1418,8 +1512,11 @@ static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait)
 		return -ERESTARTSYS;
 
 	res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+
 	mutex_unlock(&imr->mutex);
 
+	v4l2_dbg(3, debug, &imr->v4l2_dev, "poll result: %X (ctx=%p)\n", res, ctx);
+
 	return res;
 }
 
@@ -1453,7 +1550,6 @@ static const struct v4l2_file_operations imr_fops = {
  * M2M device interface
  ******************************************************************************/
 
-#if 0
 /* ...job cleanup function */
 static void imr_cleanup(struct imr_ctx *ctx)
 {
@@ -1473,17 +1569,16 @@ static void imr_cleanup(struct imr_ctx *ctx)
 	/* ...release lock before we mark current job as finished */
 	spin_unlock_irqrestore(&imr->lock, flags);
 }
-#endif
 
 /* ...job execution function */
 static void imr_device_run(void *priv)
 {
-	struct imr_ctx     *ctx = priv;
-	struct imr_device  *imr = ctx->imr;
-	struct imr_cfg     *cfg;
-	struct vb2_buffer  *src_buf, *dst_buf;
-	u32                 src_addr, dst_addr;
-	unsigned long       flags;
+	struct imr_ctx         *ctx = priv;
+	struct imr_device      *imr = ctx->imr;
+	struct imr_cfg         *cfg;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	u32                     src_addr, dst_addr;
+	unsigned long           flags;
 
 	v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n");
 
@@ -1494,8 +1589,11 @@ static void imr_device_run(void *priv)
 	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 
+	/* ...put source/destination buffers sequence numbers */
+	dst_buf->sequence = src_buf->sequence = ctx->sequence++;
+
 	/* ...take configuration pointer associated with input buffer */
-	cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg;
+	cfg = to_imr_buffer(src_buf)->cfg;
 
 	/* ...cancel software reset state as needed */
 	iowrite32(0, imr->mmio + IMR_CR);
@@ -1507,8 +1605,8 @@ static void imr_device_run(void *priv)
 	iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR);
 
 	/* ...adjust source/destination parameters of the program (interleaved / semiplanar) */
-	*cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0);
-	*cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	*cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+	*cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
 
 	/* ...adjust source/destination parameters of the UV-plane as needed */
 	if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) {
@@ -1529,6 +1627,9 @@ static void imr_device_run(void *priv)
 	/* ...set display list address */
 	iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR);
 
+	/* ...enable texture prefetching */
+	iowrite32(0xACCE5501, imr->mmio + IMR_TPOR);
+
 	/* ...explicitly flush any pending write operations (don't need that, I guess) */
 	wmb();
 
@@ -1536,7 +1637,7 @@ static void imr_device_run(void *priv)
 	iowrite32(IMR_CR_RS, imr->mmio + IMR_CR);
 
 	/* ...timestamp input buffer */
-	src_buf->timestamp = ktime_get_ns();
+	src_buf->vb2_buf.timestamp = ktime_get_ns();
 
 	/* ...unlock device access */
 	spin_unlock_irqrestore(&imr->lock, flags);
@@ -1633,13 +1734,14 @@ static irqreturn_t imr_irq_handler(int irq, void *data)
 			dst_buf->timecode = src_buf->timecode;
 		dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME |
 			 V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
-		dst_buf->sequence = src_buf->sequence = ctx->sequence++;
+		//dst_buf->sequence = src_buf->sequence = ctx->sequence++;
+
 		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
 		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
 
-		v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n",
+		v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done (ctx=%p)\n",
 			(u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0),
-			(u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0));
+			(u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), ctx);
 	} else {
 		/* ...operation completed in error; no way to understand what exactly went wrong */
 		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
@@ -1668,6 +1770,8 @@ static irqreturn_t imr_irq_handler(int irq, void *data)
  * Device probing / removal interface
  ******************************************************************************/
 
+static struct class *imr_alloc_class;
+
 static int imr_probe(struct platform_device *pdev)
 {
 	struct imr_device *imr;
@@ -1727,6 +1831,26 @@ static int imr_probe(struct platform_device *pdev)
 		goto device_register_rollback;
 	}
 
+	if (!imr_alloc_class) {
+		imr_alloc_class = class_create(THIS_MODULE, "imr-alloc");
+		if (IS_ERR(imr_alloc_class)) {
+			v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device class\n");
+			ret = PTR_ERR(imr_alloc_class);
+			goto m2m_init_rollback;
+		}
+	}
+
+	struct device *adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, "%s_alloc", dev_name(&pdev->dev));
+	if (IS_ERR(adev)) {
+		v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device\n");
+		ret = PTR_ERR(adev);
+		goto m2m_init_rollback;
+	}
+	adev->dma_mask = &adev->coherent_dma_mask;
+	adev->coherent_dma_mask = DMA_BIT_MASK(32);
+	arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true);
+	imr->alloc_dev = adev;
+
 	strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name));
 	imr->video_dev.fops         = &imr_fops;
 	imr->video_dev.ioctl_ops    = &imr_ioctl_ops;
@@ -1765,6 +1889,7 @@ static int imr_remove(struct platform_device *pdev)
 
 	//pm_runtime_disable(imr->v4l2_dev.dev);
 	video_unregister_device(&imr->video_dev);
+	//device_destroy(imr->alloc_dev, MKDEV(0, 0));
 	v4l2_m2m_release(imr->m2m_dev);
 	v4l2_device_unregister(&imr->v4l2_dev);
 
diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h
index d02082f..7b8ed0c 100644
--- a/include/uapi/linux/rcar-imr.h
+++ b/include/uapi/linux/rcar-imr.h
@@ -48,6 +48,12 @@ struct imr_map_desc {
 /* ...vertex clockwise-mode order */
 #define IMR_MAP_TCM                     (1 << 5)
 
+/* ...texture mapping enable flag */
+#define IMR_MAP_TME                     (1 << 6)
+
+/* ...bilinear filtration enable flag */
+#define IMR_MAP_BFE                     (1 << 7)
+
 /* ...source coordinate decimal point position bit index */
 #define __IMR_MAP_UVDPOR_SHIFT          8
 #define __IMR_MAP_UVDPOR(v)             (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7)
@@ -81,18 +87,12 @@ struct imr_mesh {
 
 }   __attribute__((packed));
 
-/* ...VBO descriptor */
-struct imr_vbo {
-	/* ...number of triangles */
-	u16             num;
-
-}   __attribute__((packed));
-
-
 /*******************************************************************************
  * Private IOCTL codes
  ******************************************************************************/
 
 #define VIDIOC_IMR_MESH                 _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc)
+#define VIDIOC_IMR_MESH_RAW             _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc)
+#define VIDIOC_IMR_COLOR                _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32)
 
 #endif  /* RCAR_IMR_USER_H */
-- 
2.7.4