]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/media/platform/mxc/output/mxc_pxp_v4l2.c
d18043124b12cf3cc0b1d02c81153cca22daaced
[karo-tx-linux.git] / drivers / media / platform / mxc / output / mxc_pxp_v4l2.c
1 /*
2  * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  *
18  */
19 /*
20  * Based on STMP378X PxP driver
21  * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
22  */
23
24 #include <linux/dma-mapping.h>
25 #include <linux/fb.h>
26 #include <linux/init.h>
27 #include <linux/interrupt.h>
28 #include <linux/io.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/mutex.h>
32 #include <linux/platform_device.h>
33 #include <linux/vmalloc.h>
34 #include <linux/videodev2.h>
35 #include <linux/dmaengine.h>
36 #include <linux/pxp_dma.h>
37 #include <linux/delay.h>
38 #include <linux/console.h>
39 #include <linux/mxcfb.h>
40
41 #include <media/videobuf-dma-contig.h>
42 #include <media/v4l2-common.h>
43 #include <media/v4l2-dev.h>
44 #include <media/v4l2-ioctl.h>
45
46 #include "mxc_pxp_v4l2.h"
47
48 #define PXP_DRIVER_NAME                 "pxp-v4l2"
49 #define PXP_DRIVER_MAJOR                2
50 #define PXP_DRIVER_MINOR                0
51
52 #define PXP_DEF_BUFS                    2
53 #define PXP_MIN_PIX                     8
54
55 #define V4L2_OUTPUT_TYPE_INTERNAL       4
56
57 static int video_nr = -1;       /* -1 ==> auto assign */
58 static struct pxp_data_format pxp_s0_formats[] = {
59         {
60                 .name = "24-bit RGB",
61                 .bpp = 4,
62                 .fourcc = V4L2_PIX_FMT_RGB24,
63                 .colorspace = V4L2_COLORSPACE_SRGB,
64         }, {
65                 .name = "16-bit RGB 5:6:5",
66                 .bpp = 2,
67                 .fourcc = V4L2_PIX_FMT_RGB565,
68                 .colorspace = V4L2_COLORSPACE_SRGB,
69         }, {
70                 .name = "16-bit RGB 5:5:5",
71                 .bpp = 2,
72                 .fourcc = V4L2_PIX_FMT_RGB555,
73                 .colorspace = V4L2_COLORSPACE_SRGB,
74         }, {
75                 .name = "YUV 4:2:0 Planar",
76                 .bpp = 2,
77                 .fourcc = V4L2_PIX_FMT_YUV420,
78                 .colorspace = V4L2_COLORSPACE_JPEG,
79         }, {
80                 .name = "YUV 4:2:2 Planar",
81                 .bpp = 2,
82                 .fourcc = V4L2_PIX_FMT_YUV422P,
83                 .colorspace = V4L2_COLORSPACE_JPEG,
84         },
85 };
86
87 static unsigned int v4l2_fmt_to_pxp_fmt(u32 v4l2_pix_fmt)
88 {
89         u32 pxp_fmt = 0;
90
91         if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB24)
92                 pxp_fmt = PXP_PIX_FMT_RGB24;
93         else if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB565)
94                 pxp_fmt = PXP_PIX_FMT_RGB565;
95         else if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB555)
96                 pxp_fmt = PXP_PIX_FMT_RGB555;
97         else if (v4l2_pix_fmt == V4L2_PIX_FMT_RGB555)
98                 pxp_fmt = PXP_PIX_FMT_RGB555;
99         else if (v4l2_pix_fmt == V4L2_PIX_FMT_YUV420)
100                 pxp_fmt = PXP_PIX_FMT_YUV420P;
101         else if (v4l2_pix_fmt == V4L2_PIX_FMT_YUV422P)
102                 pxp_fmt = PXP_PIX_FMT_YUV422P;
103
104         return pxp_fmt;
105 }
106 struct v4l2_queryctrl pxp_controls[] = {
107         {
108                 .id             = V4L2_CID_HFLIP,
109                 .type           = V4L2_CTRL_TYPE_BOOLEAN,
110                 .name           = "Horizontal Flip",
111                 .minimum        = 0,
112                 .maximum        = 1,
113                 .step           = 1,
114                 .default_value  = 0,
115                 .flags          = 0,
116         }, {
117                 .id             = V4L2_CID_VFLIP,
118                 .type           = V4L2_CTRL_TYPE_BOOLEAN,
119                 .name           = "Vertical Flip",
120                 .minimum        = 0,
121                 .maximum        = 1,
122                 .step           = 1,
123                 .default_value  = 0,
124                 .flags          = 0,
125         }, {
126                 .id             = V4L2_CID_PRIVATE_BASE,
127                 .type           = V4L2_CTRL_TYPE_INTEGER,
128                 .name           = "Rotation",
129                 .minimum        = 0,
130                 .maximum        = 270,
131                 .step           = 90,
132                 .default_value  = 0,
133                 .flags          = 0,
134         }, {
135                 .id             = V4L2_CID_PRIVATE_BASE + 1,
136                 .name           = "Background Color",
137                 .minimum        = 0,
138                 .maximum        = 0xFFFFFF,
139                 .step           = 1,
140                 .default_value  = 0,
141                 .flags          = 0,
142                 .type           = V4L2_CTRL_TYPE_INTEGER,
143         }, {
144                 .id             = V4L2_CID_PRIVATE_BASE + 2,
145                 .name           = "Set S0 Chromakey",
146                 .minimum        = -1,
147                 .maximum        = 0xFFFFFF,
148                 .step           = 1,
149                 .default_value  = -1,
150                 .flags          = 0,
151                 .type           = V4L2_CTRL_TYPE_INTEGER,
152         }, {
153                 .id             = V4L2_CID_PRIVATE_BASE + 3,
154                 .name           = "YUV Colorspace",
155                 .minimum        = 0,
156                 .maximum        = 1,
157                 .step           = 1,
158                 .default_value  = 0,
159                 .flags          = 0,
160                 .type           = V4L2_CTRL_TYPE_BOOLEAN,
161         },
162 };
163
164 /* callback function */
165 static void video_dma_done(void *arg)
166 {
167         struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
168         struct dma_chan *chan = tx_desc->txd.chan;
169         struct pxp_channel *pxp_chan = to_pxp_channel(chan);
170         struct pxps *pxp = pxp_chan->client;
171         struct videobuf_buffer *vb;
172
173         dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n",
174                         tx_desc->txd.cookie,
175                         pxp->active ? sg_dma_address(&pxp->active->sg[0]) : 0);
176
177         spin_lock(&pxp->lock);
178         if (pxp->active) {
179                 vb = &pxp->active->vb;
180
181                 list_del_init(&vb->queue);
182                 vb->state = VIDEOBUF_DONE;
183                 do_gettimeofday(&vb->ts);
184                 vb->field_count++;
185                 wake_up(&vb->done);
186         }
187
188         if (list_empty(&pxp->outq)) {
189                 pxp->active = NULL;
190                 spin_unlock(&pxp->lock);
191
192                 return;
193         }
194
195         pxp->active = list_entry(pxp->outq.next,
196                                      struct pxp_buffer, vb.queue);
197         pxp->active->vb.state = VIDEOBUF_ACTIVE;
198         spin_unlock(&pxp->lock);
199 }
200
201 static int acquire_dma_channel(struct pxps *pxp)
202 {
203         dma_cap_mask_t mask;
204         struct dma_chan *chan;
205         struct pxp_channel **pchan = &pxp->pxp_channel[0];
206
207         if (*pchan) {
208                 struct videobuf_buffer *vb, *_vb;
209                 dma_release_channel(&(*pchan)->dma_chan);
210                 *pchan = NULL;
211                 pxp->active = NULL;
212                 list_for_each_entry_safe(vb, _vb, &pxp->outq, queue) {
213                         list_del_init(&vb->queue);
214                         vb->state = VIDEOBUF_ERROR;
215                         wake_up(&vb->done);
216                 }
217         }
218
219         dma_cap_zero(mask);
220         dma_cap_set(DMA_SLAVE, mask);
221         dma_cap_set(DMA_PRIVATE, mask);
222         chan = dma_request_channel(mask, NULL, NULL);
223         if (!chan)
224                 return -EBUSY;
225
226         *pchan = to_pxp_channel(chan);
227         (*pchan)->client = pxp;
228
229         return 0;
230 }
231
232 static int _get_fbinfo(struct fb_info **fbi)
233 {
234         int i;
235         for (i = 0; i < num_registered_fb; i++) {
236                 char *idstr = registered_fb[i]->fix.id;
237                 if (strcmp(idstr, "mxs") == 0) {
238                         *fbi = registered_fb[i];
239                         return 0;
240                 }
241         }
242
243         return -ENODEV;
244 }
245
246 static int pxp_set_fbinfo(struct pxps *pxp)
247 {
248         struct v4l2_framebuffer *fb = &pxp->fb;
249         int err;
250
251         err = _get_fbinfo(&pxp->fbi);
252         if (err)
253                 return err;
254
255         fb->fmt.width = pxp->fbi->var.xres;
256         fb->fmt.height = pxp->fbi->var.yres;
257         pxp->pxp_conf.out_param.stride = pxp->fbi->var.xres;
258         if (pxp->fbi->var.bits_per_pixel == 16)
259                 fb->fmt.pixelformat = V4L2_PIX_FMT_RGB565;
260         else
261                 fb->fmt.pixelformat = V4L2_PIX_FMT_RGB24;
262
263         fb->base = (void *)pxp->fbi->fix.smem_start;
264
265         return 0;
266 }
267
268 static int _get_cur_fb_blank(struct pxps *pxp)
269 {
270         struct fb_info *fbi;
271         mm_segment_t old_fs;
272         int err = 0;
273
274         err = _get_fbinfo(&fbi);
275         if (err)
276                 return err;
277
278         if (fbi->fbops->fb_ioctl) {
279                 old_fs = get_fs();
280                 set_fs(KERNEL_DS);
281                 err = fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_BLANK,
282                                 (unsigned int)(&pxp->fb_blank));
283                 set_fs(old_fs);
284         }
285
286         return err;
287 }
288
289 static int pxp_show_buf(struct pxps *pxp, bool toshow)
290 {
291         struct fb_info *fbi = pxp->fbi;
292         int ret;
293
294         console_lock();
295         fbi->fix.smem_start = toshow ?
296                         pxp->outb_phys : (unsigned long)pxp->fb.base;
297         ret = fb_pan_display(fbi, &fbi->var);
298         console_unlock();
299
300         return ret;
301 }
302
303 static int set_fb_blank(int blank)
304 {
305         struct fb_info *fbi;
306         int err = 0;
307
308         err = _get_fbinfo(&fbi);
309         if (err)
310                 return err;
311
312         console_lock();
313         fb_blank(fbi, blank);
314         console_unlock();
315
316         return err;
317 }
318
319 static int pxp_set_cstate(struct pxps *pxp, struct v4l2_control *vc)
320 {
321
322         if (vc->id == V4L2_CID_HFLIP) {
323                 pxp->pxp_conf.proc_data.hflip = vc->value;
324         } else if (vc->id == V4L2_CID_VFLIP) {
325                 pxp->pxp_conf.proc_data.vflip = vc->value;
326         } else if (vc->id == V4L2_CID_PRIVATE_BASE) {
327                 if (vc->value % 90)
328                         return -ERANGE;
329                 pxp->pxp_conf.proc_data.rotate = vc->value;
330         } else if (vc->id == V4L2_CID_PRIVATE_BASE + 1) {
331                 pxp->pxp_conf.proc_data.bgcolor = vc->value;
332         } else if (vc->id == V4L2_CID_PRIVATE_BASE + 2) {
333                 pxp->pxp_conf.s0_param.color_key = vc->value;
334         } else if (vc->id == V4L2_CID_PRIVATE_BASE + 3) {
335                 pxp->pxp_conf.proc_data.yuv = vc->value;
336         }
337
338         return 0;
339 }
340
341 static int pxp_get_cstate(struct pxps *pxp, struct v4l2_control *vc)
342 {
343         if (vc->id == V4L2_CID_HFLIP)
344                 vc->value = pxp->pxp_conf.proc_data.hflip;
345         else if (vc->id == V4L2_CID_VFLIP)
346                 vc->value = pxp->pxp_conf.proc_data.vflip;
347         else if (vc->id == V4L2_CID_PRIVATE_BASE)
348                 vc->value = pxp->pxp_conf.proc_data.rotate;
349         else if (vc->id == V4L2_CID_PRIVATE_BASE + 1)
350                 vc->value = pxp->pxp_conf.proc_data.bgcolor;
351         else if (vc->id == V4L2_CID_PRIVATE_BASE + 2)
352                 vc->value = pxp->pxp_conf.s0_param.color_key;
353         else if (vc->id == V4L2_CID_PRIVATE_BASE + 3)
354                 vc->value = pxp->pxp_conf.proc_data.yuv;
355
356         return 0;
357 }
358
359 static int pxp_enumoutput(struct file *file, void *fh,
360                         struct v4l2_output *o)
361 {
362         struct pxps *pxp = video_get_drvdata(video_devdata(file));
363
364         if ((o->index < 0) || (o->index > 1))
365                 return -EINVAL;
366
367         memset(o, 0, sizeof(struct v4l2_output));
368         if (o->index == 0) {
369                 strcpy(o->name, "PxP Display Output");
370                 pxp->output = 0;
371         } else {
372                 strcpy(o->name, "PxP Virtual Output");
373                 pxp->output = 1;
374         }
375         o->type = V4L2_OUTPUT_TYPE_INTERNAL;
376         o->std = 0;
377         o->reserved[0] = pxp->outb_phys;
378
379         return 0;
380 }
381
382 static int pxp_g_output(struct file *file, void *fh,
383                         unsigned int *i)
384 {
385         struct pxps *pxp = video_get_drvdata(video_devdata(file));
386
387         *i = pxp->output;
388
389         return 0;
390 }
391
392 static int pxp_s_output(struct file *file, void *fh,
393                         unsigned int i)
394 {
395         struct pxps *pxp = video_get_drvdata(video_devdata(file));
396         struct v4l2_pix_format *fmt = &pxp->fb.fmt;
397         int bpp;
398
399         if ((i < 0) || (i > 1))
400                 return -EINVAL;
401
402         if (pxp->outb)
403                 return 0;
404
405         /* Output buffer is same format as fbdev */
406         if (fmt->pixelformat == V4L2_PIX_FMT_RGB24)
407                 bpp = 4;
408         else
409                 bpp = 2;
410
411         pxp->outb_size = fmt->width * fmt->height * bpp;
412         pxp->outb = kmalloc(fmt->width * fmt->height * bpp,
413                                 GFP_KERNEL | GFP_DMA);
414         if (pxp->outb == NULL) {
415                 dev_err(&pxp->pdev->dev, "No enough memory!\n");
416                 return -ENOMEM;
417         }
418         pxp->outb_phys = virt_to_phys(pxp->outb);
419         dma_map_single(NULL, pxp->outb,
420                         fmt->width * fmt->height * bpp, DMA_TO_DEVICE);
421
422         pxp->pxp_conf.out_param.width = fmt->width;
423         pxp->pxp_conf.out_param.height = fmt->height;
424         if (fmt->pixelformat == V4L2_PIX_FMT_RGB24)
425                 pxp->pxp_conf.out_param.pixel_fmt = PXP_PIX_FMT_RGB24;
426         else
427                 pxp->pxp_conf.out_param.pixel_fmt = PXP_PIX_FMT_RGB565;
428
429         return 0;
430 }
431
432 static int pxp_enum_fmt_video_output(struct file *file, void *fh,
433                                 struct v4l2_fmtdesc *fmt)
434 {
435         enum v4l2_buf_type type = fmt->type;
436         int index = fmt->index;
437
438         if ((fmt->index < 0) || (fmt->index >= ARRAY_SIZE(pxp_s0_formats)))
439                 return -EINVAL;
440
441         memset(fmt, 0, sizeof(struct v4l2_fmtdesc));
442         fmt->index = index;
443         fmt->type = type;
444         fmt->pixelformat = pxp_s0_formats[index].fourcc;
445         strcpy(fmt->description, pxp_s0_formats[index].name);
446
447         return 0;
448 }
449
450 static int pxp_g_fmt_video_output(struct file *file, void *fh,
451                                 struct v4l2_format *f)
452 {
453         struct v4l2_pix_format *pf = &f->fmt.pix;
454         struct pxps *pxp = video_get_drvdata(video_devdata(file));
455         struct pxp_data_format *fmt = pxp->s0_fmt;
456
457         pf->width = pxp->pxp_conf.s0_param.width;
458         pf->height = pxp->pxp_conf.s0_param.height;
459         pf->pixelformat = fmt->fourcc;
460         pf->field = V4L2_FIELD_NONE;
461         pf->bytesperline = fmt->bpp * pf->width;
462         pf->sizeimage = pf->bytesperline * pf->height;
463         pf->colorspace = fmt->colorspace;
464         pf->priv = 0;
465
466         return 0;
467 }
468
469 static struct pxp_data_format *pxp_get_format(struct v4l2_format *f)
470 {
471         struct pxp_data_format *fmt;
472         int i;
473
474         for (i = 0; i < ARRAY_SIZE(pxp_s0_formats); i++) {
475                 fmt = &pxp_s0_formats[i];
476                 if (fmt->fourcc == f->fmt.pix.pixelformat)
477                         break;
478         }
479
480         if (i == ARRAY_SIZE(pxp_s0_formats))
481                 return NULL;
482
483         return &pxp_s0_formats[i];
484 }
485
486 static int pxp_try_fmt_video_output(struct file *file, void *fh,
487                                 struct v4l2_format *f)
488 {
489         int w = f->fmt.pix.width;
490         int h = f->fmt.pix.height;
491         struct pxp_data_format *fmt = pxp_get_format(f);
492
493         if (!fmt)
494                 return -EINVAL;
495
496         w = min(w, 2040);
497         w = max(w, 8);
498         h = min(h, 2040);
499         h = max(h, 8);
500         f->fmt.pix.field = V4L2_FIELD_NONE;
501         f->fmt.pix.width = w;
502         f->fmt.pix.height = h;
503         f->fmt.pix.pixelformat = fmt->fourcc;
504
505         return 0;
506 }
507
508 static int pxp_s_fmt_video_output(struct file *file, void *fh,
509                                 struct v4l2_format *f)
510 {
511         struct pxps *pxp = video_get_drvdata(video_devdata(file));
512         struct v4l2_pix_format *pf = &f->fmt.pix;
513         int ret;
514
515         ret = acquire_dma_channel(pxp);
516         if (ret < 0)
517                 return ret;
518
519         ret = pxp_try_fmt_video_output(file, fh, f);
520         if (ret == 0) {
521                 pxp->s0_fmt = pxp_get_format(f);
522                 pxp->pxp_conf.s0_param.pixel_fmt =
523                         v4l2_fmt_to_pxp_fmt(pxp->s0_fmt->fourcc);
524                 pxp->pxp_conf.s0_param.width = pf->width;
525                 pxp->pxp_conf.s0_param.height = pf->height;
526         }
527
528
529         return ret;
530 }
531
532 static int pxp_g_fmt_output_overlay(struct file *file, void *fh,
533                                 struct v4l2_format *f)
534 {
535         struct pxps *pxp = video_get_drvdata(video_devdata(file));
536         struct v4l2_window *wf = &f->fmt.win;
537
538         memset(wf, 0, sizeof(struct v4l2_window));
539         wf->chromakey = pxp->s1_chromakey;
540         wf->global_alpha = pxp->global_alpha;
541         wf->field = V4L2_FIELD_NONE;
542         wf->clips = NULL;
543         wf->clipcount = 0;
544         wf->bitmap = NULL;
545         wf->w.left = pxp->pxp_conf.proc_data.srect.left;
546         wf->w.top = pxp->pxp_conf.proc_data.srect.top;
547         wf->w.width = pxp->pxp_conf.proc_data.srect.width;
548         wf->w.height = pxp->pxp_conf.proc_data.srect.height;
549
550         return 0;
551 }
552
553 static int pxp_try_fmt_output_overlay(struct file *file, void *fh,
554                                 struct v4l2_format *f)
555 {
556         struct pxps *pxp = video_get_drvdata(video_devdata(file));
557         struct v4l2_window *wf = &f->fmt.win;
558         struct v4l2_rect srect;
559         u32 s1_chromakey = wf->chromakey;
560         u8 global_alpha = wf->global_alpha;
561
562         memcpy(&srect, &(wf->w), sizeof(struct v4l2_rect));
563
564         pxp_g_fmt_output_overlay(file, fh, f);
565
566         wf->chromakey = s1_chromakey;
567         wf->global_alpha = global_alpha;
568
569         /* Constrain parameters to the input buffer */
570         wf->w.left = srect.left;
571         wf->w.top = srect.top;
572         wf->w.width = min(srect.width,
573                         ((__s32)pxp->pxp_conf.s0_param.width - wf->w.left));
574         wf->w.height = min(srect.height,
575                         ((__s32)pxp->pxp_conf.s0_param.height - wf->w.top));
576
577         return 0;
578 }
579
580 static int pxp_s_fmt_output_overlay(struct file *file, void *fh,
581                                         struct v4l2_format *f)
582 {
583         struct pxps *pxp = video_get_drvdata(video_devdata(file));
584         struct v4l2_window *wf = &f->fmt.win;
585         int ret = pxp_try_fmt_output_overlay(file, fh, f);
586
587         if (ret == 0) {
588                 pxp->global_alpha = wf->global_alpha;
589                 pxp->s1_chromakey = wf->chromakey;
590                 pxp->pxp_conf.proc_data.srect.left = wf->w.left;
591                 pxp->pxp_conf.proc_data.srect.top = wf->w.top;
592                 pxp->pxp_conf.proc_data.srect.width = wf->w.width;
593                 pxp->pxp_conf.proc_data.srect.height = wf->w.height;
594                 pxp->pxp_conf.ol_param[0].global_alpha = pxp->global_alpha;
595                 pxp->pxp_conf.ol_param[0].color_key = pxp->s1_chromakey;
596                 pxp->pxp_conf.ol_param[0].color_key_enable =
597                                         pxp->s1_chromakey_state;
598         }
599
600         return ret;
601 }
602
603 static int pxp_reqbufs(struct file *file, void *priv,
604                         struct v4l2_requestbuffers *r)
605 {
606         struct pxps *pxp = video_get_drvdata(video_devdata(file));
607
608         return videobuf_reqbufs(&pxp->s0_vbq, r);
609 }
610
611 static int pxp_querybuf(struct file *file, void *priv,
612                         struct v4l2_buffer *b)
613 {
614         struct pxps *pxp = video_get_drvdata(video_devdata(file));
615
616         return videobuf_querybuf(&pxp->s0_vbq, b);
617 }
618
619 static int pxp_qbuf(struct file *file, void *priv,
620                         struct v4l2_buffer *b)
621 {
622         struct pxps *pxp = video_get_drvdata(video_devdata(file));
623
624         return videobuf_qbuf(&pxp->s0_vbq, b);
625 }
626
627 static int pxp_dqbuf(struct file *file, void *priv,
628                         struct v4l2_buffer *b)
629 {
630         struct pxps *pxp = video_get_drvdata(video_devdata(file));
631
632         return videobuf_dqbuf(&pxp->s0_vbq, b, file->f_flags & O_NONBLOCK);
633 }
634
635 static int pxp_streamon(struct file *file, void *priv,
636                         enum v4l2_buf_type t)
637 {
638         struct pxps *pxp = video_get_drvdata(video_devdata(file));
639         int ret = 0;
640
641         if (t != V4L2_BUF_TYPE_VIDEO_OUTPUT)
642                 return -EINVAL;
643
644         _get_cur_fb_blank(pxp);
645         set_fb_blank(FB_BLANK_UNBLANK);
646
647         ret = videobuf_streamon(&pxp->s0_vbq);
648
649         if (!ret && (pxp->output == 0))
650                 pxp_show_buf(pxp, true);
651
652         return ret;
653 }
654
655 static int pxp_streamoff(struct file *file, void *priv,
656                         enum v4l2_buf_type t)
657 {
658         struct pxps *pxp = video_get_drvdata(video_devdata(file));
659         int ret = 0;
660
661         if ((t != V4L2_BUF_TYPE_VIDEO_OUTPUT))
662                 return -EINVAL;
663
664         ret = videobuf_streamoff(&pxp->s0_vbq);
665
666         if (!ret)
667                 pxp_show_buf(pxp, false);
668
669         if (pxp->fb_blank)
670                 set_fb_blank(FB_BLANK_POWERDOWN);
671
672         return ret;
673 }
674
675 static int pxp_buf_setup(struct videobuf_queue *q,
676                         unsigned int *count, unsigned *size)
677 {
678         struct pxps *pxp = q->priv_data;
679
680         *size = pxp->pxp_conf.s0_param.width *
681                 pxp->pxp_conf.s0_param.height * pxp->s0_fmt->bpp;
682
683         if (0 == *count)
684                 *count = PXP_DEF_BUFS;
685
686         return 0;
687 }
688
689 static void pxp_buf_free(struct videobuf_queue *q, struct pxp_buffer *buf)
690 {
691         struct videobuf_buffer *vb = &buf->vb;
692         struct dma_async_tx_descriptor *txd = buf->txd;
693
694         BUG_ON(in_interrupt());
695
696         pr_debug("%s (vb=0x%p) 0x%08lx %d\n", __func__,
697                 vb, vb->baddr, vb->bsize);
698
699         /*
700          * This waits until this buffer is out of danger, i.e., until it is no
701          * longer in STATE_QUEUED or STATE_ACTIVE
702          */
703         videobuf_waiton(q, vb, 0, 0);
704         if (txd)
705                 async_tx_ack(txd);
706
707         videobuf_dma_contig_free(q, vb);
708         buf->txd = NULL;
709
710         vb->state = VIDEOBUF_NEEDS_INIT;
711 }
712
713 static int pxp_buf_prepare(struct videobuf_queue *q,
714                         struct videobuf_buffer *vb,
715                         enum v4l2_field field)
716 {
717         struct pxps *pxp = q->priv_data;
718         struct pxp_config_data *pxp_conf = &pxp->pxp_conf;
719         struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
720         struct pxp_buffer *buf = container_of(vb, struct pxp_buffer, vb);
721         struct pxp_tx_desc *desc;
722         int ret = 0;
723         int i, length;
724
725         vb->width = pxp->pxp_conf.s0_param.width;
726         vb->height = pxp->pxp_conf.s0_param.height;
727         vb->size = vb->width * vb->height * pxp->s0_fmt->bpp;
728         vb->field = V4L2_FIELD_NONE;
729         if (vb->state != VIDEOBUF_NEEDS_INIT)
730                 pxp_buf_free(q, buf);
731
732         if (vb->state == VIDEOBUF_NEEDS_INIT) {
733                 struct pxp_channel *pchan = pxp->pxp_channel[0];
734                 struct scatterlist *sg = &buf->sg[0];
735
736                 /* This actually (allocates and) maps buffers */
737                 ret = videobuf_iolock(q, vb, NULL);
738                 if (ret) {
739                         pr_err("fail to call videobuf_iolock, ret = %d\n", ret);
740                         goto fail;
741                 }
742
743                 /*
744                  * sg[0] for input(S0)
745                  * Sg[1] for output
746                  */
747                 sg_init_table(sg, 3);
748
749                 buf->txd = pchan->dma_chan.device->device_prep_slave_sg(
750                         &pchan->dma_chan, sg, 3, DMA_FROM_DEVICE,
751                         DMA_PREP_INTERRUPT, NULL);
752                 if (!buf->txd) {
753                         ret = -EIO;
754                         goto fail;
755                 }
756
757                 buf->txd->callback_param        = buf->txd;
758                 buf->txd->callback              = video_dma_done;
759
760                 desc = to_tx_desc(buf->txd);
761                 length = desc->len;
762                 for (i = 0; i < length; i++) {
763                         if (i == 0) {/* S0 */
764                                 memcpy(&desc->proc_data, proc_data,
765                                         sizeof(struct pxp_proc_data));
766                                 pxp_conf->s0_param.paddr =
767                                                 videobuf_to_dma_contig(vb);
768                                 memcpy(&desc->layer_param.s0_param,
769                                         &pxp_conf->s0_param,
770                                         sizeof(struct pxp_layer_param));
771                         } else if (i == 1) { /* Output */
772                                 if (proc_data->rotate % 180) {
773                                         pxp_conf->out_param.width =
774                                                 pxp->fb.fmt.height;
775                                         pxp_conf->out_param.height =
776                                                 pxp->fb.fmt.width;
777                                 } else {
778                                         pxp_conf->out_param.width =
779                                                 pxp->fb.fmt.width;
780                                         pxp_conf->out_param.height =
781                                                 pxp->fb.fmt.height;
782                                 }
783
784                                 pxp_conf->out_param.paddr = pxp->outb_phys;
785                                 memcpy(&desc->layer_param.out_param,
786                                         &pxp_conf->out_param,
787                                         sizeof(struct pxp_layer_param));
788                         } else if (pxp_conf->ol_param[0].combine_enable) {
789                                 /* Overlay */
790                                 pxp_conf->ol_param[0].paddr =
791                                                 (dma_addr_t)pxp->fb.base;
792                                 pxp_conf->ol_param[0].width = pxp->fb.fmt.width;
793                                 pxp_conf->ol_param[0].height =
794                                                 pxp->fb.fmt.height;
795                                 pxp_conf->ol_param[0].pixel_fmt =
796                                                 pxp_conf->out_param.pixel_fmt;
797                                 memcpy(&desc->layer_param.ol_param,
798                                        &pxp_conf->ol_param[0],
799                                        sizeof(struct pxp_layer_param));
800                         }
801
802                         desc = desc->next;
803                 }
804
805                 vb->state = VIDEOBUF_PREPARED;
806         }
807
808         return 0;
809
810 fail:
811         pxp_buf_free(q, buf);
812         return ret;
813 }
814
815
816 static void pxp_buf_queue(struct videobuf_queue *q,
817                         struct videobuf_buffer *vb)
818 {
819         struct pxps *pxp = q->priv_data;
820         struct pxp_buffer *buf = container_of(vb, struct pxp_buffer, vb);
821         struct dma_async_tx_descriptor *txd = buf->txd;
822         struct pxp_channel *pchan = pxp->pxp_channel[0];
823         dma_cookie_t cookie;
824
825         BUG_ON(!irqs_disabled());
826
827         list_add_tail(&vb->queue, &pxp->outq);
828
829         if (!pxp->active) {
830                 pxp->active = buf;
831                 vb->state = VIDEOBUF_ACTIVE;
832         } else {
833                 vb->state = VIDEOBUF_QUEUED;
834         }
835
836         spin_unlock_irq(&pxp->lock);
837
838         cookie = txd->tx_submit(txd);
839         dev_dbg(&pxp->pdev->dev, "Submitted cookie %d DMA 0x%08x\n",
840                                 cookie, sg_dma_address(&buf->sg[0]));
841         mdelay(5);
842         /* trigger ePxP */
843         dma_async_issue_pending(&pchan->dma_chan);
844
845         spin_lock_irq(&pxp->lock);
846
847         if (cookie >= 0)
848                 return;
849
850         /* Submit error */
851         pr_err("%s: Submit error\n", __func__);
852         vb->state = VIDEOBUF_PREPARED;
853
854         list_del_init(&vb->queue);
855
856         if (pxp->active == buf)
857                 pxp->active = NULL;
858 }
859
860 static void pxp_buf_release(struct videobuf_queue *q,
861                         struct videobuf_buffer *vb)
862 {
863         struct pxps *pxp = q->priv_data;
864         struct pxp_buffer *buf = container_of(vb, struct pxp_buffer, vb);
865         unsigned long flags;
866
867         spin_lock_irqsave(&pxp->lock, flags);
868         if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
869             !list_empty(&vb->queue)) {
870                 vb->state = VIDEOBUF_ERROR;
871
872                 list_del_init(&vb->queue);
873                 if (pxp->active == buf)
874                         pxp->active = NULL;
875         }
876         spin_unlock_irqrestore(&pxp->lock, flags);
877
878         pxp_buf_free(q, buf);
879 }
880
881 static struct videobuf_queue_ops pxp_vbq_ops = {
882         .buf_setup      = pxp_buf_setup,
883         .buf_prepare    = pxp_buf_prepare,
884         .buf_queue      = pxp_buf_queue,
885         .buf_release    = pxp_buf_release,
886 };
887
888 static int pxp_querycap(struct file *file, void *fh,
889                         struct v4l2_capability *cap)
890 {
891         struct pxps *pxp = video_get_drvdata(video_devdata(file));
892
893         memset(cap, 0, sizeof(*cap));
894         strcpy(cap->driver, "pxp");
895         strcpy(cap->card, "pxp");
896         strlcpy(cap->bus_info, dev_name(&pxp->pdev->dev),
897                 sizeof(cap->bus_info));
898
899         cap->version = (PXP_DRIVER_MAJOR << 8) + PXP_DRIVER_MINOR;
900
901         cap->capabilities = V4L2_CAP_VIDEO_OUTPUT |
902                                 V4L2_CAP_VIDEO_OUTPUT_OVERLAY |
903                                 V4L2_CAP_STREAMING;
904
905         return 0;
906 }
907
908 static int pxp_g_fbuf(struct file *file, void *priv,
909                         struct v4l2_framebuffer *fb)
910 {
911         struct pxps *pxp = video_get_drvdata(video_devdata(file));
912
913         memset(fb, 0, sizeof(*fb));
914
915         fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY |
916                          V4L2_FBUF_CAP_CHROMAKEY |
917                          V4L2_FBUF_CAP_LOCAL_ALPHA |
918                          V4L2_FBUF_CAP_GLOBAL_ALPHA;
919
920         if (pxp->global_alpha_state)
921                 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
922         if (pxp->s1_chromakey_state)
923                 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
924
925         return 0;
926 }
927
928 static int pxp_s_fbuf(struct file *file, void *priv,
929                         const struct v4l2_framebuffer *fb)
930 {
931         struct pxps *pxp = video_get_drvdata(video_devdata(file));
932
933         pxp->overlay_state =
934                 (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
935         pxp->global_alpha_state =
936                 (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
937         pxp->s1_chromakey_state =
938                 (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
939
940         pxp->pxp_conf.ol_param[0].combine_enable = pxp->overlay_state;
941         pxp->pxp_conf.ol_param[0].global_alpha_enable = pxp->global_alpha_state;
942
943         return 0;
944 }
945
946 static int pxp_g_crop(struct file *file, void *fh,
947                         struct v4l2_crop *c)
948 {
949         struct pxps *pxp = video_get_drvdata(video_devdata(file));
950
951         if (c->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY)
952                 return -EINVAL;
953
954         c->c.left = pxp->pxp_conf.proc_data.drect.left;
955         c->c.top = pxp->pxp_conf.proc_data.drect.top;
956         c->c.width = pxp->pxp_conf.proc_data.drect.width;
957         c->c.height = pxp->pxp_conf.proc_data.drect.height;
958
959         return 0;
960 }
961
962 static int pxp_s_crop(struct file *file, void *fh,
963                         const struct v4l2_crop *c)
964 {
965         struct pxps *pxp = video_get_drvdata(video_devdata(file));
966         int l = c->c.left;
967         int t = c->c.top;
968         int w = c->c.width;
969         int h = c->c.height;
970         int fbw = pxp->fb.fmt.width;
971         int fbh = pxp->fb.fmt.height;
972
973         if (c->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY)
974                 return -EINVAL;
975
976         /* Constrain parameters to FB limits */
977         w = min(w, fbw);
978         w = max(w, PXP_MIN_PIX);
979         h = min(h, fbh);
980         h = max(h, PXP_MIN_PIX);
981         if ((l + w) > fbw)
982                 l = 0;
983         if ((t + h) > fbh)
984                 t = 0;
985
986         /* Round up values to PxP pixel block */
987         l = roundup(l, PXP_MIN_PIX);
988         t = roundup(t, PXP_MIN_PIX);
989         w = roundup(w, PXP_MIN_PIX);
990         h = roundup(h, PXP_MIN_PIX);
991
992         pxp->pxp_conf.proc_data.drect.left = l;
993         pxp->pxp_conf.proc_data.drect.top = t;
994         pxp->pxp_conf.proc_data.drect.width = w;
995         pxp->pxp_conf.proc_data.drect.height = h;
996
997         return 0;
998 }
999
1000 static int pxp_queryctrl(struct file *file, void *priv,
1001                          struct v4l2_queryctrl *qc)
1002 {
1003         int i;
1004
1005         for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
1006                 if (qc->id && qc->id == pxp_controls[i].id) {
1007                         memcpy(qc, &(pxp_controls[i]), sizeof(*qc));
1008                         return 0;
1009                 }
1010
1011         return -EINVAL;
1012 }
1013
1014 static int pxp_g_ctrl(struct file *file, void *priv,
1015                          struct v4l2_control *vc)
1016 {
1017         int i;
1018
1019         struct pxps *pxp = video_get_drvdata(video_devdata(file));
1020
1021         for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
1022                 if (vc->id == pxp_controls[i].id)
1023                         return pxp_get_cstate(pxp, vc);
1024
1025         return -EINVAL;
1026 }
1027
1028 static int pxp_s_ctrl(struct file *file, void *priv,
1029                          struct v4l2_control *vc)
1030 {
1031         int i;
1032         struct pxps *pxp = video_get_drvdata(video_devdata(file));
1033
1034         for (i = 0; i < ARRAY_SIZE(pxp_controls); i++)
1035                 if (vc->id == pxp_controls[i].id) {
1036                         if (vc->value < pxp_controls[i].minimum ||
1037                             vc->value > pxp_controls[i].maximum)
1038                                 return -ERANGE;
1039                         return pxp_set_cstate(pxp, vc);
1040                 }
1041
1042         return -EINVAL;
1043 }
1044
1045 void pxp_release(struct video_device *vfd)
1046 {
1047         struct pxps *pxp = video_get_drvdata(vfd);
1048
1049         spin_lock(&pxp->lock);
1050         video_device_release(vfd);
1051         spin_unlock(&pxp->lock);
1052 }
1053
1054 static int pxp_open(struct file *file)
1055 {
1056         struct pxps *pxp = video_get_drvdata(video_devdata(file));
1057         int ret = 0;
1058
1059         mutex_lock(&pxp->mutex);
1060         pxp->users++;
1061
1062         if (pxp->users > 1) {
1063                 pxp->users--;
1064                 ret = -EBUSY;
1065                 goto out;
1066         }
1067 out:
1068         mutex_unlock(&pxp->mutex);
1069         if (ret)
1070                 return ret;
1071
1072         ret = pxp_set_fbinfo(pxp);
1073         if (ret) {
1074                 dev_err(&pxp->pdev->dev, "failed to call pxp_set_fbinfo\n");
1075                 return ret;
1076         }
1077
1078         videobuf_queue_dma_contig_init(&pxp->s0_vbq,
1079                                 &pxp_vbq_ops,
1080                                 &pxp->pdev->dev,
1081                                 &pxp->lock,
1082                                 V4L2_BUF_TYPE_VIDEO_OUTPUT,
1083                                 V4L2_FIELD_NONE,
1084                                 sizeof(struct pxp_buffer),
1085                                 pxp,
1086                                 NULL);
1087         dev_dbg(&pxp->pdev->dev, "call pxp_open\n");
1088
1089         return 0;
1090 }
1091
1092 static int pxp_close(struct file *file)
1093 {
1094         struct pxps *pxp = video_get_drvdata(video_devdata(file));
1095
1096         videobuf_stop(&pxp->s0_vbq);
1097         videobuf_mmap_free(&pxp->s0_vbq);
1098         pxp->active = NULL;
1099         kfree(pxp->outb);
1100         pxp->outb = NULL;
1101
1102         mutex_lock(&pxp->mutex);
1103         pxp->users--;
1104         mutex_unlock(&pxp->mutex);
1105
1106         return 0;
1107 }
1108
1109 static int pxp_mmap(struct file *file, struct vm_area_struct *vma)
1110 {
1111         struct pxps *pxp = video_get_drvdata(video_devdata(file));
1112         int ret;
1113
1114         ret = videobuf_mmap_mapper(&pxp->s0_vbq, vma);
1115
1116         return ret;
1117 }
1118
1119 static const struct v4l2_file_operations pxp_fops = {
1120         .owner          = THIS_MODULE,
1121         .open           = pxp_open,
1122         .release        = pxp_close,
1123         .unlocked_ioctl = video_ioctl2,
1124         .mmap           = pxp_mmap,
1125 };
1126
1127 static const struct v4l2_ioctl_ops pxp_ioctl_ops = {
1128         .vidioc_querycap                = pxp_querycap,
1129
1130         .vidioc_reqbufs                 = pxp_reqbufs,
1131         .vidioc_querybuf                = pxp_querybuf,
1132         .vidioc_qbuf                    = pxp_qbuf,
1133         .vidioc_dqbuf                   = pxp_dqbuf,
1134
1135         .vidioc_streamon                = pxp_streamon,
1136         .vidioc_streamoff               = pxp_streamoff,
1137
1138         .vidioc_enum_output             = pxp_enumoutput,
1139         .vidioc_g_output                = pxp_g_output,
1140         .vidioc_s_output                = pxp_s_output,
1141
1142         .vidioc_enum_fmt_vid_out        = pxp_enum_fmt_video_output,
1143         .vidioc_try_fmt_vid_out         = pxp_try_fmt_video_output,
1144         .vidioc_g_fmt_vid_out           = pxp_g_fmt_video_output,
1145         .vidioc_s_fmt_vid_out           = pxp_s_fmt_video_output,
1146
1147         .vidioc_try_fmt_vid_out_overlay = pxp_try_fmt_output_overlay,
1148         .vidioc_g_fmt_vid_out_overlay   = pxp_g_fmt_output_overlay,
1149         .vidioc_s_fmt_vid_out_overlay   = pxp_s_fmt_output_overlay,
1150
1151         .vidioc_g_fbuf                  = pxp_g_fbuf,
1152         .vidioc_s_fbuf                  = pxp_s_fbuf,
1153
1154         .vidioc_g_crop                  = pxp_g_crop,
1155         .vidioc_s_crop                  = pxp_s_crop,
1156
1157         .vidioc_queryctrl               = pxp_queryctrl,
1158         .vidioc_g_ctrl                  = pxp_g_ctrl,
1159         .vidioc_s_ctrl                  = pxp_s_ctrl,
1160 };
1161
1162 static const struct video_device pxp_template = {
1163         .name                           = "PxP",
1164         .vfl_type                       = V4L2_CAP_VIDEO_OUTPUT |
1165                                                 V4L2_CAP_VIDEO_OVERLAY |
1166                                                 V4L2_CAP_STREAMING,
1167         .vfl_dir                        = VFL_DIR_TX,
1168         .fops                           = &pxp_fops,
1169         .release                        = pxp_release,
1170         .minor                          = -1,
1171         .ioctl_ops                      = &pxp_ioctl_ops,
1172 };
1173
1174 static const struct of_device_id imx_pxpv4l2_dt_ids[] = {
1175         { .compatible = "fsl,imx6sl-pxp-v4l2", },
1176         { /* sentinel */ }
1177 };
1178 MODULE_DEVICE_TABLE(of, imx_pxpv4l2_dt_ids);
1179
1180 static int pxp_probe(struct platform_device *pdev)
1181 {
1182         struct pxps *pxp;
1183         int err = 0;
1184
1185         pxp = kzalloc(sizeof(*pxp), GFP_KERNEL);
1186         if (!pxp) {
1187                 dev_err(&pdev->dev, "failed to allocate control object\n");
1188                 err = -ENOMEM;
1189                 goto exit;
1190         }
1191
1192         dev_set_drvdata(&pdev->dev, pxp);
1193
1194         INIT_LIST_HEAD(&pxp->outq);
1195         spin_lock_init(&pxp->lock);
1196         mutex_init(&pxp->mutex);
1197
1198         pxp->pdev = pdev;
1199
1200         pxp->vdev = video_device_alloc();
1201         if (!pxp->vdev) {
1202                 dev_err(&pdev->dev, "video_device_alloc() failed\n");
1203                 err = -ENOMEM;
1204                 goto freeirq;
1205         }
1206
1207         memcpy(pxp->vdev, &pxp_template, sizeof(pxp_template));
1208         video_set_drvdata(pxp->vdev, pxp);
1209
1210         err = video_register_device(pxp->vdev, VFL_TYPE_GRABBER, video_nr);
1211         if (err) {
1212                 dev_err(&pdev->dev, "failed to register video device\n");
1213                 goto freevdev;
1214         }
1215
1216         dev_info(&pdev->dev, "initialized\n");
1217
1218 exit:
1219         return err;
1220
1221 freevdev:
1222         video_device_release(pxp->vdev);
1223
1224 freeirq:
1225         kfree(pxp);
1226
1227         return err;
1228 }
1229
1230 static int pxp_remove(struct platform_device *pdev)
1231 {
1232         struct pxps *pxp = platform_get_drvdata(pdev);
1233
1234         video_unregister_device(pxp->vdev);
1235         video_device_release(pxp->vdev);
1236
1237         kfree(pxp);
1238
1239         return 0;
1240 }
1241
1242 static struct platform_driver pxp_driver = {
1243         .driver         = {
1244                 .name   = PXP_DRIVER_NAME,
1245                 .of_match_table = of_match_ptr(imx_pxpv4l2_dt_ids),
1246         },
1247         .probe          = pxp_probe,
1248         .remove         = pxp_remove,
1249 };
1250
1251 module_platform_driver(pxp_driver);
1252
1253 module_param(video_nr, int, 0444);
1254 MODULE_DESCRIPTION("MXC PxP V4L2 driver");
1255 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
1256 MODULE_LICENSE("GPL");