aboutsummaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch
blob: 42d2e32bcf3dccaf0efc79a87f9b453bf334df70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
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