Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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