blob: 5f73a017961c7169d74bd0756c75d3fe229acd87 [file] [log] [blame]
Guennadi Liakhovetskia81fb9b2010-03-17 11:21:13 -03001/*
2 * SuperH Video Output Unit (VOU) driver
3 *
4 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/dma-mapping.h>
12#include <linux/delay.h>
13#include <linux/errno.h>
14#include <linux/fs.h>
15#include <linux/i2c.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/kernel.h>
19#include <linux/platform_device.h>
20#include <linux/pm_runtime.h>
Guennadi Liakhovetski3b23db32010-07-08 05:12:11 -030021#include <linux/slab.h>
Guennadi Liakhovetskia81fb9b2010-03-17 11:21:13 -030022#include <linux/version.h>
23#include <linux/videodev2.h>
24
25#include <media/sh_vou.h>
26#include <media/v4l2-common.h>
27#include <media/v4l2-device.h>
28#include <media/v4l2-ioctl.h>
29#include <media/v4l2-mediabus.h>
30#include <media/videobuf-dma-contig.h>
31
32/* Mirror addresses are not available for all registers */
33#define VOUER 0
34#define VOUCR 4
35#define VOUSTR 8
36#define VOUVCR 0xc
37#define VOUISR 0x10
38#define VOUBCR 0x14
39#define VOUDPR 0x18
40#define VOUDSR 0x1c
41#define VOUVPR 0x20
42#define VOUIR 0x24
43#define VOUSRR 0x28
44#define VOUMSR 0x2c
45#define VOUHIR 0x30
46#define VOUDFR 0x34
47#define VOUAD1R 0x38
48#define VOUAD2R 0x3c
49#define VOUAIR 0x40
50#define VOUSWR 0x44
51#define VOURCR 0x48
52#define VOURPR 0x50
53
54enum sh_vou_status {
55 SH_VOU_IDLE,
56 SH_VOU_INITIALISING,
57 SH_VOU_RUNNING,
58};
59
60#define VOU_MAX_IMAGE_WIDTH 720
61#define VOU_MAX_IMAGE_HEIGHT 480
62
63struct sh_vou_device {
64 struct v4l2_device v4l2_dev;
65 struct video_device *vdev;
66 atomic_t use_count;
67 struct sh_vou_pdata *pdata;
68 spinlock_t lock;
69 void __iomem *base;
70 /* State information */
71 struct v4l2_pix_format pix;
72 struct v4l2_rect rect;
73 struct list_head queue;
74 v4l2_std_id std;
75 int pix_idx;
76 struct videobuf_buffer *active;
77 enum sh_vou_status status;
78};
79
80struct sh_vou_file {
81 struct videobuf_queue vbq;
82};
83
84/* Register access routines for sides A, B and mirror addresses */
85static void sh_vou_reg_a_write(struct sh_vou_device *vou_dev, unsigned int reg,
86 u32 value)
87{
88 __raw_writel(value, vou_dev->base + reg);
89}
90
91static void sh_vou_reg_ab_write(struct sh_vou_device *vou_dev, unsigned int reg,
92 u32 value)
93{
94 __raw_writel(value, vou_dev->base + reg);
95 __raw_writel(value, vou_dev->base + reg + 0x1000);
96}
97
98static void sh_vou_reg_m_write(struct sh_vou_device *vou_dev, unsigned int reg,
99 u32 value)
100{
101 __raw_writel(value, vou_dev->base + reg + 0x2000);
102}
103
104static u32 sh_vou_reg_a_read(struct sh_vou_device *vou_dev, unsigned int reg)
105{
106 return __raw_readl(vou_dev->base + reg);
107}
108
109static void sh_vou_reg_a_set(struct sh_vou_device *vou_dev, unsigned int reg,
110 u32 value, u32 mask)
111{
112 u32 old = __raw_readl(vou_dev->base + reg);
113
114 value = (value & mask) | (old & ~mask);
115 __raw_writel(value, vou_dev->base + reg);
116}
117
118static void sh_vou_reg_b_set(struct sh_vou_device *vou_dev, unsigned int reg,
119 u32 value, u32 mask)
120{
121 sh_vou_reg_a_set(vou_dev, reg + 0x1000, value, mask);
122}
123
124static void sh_vou_reg_ab_set(struct sh_vou_device *vou_dev, unsigned int reg,
125 u32 value, u32 mask)
126{
127 sh_vou_reg_a_set(vou_dev, reg, value, mask);
128 sh_vou_reg_b_set(vou_dev, reg, value, mask);
129}
130
131struct sh_vou_fmt {
132 u32 pfmt;
133 char *desc;
134 unsigned char bpp;
135 unsigned char rgb;
136 unsigned char yf;
137 unsigned char pkf;
138};
139
140/* Further pixel formats can be added */
141static struct sh_vou_fmt vou_fmt[] = {
142 {
143 .pfmt = V4L2_PIX_FMT_NV12,
144 .bpp = 12,
145 .desc = "YVU420 planar",
146 .yf = 0,
147 .rgb = 0,
148 },
149 {
150 .pfmt = V4L2_PIX_FMT_NV16,
151 .bpp = 16,
152 .desc = "YVYU planar",
153 .yf = 1,
154 .rgb = 0,
155 },
156 {
157 .pfmt = V4L2_PIX_FMT_RGB24,
158 .bpp = 24,
159 .desc = "RGB24",
160 .pkf = 2,
161 .rgb = 1,
162 },
163 {
164 .pfmt = V4L2_PIX_FMT_RGB565,
165 .bpp = 16,
166 .desc = "RGB565",
167 .pkf = 3,
168 .rgb = 1,
169 },
170 {
171 .pfmt = V4L2_PIX_FMT_RGB565X,
172 .bpp = 16,
173 .desc = "RGB565 byteswapped",
174 .pkf = 3,
175 .rgb = 1,
176 },
177};
178
179static void sh_vou_schedule_next(struct sh_vou_device *vou_dev,
180 struct videobuf_buffer *vb)
181{
182 dma_addr_t addr1, addr2;
183
184 addr1 = videobuf_to_dma_contig(vb);
185 switch (vou_dev->pix.pixelformat) {
186 case V4L2_PIX_FMT_NV12:
187 case V4L2_PIX_FMT_NV16:
188 addr2 = addr1 + vou_dev->pix.width * vou_dev->pix.height;
189 break;
190 default:
191 addr2 = 0;
192 }
193
194 sh_vou_reg_m_write(vou_dev, VOUAD1R, addr1);
195 sh_vou_reg_m_write(vou_dev, VOUAD2R, addr2);
196}
197
198static void sh_vou_stream_start(struct sh_vou_device *vou_dev,
199 struct videobuf_buffer *vb)
200{
201 unsigned int row_coeff;
202#ifdef __LITTLE_ENDIAN
203 u32 dataswap = 7;
204#else
205 u32 dataswap = 0;
206#endif
207
208 switch (vou_dev->pix.pixelformat) {
209 case V4L2_PIX_FMT_NV12:
210 case V4L2_PIX_FMT_NV16:
211 row_coeff = 1;
212 break;
213 case V4L2_PIX_FMT_RGB565:
214 dataswap ^= 1;
215 case V4L2_PIX_FMT_RGB565X:
216 row_coeff = 2;
217 break;
218 case V4L2_PIX_FMT_RGB24:
219 row_coeff = 3;
220 break;
221 }
222
223 sh_vou_reg_a_write(vou_dev, VOUSWR, dataswap);
224 sh_vou_reg_ab_write(vou_dev, VOUAIR, vou_dev->pix.width * row_coeff);
225 sh_vou_schedule_next(vou_dev, vb);
226}
227
228static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)
229{
230 BUG_ON(in_interrupt());
231
232 /* Wait until this buffer is no longer in STATE_QUEUED or STATE_ACTIVE */
233 videobuf_waiton(vb, 0, 0);
234 videobuf_dma_contig_free(vq, vb);
235 vb->state = VIDEOBUF_NEEDS_INIT;
236}
237
238/* Locking: caller holds vq->vb_lock mutex */
239static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
240 unsigned int *size)
241{
242 struct video_device *vdev = vq->priv_data;
243 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
244
245 *size = vou_fmt[vou_dev->pix_idx].bpp * vou_dev->pix.width *
246 vou_dev->pix.height / 8;
247
248 if (*count < 2)
249 *count = 2;
250
251 /* Taking into account maximum frame size, *count will stay >= 2 */
252 if (PAGE_ALIGN(*size) * *count > 4 * 1024 * 1024)
253 *count = 4 * 1024 * 1024 / PAGE_ALIGN(*size);
254
255 dev_dbg(vq->dev, "%s(): count=%d, size=%d\n", __func__, *count, *size);
256
257 return 0;
258}
259
260/* Locking: caller holds vq->vb_lock mutex */
261static int sh_vou_buf_prepare(struct videobuf_queue *vq,
262 struct videobuf_buffer *vb,
263 enum v4l2_field field)
264{
265 struct video_device *vdev = vq->priv_data;
266 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
267 struct v4l2_pix_format *pix = &vou_dev->pix;
268 int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
269 int ret;
270
271 dev_dbg(vq->dev, "%s()\n", __func__);
272
273 if (vb->width != pix->width ||
274 vb->height != pix->height ||
275 vb->field != pix->field) {
276 vb->width = pix->width;
277 vb->height = pix->height;
278 vb->field = field;
279 if (vb->state != VIDEOBUF_NEEDS_INIT)
280 free_buffer(vq, vb);
281 }
282
283 vb->size = vb->height * bytes_per_line;
284 if (vb->baddr && vb->bsize < vb->size) {
285 /* User buffer too small */
286 dev_warn(vq->dev, "User buffer too small: [%u] @ %lx\n",
287 vb->bsize, vb->baddr);
288 return -EINVAL;
289 }
290
291 if (vb->state == VIDEOBUF_NEEDS_INIT) {
292 ret = videobuf_iolock(vq, vb, NULL);
293 if (ret < 0) {
294 dev_warn(vq->dev, "IOLOCK buf-type %d: %d\n",
295 vb->memory, ret);
296 return ret;
297 }
298 vb->state = VIDEOBUF_PREPARED;
299 }
300
301 dev_dbg(vq->dev,
302 "%s(): fmt #%d, %u bytes per line, phys 0x%x, type %d, state %d\n",
303 __func__, vou_dev->pix_idx, bytes_per_line,
304 videobuf_to_dma_contig(vb), vb->memory, vb->state);
305
306 return 0;
307}
308
309/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */
310static void sh_vou_buf_queue(struct videobuf_queue *vq,
311 struct videobuf_buffer *vb)
312{
313 struct video_device *vdev = vq->priv_data;
314 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
315
316 dev_dbg(vq->dev, "%s()\n", __func__);
317
318 vb->state = VIDEOBUF_QUEUED;
319 list_add_tail(&vb->queue, &vou_dev->queue);
320
321 if (vou_dev->status == SH_VOU_RUNNING) {
322 return;
323 } else if (!vou_dev->active) {
324 vou_dev->active = vb;
325 /* Start from side A: we use mirror addresses, so, set B */
326 sh_vou_reg_a_write(vou_dev, VOURPR, 1);
327 dev_dbg(vq->dev, "%s: first buffer status 0x%x\n", __func__,
328 sh_vou_reg_a_read(vou_dev, VOUSTR));
329 sh_vou_schedule_next(vou_dev, vb);
330 /* Only activate VOU after the second buffer */
331 } else if (vou_dev->active->queue.next == &vb->queue) {
332 /* Second buffer - initialise register side B */
333 sh_vou_reg_a_write(vou_dev, VOURPR, 0);
334 sh_vou_stream_start(vou_dev, vb);
335
336 /* Register side switching with frame VSYNC */
337 sh_vou_reg_a_write(vou_dev, VOURCR, 5);
338 dev_dbg(vq->dev, "%s: second buffer status 0x%x\n", __func__,
339 sh_vou_reg_a_read(vou_dev, VOUSTR));
340
341 /* Enable End-of-Frame (VSYNC) interrupts */
342 sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004);
343 /* Two buffers on the queue - activate the hardware */
344
345 vou_dev->status = SH_VOU_RUNNING;
346 sh_vou_reg_a_write(vou_dev, VOUER, 0x107);
347 }
348}
349
350static void sh_vou_buf_release(struct videobuf_queue *vq,
351 struct videobuf_buffer *vb)
352{
353 struct video_device *vdev = vq->priv_data;
354 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
355 unsigned long flags;
356
357 dev_dbg(vq->dev, "%s()\n", __func__);
358
359 spin_lock_irqsave(&vou_dev->lock, flags);
360
361 if (vou_dev->active == vb) {
362 /* disable output */
363 sh_vou_reg_a_set(vou_dev, VOUER, 0, 1);
364 /* ...but the current frame will complete */
365 sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000);
366 vou_dev->active = NULL;
367 }
368
369 if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED)) {
370 vb->state = VIDEOBUF_ERROR;
371 list_del(&vb->queue);
372 }
373
374 spin_unlock_irqrestore(&vou_dev->lock, flags);
375
376 free_buffer(vq, vb);
377}
378
379static struct videobuf_queue_ops sh_vou_video_qops = {
380 .buf_setup = sh_vou_buf_setup,
381 .buf_prepare = sh_vou_buf_prepare,
382 .buf_queue = sh_vou_buf_queue,
383 .buf_release = sh_vou_buf_release,
384};
385
386/* Video IOCTLs */
387static int sh_vou_querycap(struct file *file, void *priv,
388 struct v4l2_capability *cap)
389{
390 struct sh_vou_file *vou_file = priv;
391
392 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
393
394 strlcpy(cap->card, "SuperH VOU", sizeof(cap->card));
395 cap->version = KERNEL_VERSION(0, 1, 0);
396 cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
397 return 0;
398}
399
400/* Enumerate formats, that the device can accept from the user */
401static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv,
402 struct v4l2_fmtdesc *fmt)
403{
404 struct sh_vou_file *vou_file = priv;
405
406 if (fmt->index >= ARRAY_SIZE(vou_fmt))
407 return -EINVAL;
408
409 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
410
411 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
412 strlcpy(fmt->description, vou_fmt[fmt->index].desc,
413 sizeof(fmt->description));
414 fmt->pixelformat = vou_fmt[fmt->index].pfmt;
415
416 return 0;
417}
418
419static int sh_vou_g_fmt_vid_out(struct file *file, void *priv,
420 struct v4l2_format *fmt)
421{
422 struct video_device *vdev = video_devdata(file);
423 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
424
425 dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
426
427 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
428 fmt->fmt.pix = vou_dev->pix;
429
430 return 0;
431}
432
433static const unsigned char vou_scale_h_num[] = {1, 9, 2, 9, 4};
434static const unsigned char vou_scale_h_den[] = {1, 8, 1, 4, 1};
435static const unsigned char vou_scale_h_fld[] = {0, 2, 1, 3};
436static const unsigned char vou_scale_v_num[] = {1, 2, 4};
437static const unsigned char vou_scale_v_den[] = {1, 1, 1};
438static const unsigned char vou_scale_v_fld[] = {0, 1};
439
440static void sh_vou_configure_geometry(struct sh_vou_device *vou_dev,
441 int pix_idx, int w_idx, int h_idx)
442{
443 struct sh_vou_fmt *fmt = vou_fmt + pix_idx;
444 unsigned int black_left, black_top, width_max, height_max,
445 frame_in_height, frame_out_height, frame_out_top;
446 struct v4l2_rect *rect = &vou_dev->rect;
447 struct v4l2_pix_format *pix = &vou_dev->pix;
448 u32 vouvcr = 0, dsr_h, dsr_v;
449
450 if (vou_dev->std & V4L2_STD_525_60) {
451 width_max = 858;
452 height_max = 262;
453 } else {
454 width_max = 864;
455 height_max = 312;
456 }
457
458 frame_in_height = pix->height / 2;
459 frame_out_height = rect->height / 2;
460 frame_out_top = rect->top / 2;
461
462 /*
463 * Cropping scheme: max useful image is 720x480, and the total video
464 * area is 858x525 (NTSC) or 864x625 (PAL). AK8813 / 8814 starts
465 * sampling data beginning with fixed 276th (NTSC) / 288th (PAL) clock,
466 * of which the first 33 / 25 clocks HSYNC must be held active. This
467 * has to be configured in CR[HW]. 1 pixel equals 2 clock periods.
468 * This gives CR[HW] = 16 / 12, VPR[HVP] = 138 / 144, which gives
469 * exactly 858 - 138 = 864 - 144 = 720! We call the out-of-display area,
470 * beyond DSR, specified on the left and top by the VPR register "black
471 * pixels" and out-of-image area (DPR) "background pixels." We fix VPR
472 * at 138 / 144 : 20, because that's the HSYNC timing, that our first
473 * client requires, and that's exactly what leaves us 720 pixels for the
474 * image; we leave VPR[VVP] at default 20 for now, because the client
475 * doesn't seem to have any special requirements for it. Otherwise we
476 * could also set it to max - 240 = 22 / 72. Thus VPR depends only on
477 * the selected standard, and DPR and DSR are selected according to
478 * cropping. Q: how does the client detect the first valid line? Does
479 * HSYNC stay inactive during invalid (black) lines?
480 */
481 black_left = width_max - VOU_MAX_IMAGE_WIDTH;
482 black_top = 20;
483
484 dsr_h = rect->width + rect->left;
485 dsr_v = frame_out_height + frame_out_top;
486
487 dev_dbg(vou_dev->v4l2_dev.dev,
488 "image %ux%u, black %u:%u, offset %u:%u, display %ux%u\n",
489 pix->width, frame_in_height, black_left, black_top,
490 rect->left, frame_out_top, dsr_h, dsr_v);
491
492 /* VOUISR height - half of a frame height in frame mode */
493 sh_vou_reg_ab_write(vou_dev, VOUISR, (pix->width << 16) | frame_in_height);
494 sh_vou_reg_ab_write(vou_dev, VOUVPR, (black_left << 16) | black_top);
495 sh_vou_reg_ab_write(vou_dev, VOUDPR, (rect->left << 16) | frame_out_top);
496 sh_vou_reg_ab_write(vou_dev, VOUDSR, (dsr_h << 16) | dsr_v);
497
498 /*
499 * if necessary, we could set VOUHIR to
500 * max(black_left + dsr_h, width_max) here
501 */
502
503 if (w_idx)
504 vouvcr |= (1 << 15) | (vou_scale_h_fld[w_idx - 1] << 4);
505 if (h_idx)
506 vouvcr |= (1 << 14) | vou_scale_v_fld[h_idx - 1];
507
508 dev_dbg(vou_dev->v4l2_dev.dev, "%s: scaling 0x%x\n", fmt->desc, vouvcr);
509
510 /* To produce a colour bar for testing set bit 23 of VOUVCR */
511 sh_vou_reg_ab_write(vou_dev, VOUVCR, vouvcr);
512 sh_vou_reg_ab_write(vou_dev, VOUDFR,
513 fmt->pkf | (fmt->yf << 8) | (fmt->rgb << 16));
514}
515
516struct sh_vou_geometry {
517 struct v4l2_rect output;
518 unsigned int in_width;
519 unsigned int in_height;
520 int scale_idx_h;
521 int scale_idx_v;
522};
523
524/*
525 * Find input geometry, that we can use to produce output, closest to the
526 * requested rectangle, using VOU scaling
527 */
528static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std)
529{
530 /* The compiler cannot know, that best and idx will indeed be set */
531 unsigned int best_err = UINT_MAX, best = 0, width_max, height_max;
532 int i, idx = 0;
533
534 if (std & V4L2_STD_525_60) {
535 width_max = 858;
536 height_max = 262;
537 } else {
538 width_max = 864;
539 height_max = 312;
540 }
541
542 /* Image width must be a multiple of 4 */
543 v4l_bound_align_image(&geo->in_width, 0, VOU_MAX_IMAGE_WIDTH, 2,
544 &geo->in_height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0);
545
546 /* Select scales to come as close as possible to the output image */
547 for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) {
548 unsigned int err;
549 unsigned int found = geo->output.width * vou_scale_h_den[i] /
550 vou_scale_h_num[i];
551
552 if (found > VOU_MAX_IMAGE_WIDTH)
553 /* scales increase */
554 break;
555
556 err = abs(found - geo->in_width);
557 if (err < best_err) {
558 best_err = err;
559 idx = i;
560 best = found;
561 }
562 if (!err)
563 break;
564 }
565
566 geo->in_width = best;
567 geo->scale_idx_h = idx;
568
569 best_err = UINT_MAX;
570
571 /* This loop can be replaced with one division */
572 for (i = ARRAY_SIZE(vou_scale_v_num) - 1; i >= 0; i--) {
573 unsigned int err;
574 unsigned int found = geo->output.height * vou_scale_v_den[i] /
575 vou_scale_v_num[i];
576
577 if (found > VOU_MAX_IMAGE_HEIGHT)
578 /* scales increase */
579 break;
580
581 err = abs(found - geo->in_height);
582 if (err < best_err) {
583 best_err = err;
584 idx = i;
585 best = found;
586 }
587 if (!err)
588 break;
589 }
590
591 geo->in_height = best;
592 geo->scale_idx_v = idx;
593}
594
595/*
596 * Find output geometry, that we can produce, using VOU scaling, closest to
597 * the requested rectangle
598 */
599static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std)
600{
601 unsigned int best_err = UINT_MAX, best, width_max, height_max;
602 int i, idx;
603
604 if (std & V4L2_STD_525_60) {
605 width_max = 858;
606 height_max = 262 * 2;
607 } else {
608 width_max = 864;
609 height_max = 312 * 2;
610 }
611
612 /* Select scales to come as close as possible to the output image */
613 for (i = 0; i < ARRAY_SIZE(vou_scale_h_num); i++) {
614 unsigned int err;
615 unsigned int found = geo->in_width * vou_scale_h_num[i] /
616 vou_scale_h_den[i];
617
618 if (found > VOU_MAX_IMAGE_WIDTH)
619 /* scales increase */
620 break;
621
622 err = abs(found - geo->output.width);
623 if (err < best_err) {
624 best_err = err;
625 idx = i;
626 best = found;
627 }
628 if (!err)
629 break;
630 }
631
632 geo->output.width = best;
633 geo->scale_idx_h = idx;
634 if (geo->output.left + best > width_max)
635 geo->output.left = width_max - best;
636
637 pr_debug("%s(): W %u * %u/%u = %u\n", __func__, geo->in_width,
638 vou_scale_h_num[idx], vou_scale_h_den[idx], best);
639
640 best_err = UINT_MAX;
641
642 /* This loop can be replaced with one division */
643 for (i = 0; i < ARRAY_SIZE(vou_scale_v_num); i++) {
644 unsigned int err;
645 unsigned int found = geo->in_height * vou_scale_v_num[i] /
646 vou_scale_v_den[i];
647
648 if (found > VOU_MAX_IMAGE_HEIGHT)
649 /* scales increase */
650 break;
651
652 err = abs(found - geo->output.height);
653 if (err < best_err) {
654 best_err = err;
655 idx = i;
656 best = found;
657 }
658 if (!err)
659 break;
660 }
661
662 geo->output.height = best;
663 geo->scale_idx_v = idx;
664 if (geo->output.top + best > height_max)
665 geo->output.top = height_max - best;
666
667 pr_debug("%s(): H %u * %u/%u = %u\n", __func__, geo->in_height,
668 vou_scale_v_num[idx], vou_scale_v_den[idx], best);
669}
670
671static int sh_vou_s_fmt_vid_out(struct file *file, void *priv,
672 struct v4l2_format *fmt)
673{
674 struct video_device *vdev = video_devdata(file);
675 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
676 struct v4l2_pix_format *pix = &fmt->fmt.pix;
677 int pix_idx;
678 struct sh_vou_geometry geo;
679 struct v4l2_mbus_framefmt mbfmt = {
680 /* Revisit: is this the correct code? */
681 .code = V4L2_MBUS_FMT_YUYV8_2X8_LE,
682 .field = V4L2_FIELD_INTERLACED,
683 .colorspace = V4L2_COLORSPACE_SMPTE170M,
684 };
685 int ret;
686
687 dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__,
688 vou_dev->rect.width, vou_dev->rect.height,
689 pix->width, pix->height);
690
691 if (pix->field == V4L2_FIELD_ANY)
692 pix->field = V4L2_FIELD_NONE;
693
694 if (fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
695 pix->field != V4L2_FIELD_NONE)
696 return -EINVAL;
697
698 for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++)
699 if (vou_fmt[pix_idx].pfmt == pix->pixelformat)
700 break;
701
702 if (pix_idx == ARRAY_SIZE(vou_fmt))
703 return -EINVAL;
704
705 /* Image width must be a multiple of 4 */
706 v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 2,
707 &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0);
708
709 geo.in_width = pix->width;
710 geo.in_height = pix->height;
711 geo.output = vou_dev->rect;
712
713 vou_adjust_output(&geo, vou_dev->std);
714
715 mbfmt.width = geo.output.width;
716 mbfmt.height = geo.output.height;
717 ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
718 s_mbus_fmt, &mbfmt);
719 /* Must be implemented, so, don't check for -ENOIOCTLCMD */
720 if (ret < 0)
721 return ret;
722
723 dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__,
724 geo.output.width, geo.output.height, mbfmt.width, mbfmt.height);
725
726 /* Sanity checks */
727 if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
728 (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT ||
729 mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE)
730 return -EIO;
731
732 if (mbfmt.width != geo.output.width ||
733 mbfmt.height != geo.output.height) {
734 geo.output.width = mbfmt.width;
735 geo.output.height = mbfmt.height;
736
737 vou_adjust_input(&geo, vou_dev->std);
738 }
739
740 /* We tried to preserve output rectangle, but it could have changed */
741 vou_dev->rect = geo.output;
742 pix->width = geo.in_width;
743 pix->height = geo.in_height;
744
745 dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u\n", __func__,
746 pix->width, pix->height);
747
748 vou_dev->pix_idx = pix_idx;
749
750 vou_dev->pix = *pix;
751
752 sh_vou_configure_geometry(vou_dev, pix_idx,
753 geo.scale_idx_h, geo.scale_idx_v);
754
755 return 0;
756}
757
758static int sh_vou_try_fmt_vid_out(struct file *file, void *priv,
759 struct v4l2_format *fmt)
760{
761 struct sh_vou_file *vou_file = priv;
762 struct v4l2_pix_format *pix = &fmt->fmt.pix;
763 int i;
764
765 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
766
767 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
768 pix->field = V4L2_FIELD_NONE;
769
770 v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 1,
771 &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0);
772
773 for (i = 0; ARRAY_SIZE(vou_fmt); i++)
774 if (vou_fmt[i].pfmt == pix->pixelformat)
775 return 0;
776
777 pix->pixelformat = vou_fmt[0].pfmt;
778
779 return 0;
780}
781
782static int sh_vou_reqbufs(struct file *file, void *priv,
783 struct v4l2_requestbuffers *req)
784{
785 struct sh_vou_file *vou_file = priv;
786
787 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
788
789 if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
790 return -EINVAL;
791
792 return videobuf_reqbufs(&vou_file->vbq, req);
793}
794
795static int sh_vou_querybuf(struct file *file, void *priv,
796 struct v4l2_buffer *b)
797{
798 struct sh_vou_file *vou_file = priv;
799
800 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
801
802 return videobuf_querybuf(&vou_file->vbq, b);
803}
804
805static int sh_vou_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
806{
807 struct sh_vou_file *vou_file = priv;
808
809 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
810
811 return videobuf_qbuf(&vou_file->vbq, b);
812}
813
814static int sh_vou_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
815{
816 struct sh_vou_file *vou_file = priv;
817
818 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
819
820 return videobuf_dqbuf(&vou_file->vbq, b, file->f_flags & O_NONBLOCK);
821}
822
823static int sh_vou_streamon(struct file *file, void *priv,
824 enum v4l2_buf_type buftype)
825{
826 struct video_device *vdev = video_devdata(file);
827 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
828 struct sh_vou_file *vou_file = priv;
829 int ret;
830
831 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
832
833 ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0,
834 video, s_stream, 1);
835 if (ret < 0 && ret != -ENOIOCTLCMD)
836 return ret;
837
838 /* This calls our .buf_queue() (== sh_vou_buf_queue) */
839 return videobuf_streamon(&vou_file->vbq);
840}
841
842static int sh_vou_streamoff(struct file *file, void *priv,
843 enum v4l2_buf_type buftype)
844{
845 struct video_device *vdev = video_devdata(file);
846 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
847 struct sh_vou_file *vou_file = priv;
848
849 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
850
851 /*
852 * This calls buf_release from host driver's videobuf_queue_ops for all
853 * remaining buffers. When the last buffer is freed, stop streaming
854 */
855 videobuf_streamoff(&vou_file->vbq);
856 v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video, s_stream, 0);
857
858 return 0;
859}
860
861static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt)
862{
863 switch (bus_fmt) {
864 default:
865 pr_warning("%s(): Invalid bus-format code %d, using default 8-bit\n",
866 __func__, bus_fmt);
867 case SH_VOU_BUS_8BIT:
868 return 1;
869 case SH_VOU_BUS_16BIT:
870 return 0;
871 case SH_VOU_BUS_BT656:
872 return 3;
873 }
874}
875
876static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
877{
878 struct video_device *vdev = video_devdata(file);
879 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
880 int ret;
881
882 dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, *std_id);
883
884 if (*std_id & ~vdev->tvnorms)
885 return -EINVAL;
886
887 ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
888 s_std_output, *std_id);
889 /* Shall we continue, if the subdev doesn't support .s_std_output()? */
890 if (ret < 0 && ret != -ENOIOCTLCMD)
891 return ret;
892
893 if (*std_id & V4L2_STD_525_60)
894 sh_vou_reg_ab_set(vou_dev, VOUCR,
895 sh_vou_ntsc_mode(vou_dev->pdata->bus_fmt) << 29, 7 << 29);
896 else
897 sh_vou_reg_ab_set(vou_dev, VOUCR, 5 << 29, 7 << 29);
898
899 vou_dev->std = *std_id;
900
901 return 0;
902}
903
904static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std)
905{
906 struct video_device *vdev = video_devdata(file);
907 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
908
909 dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
910
911 *std = vou_dev->std;
912
913 return 0;
914}
915
916static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
917{
918 struct video_device *vdev = video_devdata(file);
919 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
920
921 dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
922
923 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
924 a->c = vou_dev->rect;
925
926 return 0;
927}
928
929/* Assume a dull encoder, do all the work ourselves. */
930static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
931{
932 struct video_device *vdev = video_devdata(file);
933 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
934 struct v4l2_rect *rect = &a->c;
935 struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
936 struct v4l2_pix_format *pix = &vou_dev->pix;
937 struct sh_vou_geometry geo;
938 struct v4l2_mbus_framefmt mbfmt = {
939 /* Revisit: is this the correct code? */
940 .code = V4L2_MBUS_FMT_YUYV8_2X8_LE,
941 .field = V4L2_FIELD_INTERLACED,
942 .colorspace = V4L2_COLORSPACE_SMPTE170M,
943 };
944 int ret;
945
946 dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u@%u:%u\n", __func__,
947 rect->width, rect->height, rect->left, rect->top);
948
949 if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
950 return -EINVAL;
951
952 v4l_bound_align_image(&rect->width, 0, VOU_MAX_IMAGE_WIDTH, 1,
953 &rect->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0);
954
955 if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH)
956 rect->left = VOU_MAX_IMAGE_WIDTH - rect->width;
957
958 if (rect->height + rect->top > VOU_MAX_IMAGE_HEIGHT)
959 rect->top = VOU_MAX_IMAGE_HEIGHT - rect->height;
960
961 geo.output = *rect;
962 geo.in_width = pix->width;
963 geo.in_height = pix->height;
964
965 /* Configure the encoder one-to-one, position at 0, ignore errors */
966 sd_crop.c.width = geo.output.width;
967 sd_crop.c.height = geo.output.height;
968 /*
969 * We first issue a S_CROP, so that the subsequent S_FMT delivers the
970 * final encoder configuration.
971 */
972 v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
973 s_crop, &sd_crop);
974 mbfmt.width = geo.output.width;
975 mbfmt.height = geo.output.height;
976 ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
977 s_mbus_fmt, &mbfmt);
978 /* Must be implemented, so, don't check for -ENOIOCTLCMD */
979 if (ret < 0)
980 return ret;
981
982 /* Sanity checks */
983 if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
984 (unsigned)mbfmt.height > VOU_MAX_IMAGE_HEIGHT ||
985 mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8_LE)
986 return -EIO;
987
988 geo.output.width = mbfmt.width;
989 geo.output.height = mbfmt.height;
990
991 /*
992 * No down-scaling. According to the API, current call has precedence:
993 * http://v4l2spec.bytesex.org/spec/x1904.htm#AEN1954 paragraph two.
994 */
995 vou_adjust_input(&geo, vou_dev->std);
996
997 /* We tried to preserve output rectangle, but it could have changed */
998 vou_dev->rect = geo.output;
999 pix->width = geo.in_width;
1000 pix->height = geo.in_height;
1001
1002 sh_vou_configure_geometry(vou_dev, vou_dev->pix_idx,
1003 geo.scale_idx_h, geo.scale_idx_v);
1004
1005 return 0;
1006}
1007
1008/*
1009 * Total field: NTSC 858 x 2 * 262/263, PAL 864 x 2 * 312/313, default rectangle
1010 * is the initial register values, height takes the interlaced format into
1011 * account. The actual image can only go up to 720 x 2 * 240, So, VOUVPR can
1012 * actually only meaningfully contain values <= 720 and <= 240 respectively, and
1013 * not <= 864 and <= 312.
1014 */
1015static int sh_vou_cropcap(struct file *file, void *priv,
1016 struct v4l2_cropcap *a)
1017{
1018 struct sh_vou_file *vou_file = priv;
1019
1020 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
1021
1022 a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1023 a->bounds.left = 0;
1024 a->bounds.top = 0;
1025 a->bounds.width = VOU_MAX_IMAGE_WIDTH;
1026 a->bounds.height = VOU_MAX_IMAGE_HEIGHT;
1027 /* Default = max, set VOUDPR = 0, which is not hardware default */
1028 a->defrect.left = 0;
1029 a->defrect.top = 0;
1030 a->defrect.width = VOU_MAX_IMAGE_WIDTH;
1031 a->defrect.height = VOU_MAX_IMAGE_HEIGHT;
1032 a->pixelaspect.numerator = 1;
1033 a->pixelaspect.denominator = 1;
1034
1035 return 0;
1036}
1037
1038static irqreturn_t sh_vou_isr(int irq, void *dev_id)
1039{
1040 struct sh_vou_device *vou_dev = dev_id;
1041 static unsigned long j;
1042 struct videobuf_buffer *vb;
1043 static int cnt;
1044 static int side;
1045 u32 irq_status = sh_vou_reg_a_read(vou_dev, VOUIR), masked;
1046 u32 vou_status = sh_vou_reg_a_read(vou_dev, VOUSTR);
1047
1048 if (!(irq_status & 0x300)) {
1049 if (printk_timed_ratelimit(&j, 500))
1050 dev_warn(vou_dev->v4l2_dev.dev, "IRQ status 0x%x!\n",
1051 irq_status);
1052 return IRQ_NONE;
1053 }
1054
1055 spin_lock(&vou_dev->lock);
1056 if (!vou_dev->active || list_empty(&vou_dev->queue)) {
1057 if (printk_timed_ratelimit(&j, 500))
1058 dev_warn(vou_dev->v4l2_dev.dev,
1059 "IRQ without active buffer: %x!\n", irq_status);
1060 /* Just ack: buf_release will disable further interrupts */
1061 sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x300);
1062 spin_unlock(&vou_dev->lock);
1063 return IRQ_HANDLED;
1064 }
1065
1066 masked = ~(0x300 & irq_status) & irq_status & 0x30304;
1067 dev_dbg(vou_dev->v4l2_dev.dev,
1068 "IRQ status 0x%x -> 0x%x, VOU status 0x%x, cnt %d\n",
1069 irq_status, masked, vou_status, cnt);
1070
1071 cnt++;
1072 side = vou_status & 0x10000;
1073
1074 /* Clear only set interrupts */
1075 sh_vou_reg_a_write(vou_dev, VOUIR, masked);
1076
1077 vb = vou_dev->active;
1078 list_del(&vb->queue);
1079
1080 vb->state = VIDEOBUF_DONE;
1081 do_gettimeofday(&vb->ts);
1082 vb->field_count++;
1083 wake_up(&vb->done);
1084
1085 if (list_empty(&vou_dev->queue)) {
1086 /* Stop VOU */
1087 dev_dbg(vou_dev->v4l2_dev.dev, "%s: queue empty after %d\n",
1088 __func__, cnt);
1089 sh_vou_reg_a_set(vou_dev, VOUER, 0, 1);
1090 vou_dev->active = NULL;
1091 vou_dev->status = SH_VOU_INITIALISING;
1092 /* Disable End-of-Frame (VSYNC) interrupts */
1093 sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000);
1094 spin_unlock(&vou_dev->lock);
1095 return IRQ_HANDLED;
1096 }
1097
1098 vou_dev->active = list_entry(vou_dev->queue.next,
1099 struct videobuf_buffer, queue);
1100
1101 if (vou_dev->active->queue.next != &vou_dev->queue) {
1102 struct videobuf_buffer *new = list_entry(vou_dev->active->queue.next,
1103 struct videobuf_buffer, queue);
1104 sh_vou_schedule_next(vou_dev, new);
1105 }
1106
1107 spin_unlock(&vou_dev->lock);
1108
1109 return IRQ_HANDLED;
1110}
1111
1112static int sh_vou_hw_init(struct sh_vou_device *vou_dev)
1113{
1114 struct sh_vou_pdata *pdata = vou_dev->pdata;
1115 u32 voucr = sh_vou_ntsc_mode(pdata->bus_fmt) << 29;
1116 int i = 100;
1117
1118 /* Disable all IRQs */
1119 sh_vou_reg_a_write(vou_dev, VOUIR, 0);
1120
1121 /* Reset VOU interfaces - registers unaffected */
1122 sh_vou_reg_a_write(vou_dev, VOUSRR, 0x101);
1123 while (--i && (sh_vou_reg_a_read(vou_dev, VOUSRR) & 0x101))
1124 udelay(1);
1125
1126 if (!i)
1127 return -ETIMEDOUT;
1128
1129 dev_dbg(vou_dev->v4l2_dev.dev, "Reset took %dus\n", 100 - i);
1130
1131 if (pdata->flags & SH_VOU_PCLK_FALLING)
1132 voucr |= 1 << 28;
1133 if (pdata->flags & SH_VOU_HSYNC_LOW)
1134 voucr |= 1 << 27;
1135 if (pdata->flags & SH_VOU_VSYNC_LOW)
1136 voucr |= 1 << 26;
1137 sh_vou_reg_ab_set(vou_dev, VOUCR, voucr, 0xfc000000);
1138
1139 /* Manual register side switching at first */
1140 sh_vou_reg_a_write(vou_dev, VOURCR, 4);
1141 /* Default - fixed HSYNC length, can be made configurable is required */
1142 sh_vou_reg_ab_write(vou_dev, VOUMSR, 0x800000);
1143
1144 return 0;
1145}
1146
1147/* File operations */
1148static int sh_vou_open(struct file *file)
1149{
1150 struct video_device *vdev = video_devdata(file);
1151 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
1152 struct sh_vou_file *vou_file = kzalloc(sizeof(struct sh_vou_file),
1153 GFP_KERNEL);
1154
1155 if (!vou_file)
1156 return -ENOMEM;
1157
1158 dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
1159
1160 file->private_data = vou_file;
1161
1162 if (atomic_inc_return(&vou_dev->use_count) == 1) {
1163 int ret;
1164 /* First open */
1165 vou_dev->status = SH_VOU_INITIALISING;
1166 pm_runtime_get_sync(vdev->v4l2_dev->dev);
1167 ret = sh_vou_hw_init(vou_dev);
1168 if (ret < 0) {
1169 atomic_dec(&vou_dev->use_count);
1170 pm_runtime_put(vdev->v4l2_dev->dev);
1171 vou_dev->status = SH_VOU_IDLE;
1172 return ret;
1173 }
1174 }
1175
1176 videobuf_queue_dma_contig_init(&vou_file->vbq, &sh_vou_video_qops,
1177 vou_dev->v4l2_dev.dev, &vou_dev->lock,
1178 V4L2_BUF_TYPE_VIDEO_OUTPUT,
1179 V4L2_FIELD_NONE,
1180 sizeof(struct videobuf_buffer), vdev);
1181
1182 return 0;
1183}
1184
1185static int sh_vou_release(struct file *file)
1186{
1187 struct video_device *vdev = video_devdata(file);
1188 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
1189 struct sh_vou_file *vou_file = file->private_data;
1190
1191 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
1192
1193 if (!atomic_dec_return(&vou_dev->use_count)) {
1194 /* Last close */
1195 vou_dev->status = SH_VOU_IDLE;
1196 sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101);
1197 pm_runtime_put(vdev->v4l2_dev->dev);
1198 }
1199
1200 file->private_data = NULL;
1201 kfree(vou_file);
1202
1203 return 0;
1204}
1205
1206static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma)
1207{
1208 struct sh_vou_file *vou_file = file->private_data;
1209
1210 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
1211
1212 return videobuf_mmap_mapper(&vou_file->vbq, vma);
1213}
1214
1215static unsigned int sh_vou_poll(struct file *file, poll_table *wait)
1216{
1217 struct sh_vou_file *vou_file = file->private_data;
1218
1219 dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
1220
1221 return videobuf_poll_stream(file, &vou_file->vbq, wait);
1222}
1223
1224static int sh_vou_g_chip_ident(struct file *file, void *fh,
1225 struct v4l2_dbg_chip_ident *id)
1226{
1227 struct video_device *vdev = video_devdata(file);
1228 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
1229
1230 return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id);
1231}
1232
1233#ifdef CONFIG_VIDEO_ADV_DEBUG
1234static int sh_vou_g_register(struct file *file, void *fh,
1235 struct v4l2_dbg_register *reg)
1236{
1237 struct video_device *vdev = video_devdata(file);
1238 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
1239
1240 return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg);
1241}
1242
1243static int sh_vou_s_register(struct file *file, void *fh,
1244 struct v4l2_dbg_register *reg)
1245{
1246 struct video_device *vdev = video_devdata(file);
1247 struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
1248
1249 return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg);
1250}
1251#endif
1252
1253/* sh_vou display ioctl operations */
1254static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = {
1255 .vidioc_querycap = sh_vou_querycap,
1256 .vidioc_enum_fmt_vid_out = sh_vou_enum_fmt_vid_out,
1257 .vidioc_g_fmt_vid_out = sh_vou_g_fmt_vid_out,
1258 .vidioc_s_fmt_vid_out = sh_vou_s_fmt_vid_out,
1259 .vidioc_try_fmt_vid_out = sh_vou_try_fmt_vid_out,
1260 .vidioc_reqbufs = sh_vou_reqbufs,
1261 .vidioc_querybuf = sh_vou_querybuf,
1262 .vidioc_qbuf = sh_vou_qbuf,
1263 .vidioc_dqbuf = sh_vou_dqbuf,
1264 .vidioc_streamon = sh_vou_streamon,
1265 .vidioc_streamoff = sh_vou_streamoff,
1266 .vidioc_s_std = sh_vou_s_std,
1267 .vidioc_g_std = sh_vou_g_std,
1268 .vidioc_cropcap = sh_vou_cropcap,
1269 .vidioc_g_crop = sh_vou_g_crop,
1270 .vidioc_s_crop = sh_vou_s_crop,
1271 .vidioc_g_chip_ident = sh_vou_g_chip_ident,
1272#ifdef CONFIG_VIDEO_ADV_DEBUG
1273 .vidioc_g_register = sh_vou_g_register,
1274 .vidioc_s_register = sh_vou_s_register,
1275#endif
1276};
1277
1278static const struct v4l2_file_operations sh_vou_fops = {
1279 .owner = THIS_MODULE,
1280 .open = sh_vou_open,
1281 .release = sh_vou_release,
1282 .ioctl = video_ioctl2,
1283 .mmap = sh_vou_mmap,
1284 .poll = sh_vou_poll,
1285};
1286
1287static const struct video_device sh_vou_video_template = {
1288 .name = "sh_vou",
1289 .fops = &sh_vou_fops,
1290 .ioctl_ops = &sh_vou_ioctl_ops,
1291 .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */
1292 .current_norm = V4L2_STD_NTSC_M,
1293};
1294
1295static int __devinit sh_vou_probe(struct platform_device *pdev)
1296{
1297 struct sh_vou_pdata *vou_pdata = pdev->dev.platform_data;
1298 struct v4l2_rect *rect;
1299 struct v4l2_pix_format *pix;
1300 struct i2c_adapter *i2c_adap;
1301 struct video_device *vdev;
1302 struct sh_vou_device *vou_dev;
1303 struct resource *reg_res, *region;
1304 struct v4l2_subdev *subdev;
1305 int irq, ret;
1306
1307 reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1308 irq = platform_get_irq(pdev, 0);
1309
1310 if (!vou_pdata || !reg_res || irq <= 0) {
1311 dev_err(&pdev->dev, "Insufficient VOU platform information.\n");
1312 return -ENODEV;
1313 }
1314
1315 vou_dev = kzalloc(sizeof(*vou_dev), GFP_KERNEL);
1316 if (!vou_dev)
1317 return -ENOMEM;
1318
1319 INIT_LIST_HEAD(&vou_dev->queue);
1320 spin_lock_init(&vou_dev->lock);
1321 atomic_set(&vou_dev->use_count, 0);
1322 vou_dev->pdata = vou_pdata;
1323 vou_dev->status = SH_VOU_IDLE;
1324
1325 rect = &vou_dev->rect;
1326 pix = &vou_dev->pix;
1327
1328 /* Fill in defaults */
1329 vou_dev->std = sh_vou_video_template.current_norm;
1330 rect->left = 0;
1331 rect->top = 0;
1332 rect->width = VOU_MAX_IMAGE_WIDTH;
1333 rect->height = VOU_MAX_IMAGE_HEIGHT;
1334 pix->width = VOU_MAX_IMAGE_WIDTH;
1335 pix->height = VOU_MAX_IMAGE_HEIGHT;
1336 pix->pixelformat = V4L2_PIX_FMT_YVYU;
1337 pix->field = V4L2_FIELD_NONE;
1338 pix->bytesperline = VOU_MAX_IMAGE_WIDTH * 2;
1339 pix->sizeimage = VOU_MAX_IMAGE_WIDTH * 2 * VOU_MAX_IMAGE_HEIGHT;
1340 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
1341
1342 region = request_mem_region(reg_res->start, resource_size(reg_res),
1343 pdev->name);
1344 if (!region) {
1345 dev_err(&pdev->dev, "VOU region already claimed\n");
1346 ret = -EBUSY;
1347 goto ereqmemreg;
1348 }
1349
1350 vou_dev->base = ioremap(reg_res->start, resource_size(reg_res));
1351 if (!vou_dev->base) {
1352 ret = -ENOMEM;
1353 goto emap;
1354 }
1355
1356 ret = request_irq(irq, sh_vou_isr, 0, "vou", vou_dev);
1357 if (ret < 0)
1358 goto ereqirq;
1359
1360 ret = v4l2_device_register(&pdev->dev, &vou_dev->v4l2_dev);
1361 if (ret < 0) {
1362 dev_err(&pdev->dev, "Error registering v4l2 device\n");
1363 goto ev4l2devreg;
1364 }
1365
1366 /* Allocate memory for video device */
1367 vdev = video_device_alloc();
1368 if (vdev == NULL) {
1369 ret = -ENOMEM;
1370 goto evdevalloc;
1371 }
1372
1373 *vdev = sh_vou_video_template;
1374 if (vou_pdata->bus_fmt == SH_VOU_BUS_8BIT)
1375 vdev->tvnorms |= V4L2_STD_PAL;
1376 vdev->v4l2_dev = &vou_dev->v4l2_dev;
1377 vdev->release = video_device_release;
1378
1379 vou_dev->vdev = vdev;
1380 video_set_drvdata(vdev, vou_dev);
1381
1382 pm_runtime_enable(&pdev->dev);
1383 pm_runtime_resume(&pdev->dev);
1384
1385 i2c_adap = i2c_get_adapter(vou_pdata->i2c_adap);
1386 if (!i2c_adap) {
1387 ret = -ENODEV;
1388 goto ei2cgadap;
1389 }
1390
1391 ret = sh_vou_hw_init(vou_dev);
1392 if (ret < 0)
1393 goto ereset;
1394
1395 subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap,
1396 vou_pdata->module_name, vou_pdata->board_info, NULL);
1397 if (!subdev) {
1398 ret = -ENOMEM;
1399 goto ei2cnd;
1400 }
1401
1402 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1403 if (ret < 0)
1404 goto evregdev;
1405
1406 return 0;
1407
1408evregdev:
1409ei2cnd:
1410ereset:
1411 i2c_put_adapter(i2c_adap);
1412ei2cgadap:
1413 video_device_release(vdev);
1414 pm_runtime_disable(&pdev->dev);
1415evdevalloc:
1416 v4l2_device_unregister(&vou_dev->v4l2_dev);
1417ev4l2devreg:
1418 free_irq(irq, vou_dev);
1419ereqirq:
1420 iounmap(vou_dev->base);
1421emap:
1422 release_mem_region(reg_res->start, resource_size(reg_res));
1423ereqmemreg:
1424 kfree(vou_dev);
1425 return ret;
1426}
1427
1428static int __devexit sh_vou_remove(struct platform_device *pdev)
1429{
1430 int irq = platform_get_irq(pdev, 0);
1431 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
1432 struct sh_vou_device *vou_dev = container_of(v4l2_dev,
1433 struct sh_vou_device, v4l2_dev);
1434 struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
1435 struct v4l2_subdev, list);
1436 struct i2c_client *client = v4l2_get_subdevdata(sd);
1437 struct resource *reg_res;
1438
1439 if (irq > 0)
1440 free_irq(irq, vou_dev);
1441 pm_runtime_disable(&pdev->dev);
1442 video_unregister_device(vou_dev->vdev);
1443 i2c_put_adapter(client->adapter);
1444 v4l2_device_unregister(&vou_dev->v4l2_dev);
1445 iounmap(vou_dev->base);
1446 reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1447 if (reg_res)
1448 release_mem_region(reg_res->start, resource_size(reg_res));
1449 kfree(vou_dev);
1450 return 0;
1451}
1452
1453static struct platform_driver __refdata sh_vou = {
1454 .remove = __devexit_p(sh_vou_remove),
1455 .driver = {
1456 .name = "sh-vou",
1457 .owner = THIS_MODULE,
1458 },
1459};
1460
1461static int __init sh_vou_init(void)
1462{
1463 return platform_driver_probe(&sh_vou, sh_vou_probe);
1464}
1465
1466static void __exit sh_vou_exit(void)
1467{
1468 platform_driver_unregister(&sh_vou);
1469}
1470
1471module_init(sh_vou_init);
1472module_exit(sh_vou_exit);
1473
1474MODULE_DESCRIPTION("SuperH VOU driver");
1475MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1476MODULE_LICENSE("GPL v2");
1477MODULE_ALIAS("platform:sh-vou");