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