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.15 1629 lines 43 kB view raw
1/* 2 * V4L2 Driver for i.MX27 camera host 3 * 4 * Copyright (C) 2008, Sascha Hauer, Pengutronix 5 * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography 6 * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 */ 13 14#include <linux/init.h> 15#include <linux/module.h> 16#include <linux/io.h> 17#include <linux/delay.h> 18#include <linux/slab.h> 19#include <linux/dma-mapping.h> 20#include <linux/errno.h> 21#include <linux/fs.h> 22#include <linux/gcd.h> 23#include <linux/interrupt.h> 24#include <linux/kernel.h> 25#include <linux/math64.h> 26#include <linux/mm.h> 27#include <linux/moduleparam.h> 28#include <linux/time.h> 29#include <linux/device.h> 30#include <linux/platform_device.h> 31#include <linux/clk.h> 32 33#include <media/v4l2-common.h> 34#include <media/v4l2-dev.h> 35#include <media/videobuf2-core.h> 36#include <media/videobuf2-dma-contig.h> 37#include <media/soc_camera.h> 38#include <media/soc_mediabus.h> 39 40#include <linux/videodev2.h> 41 42#include <linux/platform_data/camera-mx2.h> 43 44#include <asm/dma.h> 45 46#define MX2_CAM_DRV_NAME "mx2-camera" 47#define MX2_CAM_VERSION "0.0.6" 48#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera" 49 50/* reset values */ 51#define CSICR1_RESET_VAL 0x40000800 52#define CSICR2_RESET_VAL 0x0 53#define CSICR3_RESET_VAL 0x0 54 55/* csi control reg 1 */ 56#define CSICR1_SWAP16_EN (1 << 31) 57#define CSICR1_EXT_VSYNC (1 << 30) 58#define CSICR1_EOF_INTEN (1 << 29) 59#define CSICR1_PRP_IF_EN (1 << 28) 60#define CSICR1_CCIR_MODE (1 << 27) 61#define CSICR1_COF_INTEN (1 << 26) 62#define CSICR1_SF_OR_INTEN (1 << 25) 63#define CSICR1_RF_OR_INTEN (1 << 24) 64#define CSICR1_STATFF_LEVEL (3 << 22) 65#define CSICR1_STATFF_INTEN (1 << 21) 66#define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19) 67#define CSICR1_RXFF_INTEN (1 << 18) 68#define CSICR1_SOF_POL (1 << 17) 69#define CSICR1_SOF_INTEN (1 << 16) 70#define CSICR1_MCLKDIV(d) (((d) & 0xF) << 12) 71#define CSICR1_HSYNC_POL (1 << 11) 72#define CSICR1_CCIR_EN (1 << 10) 73#define CSICR1_MCLKEN (1 << 9) 74#define CSICR1_FCC (1 << 8) 75#define CSICR1_PACK_DIR (1 << 7) 76#define CSICR1_CLR_STATFIFO (1 << 6) 77#define CSICR1_CLR_RXFIFO (1 << 5) 78#define CSICR1_GCLK_MODE (1 << 4) 79#define CSICR1_INV_DATA (1 << 3) 80#define CSICR1_INV_PCLK (1 << 2) 81#define CSICR1_REDGE (1 << 1) 82#define CSICR1_FMT_MASK (CSICR1_PACK_DIR | CSICR1_SWAP16_EN) 83 84#define SHIFT_STATFF_LEVEL 22 85#define SHIFT_RXFF_LEVEL 19 86#define SHIFT_MCLKDIV 12 87 88#define SHIFT_FRMCNT 16 89 90#define CSICR1 0x00 91#define CSICR2 0x04 92#define CSISR 0x08 93#define CSISTATFIFO 0x0c 94#define CSIRFIFO 0x10 95#define CSIRXCNT 0x14 96#define CSICR3 0x1c 97#define CSIDMASA_STATFIFO 0x20 98#define CSIDMATA_STATFIFO 0x24 99#define CSIDMASA_FB1 0x28 100#define CSIDMASA_FB2 0x2c 101#define CSIFBUF_PARA 0x30 102#define CSIIMAG_PARA 0x34 103 104/* EMMA PrP */ 105#define PRP_CNTL 0x00 106#define PRP_INTR_CNTL 0x04 107#define PRP_INTRSTATUS 0x08 108#define PRP_SOURCE_Y_PTR 0x0c 109#define PRP_SOURCE_CB_PTR 0x10 110#define PRP_SOURCE_CR_PTR 0x14 111#define PRP_DEST_RGB1_PTR 0x18 112#define PRP_DEST_RGB2_PTR 0x1c 113#define PRP_DEST_Y_PTR 0x20 114#define PRP_DEST_CB_PTR 0x24 115#define PRP_DEST_CR_PTR 0x28 116#define PRP_SRC_FRAME_SIZE 0x2c 117#define PRP_DEST_CH1_LINE_STRIDE 0x30 118#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 119#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 120#define PRP_CH1_OUT_IMAGE_SIZE 0x3c 121#define PRP_CH2_OUT_IMAGE_SIZE 0x40 122#define PRP_SRC_LINE_STRIDE 0x44 123#define PRP_CSC_COEF_012 0x48 124#define PRP_CSC_COEF_345 0x4c 125#define PRP_CSC_COEF_678 0x50 126#define PRP_CH1_RZ_HORI_COEF1 0x54 127#define PRP_CH1_RZ_HORI_COEF2 0x58 128#define PRP_CH1_RZ_HORI_VALID 0x5c 129#define PRP_CH1_RZ_VERT_COEF1 0x60 130#define PRP_CH1_RZ_VERT_COEF2 0x64 131#define PRP_CH1_RZ_VERT_VALID 0x68 132#define PRP_CH2_RZ_HORI_COEF1 0x6c 133#define PRP_CH2_RZ_HORI_COEF2 0x70 134#define PRP_CH2_RZ_HORI_VALID 0x74 135#define PRP_CH2_RZ_VERT_COEF1 0x78 136#define PRP_CH2_RZ_VERT_COEF2 0x7c 137#define PRP_CH2_RZ_VERT_VALID 0x80 138 139#define PRP_CNTL_CH1EN (1 << 0) 140#define PRP_CNTL_CH2EN (1 << 1) 141#define PRP_CNTL_CSIEN (1 << 2) 142#define PRP_CNTL_DATA_IN_YUV420 (0 << 3) 143#define PRP_CNTL_DATA_IN_YUV422 (1 << 3) 144#define PRP_CNTL_DATA_IN_RGB16 (2 << 3) 145#define PRP_CNTL_DATA_IN_RGB32 (3 << 3) 146#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) 147#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) 148#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) 149#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) 150#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) 151#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) 152#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) 153#define PRP_CNTL_CH1_LEN (1 << 9) 154#define PRP_CNTL_CH2_LEN (1 << 10) 155#define PRP_CNTL_SKIP_FRAME (1 << 11) 156#define PRP_CNTL_SWRST (1 << 12) 157#define PRP_CNTL_CLKEN (1 << 13) 158#define PRP_CNTL_WEN (1 << 14) 159#define PRP_CNTL_CH1BYP (1 << 15) 160#define PRP_CNTL_IN_TSKIP(x) ((x) << 16) 161#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) 162#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) 163#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) 164#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) 165#define PRP_CNTL_CH2B1EN (1 << 29) 166#define PRP_CNTL_CH2B2EN (1 << 30) 167#define PRP_CNTL_CH2FEN (1 << 31) 168 169/* IRQ Enable and status register */ 170#define PRP_INTR_RDERR (1 << 0) 171#define PRP_INTR_CH1WERR (1 << 1) 172#define PRP_INTR_CH2WERR (1 << 2) 173#define PRP_INTR_CH1FC (1 << 3) 174#define PRP_INTR_CH2FC (1 << 5) 175#define PRP_INTR_LBOVF (1 << 7) 176#define PRP_INTR_CH2OVF (1 << 8) 177 178/* Resizing registers */ 179#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) 180#define PRP_RZ_VALID_BILINEAR (1 << 31) 181 182#define MAX_VIDEO_MEM 16 183 184#define RESIZE_NUM_MIN 1 185#define RESIZE_NUM_MAX 20 186#define BC_COEF 3 187#define SZ_COEF (1 << BC_COEF) 188 189#define RESIZE_DIR_H 0 190#define RESIZE_DIR_V 1 191 192#define RESIZE_ALGO_BILINEAR 0 193#define RESIZE_ALGO_AVERAGING 1 194 195struct mx2_prp_cfg { 196 int channel; 197 u32 in_fmt; 198 u32 out_fmt; 199 u32 src_pixel; 200 u32 ch1_pixel; 201 u32 irq_flags; 202 u32 csicr1; 203}; 204 205/* prp resizing parameters */ 206struct emma_prp_resize { 207 int algo; /* type of algorithm used */ 208 int len; /* number of coefficients */ 209 unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ 210}; 211 212/* prp configuration for a client-host fmt pair */ 213struct mx2_fmt_cfg { 214 enum v4l2_mbus_pixelcode in_fmt; 215 u32 out_fmt; 216 struct mx2_prp_cfg cfg; 217}; 218 219struct mx2_buf_internal { 220 struct list_head queue; 221 int bufnum; 222 bool discard; 223}; 224 225/* buffer for one video frame */ 226struct mx2_buffer { 227 /* common v4l buffer stuff -- must be first */ 228 struct vb2_buffer vb; 229 struct mx2_buf_internal internal; 230}; 231 232enum mx2_camera_type { 233 IMX27_CAMERA, 234}; 235 236struct mx2_camera_dev { 237 struct device *dev; 238 struct soc_camera_host soc_host; 239 struct clk *clk_emma_ahb, *clk_emma_ipg; 240 struct clk *clk_csi_ahb, *clk_csi_per; 241 242 void __iomem *base_csi, *base_emma; 243 244 struct mx2_camera_platform_data *pdata; 245 unsigned long platform_flags; 246 247 struct list_head capture; 248 struct list_head active_bufs; 249 struct list_head discard; 250 251 spinlock_t lock; 252 253 int dma; 254 struct mx2_buffer *active; 255 struct mx2_buffer *fb1_active; 256 struct mx2_buffer *fb2_active; 257 258 u32 csicr1; 259 enum mx2_camera_type devtype; 260 261 struct mx2_buf_internal buf_discard[2]; 262 void *discard_buffer; 263 dma_addr_t discard_buffer_dma; 264 size_t discard_size; 265 struct mx2_fmt_cfg *emma_prp; 266 struct emma_prp_resize resizing[2]; 267 unsigned int s_width, s_height; 268 u32 frame_count; 269 struct vb2_alloc_ctx *alloc_ctx; 270}; 271 272static struct platform_device_id mx2_camera_devtype[] = { 273 { 274 .name = "imx27-camera", 275 .driver_data = IMX27_CAMERA, 276 }, { 277 /* sentinel */ 278 } 279}; 280MODULE_DEVICE_TABLE(platform, mx2_camera_devtype); 281 282static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) 283{ 284 return container_of(int_buf, struct mx2_buffer, internal); 285} 286 287static struct mx2_fmt_cfg mx27_emma_prp_table[] = { 288 /* 289 * This is a generic configuration which is valid for most 290 * prp input-output format combinations. 291 * We set the incoming and outgoing pixelformat to a 292 * 16 Bit wide format and adjust the bytesperline 293 * accordingly. With this configuration the inputdata 294 * will not be changed by the emma and could be any type 295 * of 16 Bit Pixelformat. 296 */ 297 { 298 .in_fmt = 0, 299 .out_fmt = 0, 300 .cfg = { 301 .channel = 1, 302 .in_fmt = PRP_CNTL_DATA_IN_RGB16, 303 .out_fmt = PRP_CNTL_CH1_OUT_RGB16, 304 .src_pixel = 0x2ca00565, /* RGB565 */ 305 .ch1_pixel = 0x2ca00565, /* RGB565 */ 306 .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | 307 PRP_INTR_CH1FC | PRP_INTR_LBOVF, 308 .csicr1 = 0, 309 } 310 }, 311 { 312 .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8, 313 .out_fmt = V4L2_PIX_FMT_YUYV, 314 .cfg = { 315 .channel = 1, 316 .in_fmt = PRP_CNTL_DATA_IN_YUV422, 317 .out_fmt = PRP_CNTL_CH1_OUT_YUV422, 318 .src_pixel = 0x22000888, /* YUV422 (YUYV) */ 319 .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ 320 .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | 321 PRP_INTR_CH1FC | PRP_INTR_LBOVF, 322 .csicr1 = CSICR1_SWAP16_EN, 323 } 324 }, 325 { 326 .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, 327 .out_fmt = V4L2_PIX_FMT_YUYV, 328 .cfg = { 329 .channel = 1, 330 .in_fmt = PRP_CNTL_DATA_IN_YUV422, 331 .out_fmt = PRP_CNTL_CH1_OUT_YUV422, 332 .src_pixel = 0x22000888, /* YUV422 (YUYV) */ 333 .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ 334 .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | 335 PRP_INTR_CH1FC | PRP_INTR_LBOVF, 336 .csicr1 = CSICR1_PACK_DIR, 337 } 338 }, 339 { 340 .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, 341 .out_fmt = V4L2_PIX_FMT_YUV420, 342 .cfg = { 343 .channel = 2, 344 .in_fmt = PRP_CNTL_DATA_IN_YUV422, 345 .out_fmt = PRP_CNTL_CH2_OUT_YUV420, 346 .src_pixel = 0x22000888, /* YUV422 (YUYV) */ 347 .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | 348 PRP_INTR_CH2FC | PRP_INTR_LBOVF | 349 PRP_INTR_CH2OVF, 350 .csicr1 = CSICR1_PACK_DIR, 351 } 352 }, 353 { 354 .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8, 355 .out_fmt = V4L2_PIX_FMT_YUV420, 356 .cfg = { 357 .channel = 2, 358 .in_fmt = PRP_CNTL_DATA_IN_YUV422, 359 .out_fmt = PRP_CNTL_CH2_OUT_YUV420, 360 .src_pixel = 0x22000888, /* YUV422 (YUYV) */ 361 .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | 362 PRP_INTR_CH2FC | PRP_INTR_LBOVF | 363 PRP_INTR_CH2OVF, 364 .csicr1 = CSICR1_SWAP16_EN, 365 } 366 }, 367}; 368 369static struct mx2_fmt_cfg *mx27_emma_prp_get_format( 370 enum v4l2_mbus_pixelcode in_fmt, 371 u32 out_fmt) 372{ 373 int i; 374 375 for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++) 376 if ((mx27_emma_prp_table[i].in_fmt == in_fmt) && 377 (mx27_emma_prp_table[i].out_fmt == out_fmt)) { 378 return &mx27_emma_prp_table[i]; 379 } 380 /* If no match return the most generic configuration */ 381 return &mx27_emma_prp_table[0]; 382}; 383 384static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, 385 unsigned long phys, int bufnum) 386{ 387 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 388 389 if (prp->cfg.channel == 1) { 390 writel(phys, pcdev->base_emma + 391 PRP_DEST_RGB1_PTR + 4 * bufnum); 392 } else { 393 writel(phys, pcdev->base_emma + 394 PRP_DEST_Y_PTR - 0x14 * bufnum); 395 if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { 396 u32 imgsize = pcdev->soc_host.icd->user_height * 397 pcdev->soc_host.icd->user_width; 398 399 writel(phys + imgsize, pcdev->base_emma + 400 PRP_DEST_CB_PTR - 0x14 * bufnum); 401 writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + 402 PRP_DEST_CR_PTR - 0x14 * bufnum); 403 } 404 } 405} 406 407static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) 408{ 409 clk_disable_unprepare(pcdev->clk_csi_ahb); 410 clk_disable_unprepare(pcdev->clk_csi_per); 411 writel(0, pcdev->base_csi + CSICR1); 412 writel(0, pcdev->base_emma + PRP_CNTL); 413} 414 415static int mx2_camera_add_device(struct soc_camera_device *icd) 416{ 417 dev_info(icd->parent, "Camera driver attached to camera %d\n", 418 icd->devnum); 419 420 return 0; 421} 422 423static void mx2_camera_remove_device(struct soc_camera_device *icd) 424{ 425 dev_info(icd->parent, "Camera driver detached from camera %d\n", 426 icd->devnum); 427} 428 429/* 430 * The following two functions absolutely depend on the fact, that 431 * there can be only one camera on mx2 camera sensor interface 432 */ 433static int mx2_camera_clock_start(struct soc_camera_host *ici) 434{ 435 struct mx2_camera_dev *pcdev = ici->priv; 436 int ret; 437 u32 csicr1; 438 439 ret = clk_prepare_enable(pcdev->clk_csi_ahb); 440 if (ret < 0) 441 return ret; 442 443 ret = clk_prepare_enable(pcdev->clk_csi_per); 444 if (ret < 0) 445 goto exit_csi_ahb; 446 447 csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC | 448 CSICR1_RXFF_LEVEL(0); 449 450 pcdev->csicr1 = csicr1; 451 writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 452 453 pcdev->frame_count = 0; 454 455 return 0; 456 457exit_csi_ahb: 458 clk_disable_unprepare(pcdev->clk_csi_ahb); 459 460 return ret; 461} 462 463static void mx2_camera_clock_stop(struct soc_camera_host *ici) 464{ 465 struct mx2_camera_dev *pcdev = ici->priv; 466 467 mx2_camera_deactivate(pcdev); 468} 469 470/* 471 * Videobuf operations 472 */ 473static int mx2_videobuf_setup(struct vb2_queue *vq, 474 const struct v4l2_format *fmt, 475 unsigned int *count, unsigned int *num_planes, 476 unsigned int sizes[], void *alloc_ctxs[]) 477{ 478 struct soc_camera_device *icd = soc_camera_from_vb2q(vq); 479 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 480 struct mx2_camera_dev *pcdev = ici->priv; 481 482 dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); 483 484 /* TODO: support for VIDIOC_CREATE_BUFS not ready */ 485 if (fmt != NULL) 486 return -ENOTTY; 487 488 alloc_ctxs[0] = pcdev->alloc_ctx; 489 490 sizes[0] = icd->sizeimage; 491 492 if (0 == *count) 493 *count = 32; 494 if (!*num_planes && 495 sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) 496 *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; 497 498 *num_planes = 1; 499 500 return 0; 501} 502 503static int mx2_videobuf_prepare(struct vb2_buffer *vb) 504{ 505 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); 506 int ret = 0; 507 508 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, 509 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); 510 511#ifdef DEBUG 512 /* 513 * This can be useful if you want to see if we actually fill 514 * the buffer with something 515 */ 516 memset((void *)vb2_plane_vaddr(vb, 0), 517 0xaa, vb2_get_plane_payload(vb, 0)); 518#endif 519 520 vb2_set_plane_payload(vb, 0, icd->sizeimage); 521 if (vb2_plane_vaddr(vb, 0) && 522 vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { 523 ret = -EINVAL; 524 goto out; 525 } 526 527 return 0; 528 529out: 530 return ret; 531} 532 533static void mx2_videobuf_queue(struct vb2_buffer *vb) 534{ 535 struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); 536 struct soc_camera_host *ici = 537 to_soc_camera_host(icd->parent); 538 struct mx2_camera_dev *pcdev = ici->priv; 539 struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); 540 unsigned long flags; 541 542 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, 543 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); 544 545 spin_lock_irqsave(&pcdev->lock, flags); 546 547 list_add_tail(&buf->internal.queue, &pcdev->capture); 548 549 spin_unlock_irqrestore(&pcdev->lock, flags); 550} 551 552static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, 553 int bytesperline) 554{ 555 struct soc_camera_host *ici = 556 to_soc_camera_host(icd->parent); 557 struct mx2_camera_dev *pcdev = ici->priv; 558 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 559 560 writel((pcdev->s_width << 16) | pcdev->s_height, 561 pcdev->base_emma + PRP_SRC_FRAME_SIZE); 562 writel(prp->cfg.src_pixel, 563 pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); 564 if (prp->cfg.channel == 1) { 565 writel((icd->user_width << 16) | icd->user_height, 566 pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); 567 writel(bytesperline, 568 pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); 569 writel(prp->cfg.ch1_pixel, 570 pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); 571 } else { /* channel 2 */ 572 writel((icd->user_width << 16) | icd->user_height, 573 pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); 574 } 575 576 /* Enable interrupts */ 577 writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); 578} 579 580static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) 581{ 582 int dir; 583 584 for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { 585 unsigned char *s = pcdev->resizing[dir].s; 586 int len = pcdev->resizing[dir].len; 587 unsigned int coeff[2] = {0, 0}; 588 unsigned int valid = 0; 589 int i; 590 591 if (len == 0) 592 continue; 593 594 for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { 595 int j; 596 597 j = i > 9 ? 1 : 0; 598 coeff[j] = (coeff[j] << BC_COEF) | 599 (s[i] & (SZ_COEF - 1)); 600 601 if (i == 5 || i == 15) 602 coeff[j] <<= 1; 603 604 valid = (valid << 1) | (s[i] >> BC_COEF); 605 } 606 607 valid |= PRP_RZ_VALID_TBL_LEN(len); 608 609 if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) 610 valid |= PRP_RZ_VALID_BILINEAR; 611 612 if (pcdev->emma_prp->cfg.channel == 1) { 613 if (dir == RESIZE_DIR_H) { 614 writel(coeff[0], pcdev->base_emma + 615 PRP_CH1_RZ_HORI_COEF1); 616 writel(coeff[1], pcdev->base_emma + 617 PRP_CH1_RZ_HORI_COEF2); 618 writel(valid, pcdev->base_emma + 619 PRP_CH1_RZ_HORI_VALID); 620 } else { 621 writel(coeff[0], pcdev->base_emma + 622 PRP_CH1_RZ_VERT_COEF1); 623 writel(coeff[1], pcdev->base_emma + 624 PRP_CH1_RZ_VERT_COEF2); 625 writel(valid, pcdev->base_emma + 626 PRP_CH1_RZ_VERT_VALID); 627 } 628 } else { 629 if (dir == RESIZE_DIR_H) { 630 writel(coeff[0], pcdev->base_emma + 631 PRP_CH2_RZ_HORI_COEF1); 632 writel(coeff[1], pcdev->base_emma + 633 PRP_CH2_RZ_HORI_COEF2); 634 writel(valid, pcdev->base_emma + 635 PRP_CH2_RZ_HORI_VALID); 636 } else { 637 writel(coeff[0], pcdev->base_emma + 638 PRP_CH2_RZ_VERT_COEF1); 639 writel(coeff[1], pcdev->base_emma + 640 PRP_CH2_RZ_VERT_COEF2); 641 writel(valid, pcdev->base_emma + 642 PRP_CH2_RZ_VERT_VALID); 643 } 644 } 645 } 646} 647 648static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) 649{ 650 struct soc_camera_device *icd = soc_camera_from_vb2q(q); 651 struct soc_camera_host *ici = 652 to_soc_camera_host(icd->parent); 653 struct mx2_camera_dev *pcdev = ici->priv; 654 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 655 struct vb2_buffer *vb; 656 struct mx2_buffer *buf; 657 unsigned long phys; 658 int bytesperline; 659 unsigned long flags; 660 661 if (count < 2) 662 return -ENOBUFS; 663 664 spin_lock_irqsave(&pcdev->lock, flags); 665 666 buf = list_first_entry(&pcdev->capture, struct mx2_buffer, 667 internal.queue); 668 buf->internal.bufnum = 0; 669 vb = &buf->vb; 670 671 phys = vb2_dma_contig_plane_dma_addr(vb, 0); 672 mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); 673 list_move_tail(pcdev->capture.next, &pcdev->active_bufs); 674 675 buf = list_first_entry(&pcdev->capture, struct mx2_buffer, 676 internal.queue); 677 buf->internal.bufnum = 1; 678 vb = &buf->vb; 679 680 phys = vb2_dma_contig_plane_dma_addr(vb, 0); 681 mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); 682 list_move_tail(pcdev->capture.next, &pcdev->active_bufs); 683 684 bytesperline = soc_mbus_bytes_per_line(icd->user_width, 685 icd->current_fmt->host_fmt); 686 if (bytesperline < 0) { 687 spin_unlock_irqrestore(&pcdev->lock, flags); 688 return bytesperline; 689 } 690 691 /* 692 * I didn't manage to properly enable/disable the prp 693 * on a per frame basis during running transfers, 694 * thus we allocate a buffer here and use it to 695 * discard frames when no buffer is available. 696 * Feel free to work on this ;) 697 */ 698 pcdev->discard_size = icd->user_height * bytesperline; 699 pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, 700 pcdev->discard_size, 701 &pcdev->discard_buffer_dma, GFP_ATOMIC); 702 if (!pcdev->discard_buffer) { 703 spin_unlock_irqrestore(&pcdev->lock, flags); 704 return -ENOMEM; 705 } 706 707 pcdev->buf_discard[0].discard = true; 708 list_add_tail(&pcdev->buf_discard[0].queue, 709 &pcdev->discard); 710 711 pcdev->buf_discard[1].discard = true; 712 list_add_tail(&pcdev->buf_discard[1].queue, 713 &pcdev->discard); 714 715 mx2_prp_resize_commit(pcdev); 716 717 mx27_camera_emma_buf_init(icd, bytesperline); 718 719 if (prp->cfg.channel == 1) { 720 writel(PRP_CNTL_CH1EN | 721 PRP_CNTL_CSIEN | 722 prp->cfg.in_fmt | 723 prp->cfg.out_fmt | 724 PRP_CNTL_CH1_LEN | 725 PRP_CNTL_CH1BYP | 726 PRP_CNTL_CH1_TSKIP(0) | 727 PRP_CNTL_IN_TSKIP(0), 728 pcdev->base_emma + PRP_CNTL); 729 } else { 730 writel(PRP_CNTL_CH2EN | 731 PRP_CNTL_CSIEN | 732 prp->cfg.in_fmt | 733 prp->cfg.out_fmt | 734 PRP_CNTL_CH2_LEN | 735 PRP_CNTL_CH2_TSKIP(0) | 736 PRP_CNTL_IN_TSKIP(0), 737 pcdev->base_emma + PRP_CNTL); 738 } 739 spin_unlock_irqrestore(&pcdev->lock, flags); 740 741 return 0; 742} 743 744static int mx2_stop_streaming(struct vb2_queue *q) 745{ 746 struct soc_camera_device *icd = soc_camera_from_vb2q(q); 747 struct soc_camera_host *ici = 748 to_soc_camera_host(icd->parent); 749 struct mx2_camera_dev *pcdev = ici->priv; 750 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 751 unsigned long flags; 752 void *b; 753 u32 cntl; 754 755 spin_lock_irqsave(&pcdev->lock, flags); 756 757 cntl = readl(pcdev->base_emma + PRP_CNTL); 758 if (prp->cfg.channel == 1) { 759 writel(cntl & ~PRP_CNTL_CH1EN, 760 pcdev->base_emma + PRP_CNTL); 761 } else { 762 writel(cntl & ~PRP_CNTL_CH2EN, 763 pcdev->base_emma + PRP_CNTL); 764 } 765 INIT_LIST_HEAD(&pcdev->capture); 766 INIT_LIST_HEAD(&pcdev->active_bufs); 767 INIT_LIST_HEAD(&pcdev->discard); 768 769 b = pcdev->discard_buffer; 770 pcdev->discard_buffer = NULL; 771 772 spin_unlock_irqrestore(&pcdev->lock, flags); 773 774 dma_free_coherent(ici->v4l2_dev.dev, 775 pcdev->discard_size, b, pcdev->discard_buffer_dma); 776 777 return 0; 778} 779 780static struct vb2_ops mx2_videobuf_ops = { 781 .queue_setup = mx2_videobuf_setup, 782 .buf_prepare = mx2_videobuf_prepare, 783 .buf_queue = mx2_videobuf_queue, 784 .start_streaming = mx2_start_streaming, 785 .stop_streaming = mx2_stop_streaming, 786}; 787 788static int mx2_camera_init_videobuf(struct vb2_queue *q, 789 struct soc_camera_device *icd) 790{ 791 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 792 q->io_modes = VB2_MMAP | VB2_USERPTR; 793 q->drv_priv = icd; 794 q->ops = &mx2_videobuf_ops; 795 q->mem_ops = &vb2_dma_contig_memops; 796 q->buf_struct_size = sizeof(struct mx2_buffer); 797 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 798 799 return vb2_queue_init(q); 800} 801 802#define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ 803 V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ 804 V4L2_MBUS_VSYNC_ACTIVE_LOW | \ 805 V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ 806 V4L2_MBUS_HSYNC_ACTIVE_LOW | \ 807 V4L2_MBUS_PCLK_SAMPLE_RISING | \ 808 V4L2_MBUS_PCLK_SAMPLE_FALLING | \ 809 V4L2_MBUS_DATA_ACTIVE_HIGH | \ 810 V4L2_MBUS_DATA_ACTIVE_LOW) 811 812static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) 813{ 814 u32 cntl; 815 int count = 0; 816 817 cntl = readl(pcdev->base_emma + PRP_CNTL); 818 writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); 819 while (count++ < 100) { 820 if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) 821 return 0; 822 barrier(); 823 udelay(1); 824 } 825 826 return -ETIMEDOUT; 827} 828 829static int mx2_camera_set_bus_param(struct soc_camera_device *icd) 830{ 831 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 832 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 833 struct mx2_camera_dev *pcdev = ici->priv; 834 struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; 835 unsigned long common_flags; 836 int ret; 837 int bytesperline; 838 u32 csicr1 = pcdev->csicr1; 839 840 ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); 841 if (!ret) { 842 common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS); 843 if (!common_flags) { 844 dev_warn(icd->parent, 845 "Flags incompatible: camera 0x%x, host 0x%x\n", 846 cfg.flags, MX2_BUS_FLAGS); 847 return -EINVAL; 848 } 849 } else if (ret != -ENOIOCTLCMD) { 850 return ret; 851 } else { 852 common_flags = MX2_BUS_FLAGS; 853 } 854 855 if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && 856 (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { 857 if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH) 858 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; 859 else 860 common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; 861 } 862 863 if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && 864 (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { 865 if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING) 866 common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; 867 else 868 common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; 869 } 870 871 cfg.flags = common_flags; 872 ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); 873 if (ret < 0 && ret != -ENOIOCTLCMD) { 874 dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", 875 common_flags, ret); 876 return ret; 877 } 878 879 csicr1 = (csicr1 & ~CSICR1_FMT_MASK) | pcdev->emma_prp->cfg.csicr1; 880 881 if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) 882 csicr1 |= CSICR1_REDGE; 883 if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) 884 csicr1 |= CSICR1_SOF_POL; 885 if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) 886 csicr1 |= CSICR1_HSYNC_POL; 887 if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) 888 csicr1 |= CSICR1_EXT_VSYNC; 889 if (pcdev->platform_flags & MX2_CAMERA_CCIR) 890 csicr1 |= CSICR1_CCIR_EN; 891 if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE) 892 csicr1 |= CSICR1_CCIR_MODE; 893 if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK) 894 csicr1 |= CSICR1_GCLK_MODE; 895 if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) 896 csicr1 |= CSICR1_INV_DATA; 897 898 pcdev->csicr1 = csicr1; 899 900 bytesperline = soc_mbus_bytes_per_line(icd->user_width, 901 icd->current_fmt->host_fmt); 902 if (bytesperline < 0) 903 return bytesperline; 904 905 ret = mx27_camera_emma_prp_reset(pcdev); 906 if (ret) 907 return ret; 908 909 writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 910 911 return 0; 912} 913 914static int mx2_camera_set_crop(struct soc_camera_device *icd, 915 const struct v4l2_crop *a) 916{ 917 struct v4l2_crop a_writable = *a; 918 struct v4l2_rect *rect = &a_writable.c; 919 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 920 struct v4l2_mbus_framefmt mf; 921 int ret; 922 923 soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); 924 soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); 925 926 ret = v4l2_subdev_call(sd, video, s_crop, a); 927 if (ret < 0) 928 return ret; 929 930 /* The capture device might have changed its output */ 931 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); 932 if (ret < 0) 933 return ret; 934 935 dev_dbg(icd->parent, "Sensor cropped %dx%d\n", 936 mf.width, mf.height); 937 938 icd->user_width = mf.width; 939 icd->user_height = mf.height; 940 941 return ret; 942} 943 944static int mx2_camera_get_formats(struct soc_camera_device *icd, 945 unsigned int idx, 946 struct soc_camera_format_xlate *xlate) 947{ 948 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 949 const struct soc_mbus_pixelfmt *fmt; 950 struct device *dev = icd->parent; 951 enum v4l2_mbus_pixelcode code; 952 int ret, formats = 0; 953 954 ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); 955 if (ret < 0) 956 /* no more formats */ 957 return 0; 958 959 fmt = soc_mbus_get_fmtdesc(code); 960 if (!fmt) { 961 dev_err(dev, "Invalid format code #%u: %d\n", idx, code); 962 return 0; 963 } 964 965 if (code == V4L2_MBUS_FMT_YUYV8_2X8 || 966 code == V4L2_MBUS_FMT_UYVY8_2X8) { 967 formats++; 968 if (xlate) { 969 /* 970 * CH2 can output YUV420 which is a standard format in 971 * soc_mediabus.c 972 */ 973 xlate->host_fmt = 974 soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8); 975 xlate->code = code; 976 dev_dbg(dev, "Providing host format %s for sensor code %d\n", 977 xlate->host_fmt->name, code); 978 xlate++; 979 } 980 } 981 982 if (code == V4L2_MBUS_FMT_UYVY8_2X8) { 983 formats++; 984 if (xlate) { 985 xlate->host_fmt = 986 soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8); 987 xlate->code = code; 988 dev_dbg(dev, "Providing host format %s for sensor code %d\n", 989 xlate->host_fmt->name, code); 990 xlate++; 991 } 992 } 993 994 /* Generic pass-trough */ 995 formats++; 996 if (xlate) { 997 xlate->host_fmt = fmt; 998 xlate->code = code; 999 xlate++; 1000 } 1001 return formats; 1002} 1003 1004static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, 1005 struct v4l2_mbus_framefmt *mf_in, 1006 struct v4l2_pix_format *pix_out, bool apply) 1007{ 1008 int num, den; 1009 unsigned long m; 1010 int i, dir; 1011 1012 for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { 1013 struct emma_prp_resize tmprsz; 1014 unsigned char *s = tmprsz.s; 1015 int len = 0; 1016 int in, out; 1017 1018 if (dir == RESIZE_DIR_H) { 1019 in = mf_in->width; 1020 out = pix_out->width; 1021 } else { 1022 in = mf_in->height; 1023 out = pix_out->height; 1024 } 1025 1026 if (in < out) 1027 return -EINVAL; 1028 else if (in == out) 1029 continue; 1030 1031 /* Calculate ratio */ 1032 m = gcd(in, out); 1033 num = in / m; 1034 den = out / m; 1035 if (num > RESIZE_NUM_MAX) 1036 return -EINVAL; 1037 1038 if ((num >= 2 * den) && (den == 1) && 1039 (num < 9) && (!(num & 0x01))) { 1040 int sum = 0; 1041 int j; 1042 1043 /* Average scaling for >= 2:1 ratios */ 1044 /* Support can be added for num >=9 and odd values */ 1045 1046 tmprsz.algo = RESIZE_ALGO_AVERAGING; 1047 len = num; 1048 1049 for (i = 0; i < (len / 2); i++) 1050 s[i] = 8; 1051 1052 do { 1053 for (i = 0; i < (len / 2); i++) { 1054 s[i] = s[i] >> 1; 1055 sum = 0; 1056 for (j = 0; j < (len / 2); j++) 1057 sum += s[j]; 1058 if (sum == 4) 1059 break; 1060 } 1061 } while (sum != 4); 1062 1063 for (i = (len / 2); i < len; i++) 1064 s[i] = s[len - i - 1]; 1065 1066 s[len - 1] |= SZ_COEF; 1067 } else { 1068 /* bilinear scaling for < 2:1 ratios */ 1069 int v; /* overflow counter */ 1070 int coeff, nxt; /* table output */ 1071 int in_pos_inc = 2 * den; 1072 int out_pos = num; 1073 int out_pos_inc = 2 * num; 1074 int init_carry = num - den; 1075 int carry = init_carry; 1076 1077 tmprsz.algo = RESIZE_ALGO_BILINEAR; 1078 v = den + in_pos_inc; 1079 do { 1080 coeff = v - out_pos; 1081 out_pos += out_pos_inc; 1082 carry += out_pos_inc; 1083 for (nxt = 0; v < out_pos; nxt++) { 1084 v += in_pos_inc; 1085 carry -= in_pos_inc; 1086 } 1087 1088 if (len > RESIZE_NUM_MAX) 1089 return -EINVAL; 1090 1091 coeff = ((coeff << BC_COEF) + 1092 (in_pos_inc >> 1)) / in_pos_inc; 1093 1094 if (coeff >= (SZ_COEF - 1)) 1095 coeff--; 1096 1097 coeff |= SZ_COEF; 1098 s[len] = (unsigned char)coeff; 1099 len++; 1100 1101 for (i = 1; i < nxt; i++) { 1102 if (len >= RESIZE_NUM_MAX) 1103 return -EINVAL; 1104 s[len] = 0; 1105 len++; 1106 } 1107 } while (carry != init_carry); 1108 } 1109 tmprsz.len = len; 1110 if (dir == RESIZE_DIR_H) 1111 mf_in->width = pix_out->width; 1112 else 1113 mf_in->height = pix_out->height; 1114 1115 if (apply) 1116 memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); 1117 } 1118 return 0; 1119} 1120 1121static int mx2_camera_set_fmt(struct soc_camera_device *icd, 1122 struct v4l2_format *f) 1123{ 1124 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1125 struct mx2_camera_dev *pcdev = ici->priv; 1126 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1127 const struct soc_camera_format_xlate *xlate; 1128 struct v4l2_pix_format *pix = &f->fmt.pix; 1129 struct v4l2_mbus_framefmt mf; 1130 int ret; 1131 1132 dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", 1133 __func__, pix->width, pix->height); 1134 1135 xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); 1136 if (!xlate) { 1137 dev_warn(icd->parent, "Format %x not found\n", 1138 pix->pixelformat); 1139 return -EINVAL; 1140 } 1141 1142 mf.width = pix->width; 1143 mf.height = pix->height; 1144 mf.field = pix->field; 1145 mf.colorspace = pix->colorspace; 1146 mf.code = xlate->code; 1147 1148 ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); 1149 if (ret < 0 && ret != -ENOIOCTLCMD) 1150 return ret; 1151 1152 /* Store width and height returned by the sensor for resizing */ 1153 pcdev->s_width = mf.width; 1154 pcdev->s_height = mf.height; 1155 dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", 1156 __func__, pcdev->s_width, pcdev->s_height); 1157 1158 pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, 1159 xlate->host_fmt->fourcc); 1160 1161 memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); 1162 if ((mf.width != pix->width || mf.height != pix->height) && 1163 pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { 1164 if (mx2_emmaprp_resize(pcdev, &mf, pix, true) < 0) 1165 dev_dbg(icd->parent, "%s: can't resize\n", __func__); 1166 } 1167 1168 if (mf.code != xlate->code) 1169 return -EINVAL; 1170 1171 pix->width = mf.width; 1172 pix->height = mf.height; 1173 pix->field = mf.field; 1174 pix->colorspace = mf.colorspace; 1175 icd->current_fmt = xlate; 1176 1177 dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", 1178 __func__, pix->width, pix->height); 1179 1180 return 0; 1181} 1182 1183static int mx2_camera_try_fmt(struct soc_camera_device *icd, 1184 struct v4l2_format *f) 1185{ 1186 struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1187 const struct soc_camera_format_xlate *xlate; 1188 struct v4l2_pix_format *pix = &f->fmt.pix; 1189 struct v4l2_mbus_framefmt mf; 1190 __u32 pixfmt = pix->pixelformat; 1191 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1192 struct mx2_camera_dev *pcdev = ici->priv; 1193 struct mx2_fmt_cfg *emma_prp; 1194 int ret; 1195 1196 dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", 1197 __func__, pix->width, pix->height); 1198 1199 xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 1200 if (pixfmt && !xlate) { 1201 dev_warn(icd->parent, "Format %x not found\n", pixfmt); 1202 return -EINVAL; 1203 } 1204 1205 /* 1206 * limit to MX27 hardware capabilities: width must be a multiple of 8 as 1207 * requested by the CSI. (Table 39-2 in the i.MX27 Reference Manual). 1208 */ 1209 pix->width &= ~0x7; 1210 1211 /* limit to sensor capabilities */ 1212 mf.width = pix->width; 1213 mf.height = pix->height; 1214 mf.field = pix->field; 1215 mf.colorspace = pix->colorspace; 1216 mf.code = xlate->code; 1217 1218 ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); 1219 if (ret < 0) 1220 return ret; 1221 1222 dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", 1223 __func__, pcdev->s_width, pcdev->s_height); 1224 1225 /* If the sensor does not support image size try PrP resizing */ 1226 emma_prp = mx27_emma_prp_get_format(xlate->code, 1227 xlate->host_fmt->fourcc); 1228 1229 if ((mf.width != pix->width || mf.height != pix->height) && 1230 emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { 1231 if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) 1232 dev_dbg(icd->parent, "%s: can't resize\n", __func__); 1233 } 1234 1235 if (mf.field == V4L2_FIELD_ANY) 1236 mf.field = V4L2_FIELD_NONE; 1237 /* 1238 * Driver supports interlaced images provided they have 1239 * both fields so that they can be processed as if they 1240 * were progressive. 1241 */ 1242 if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) { 1243 dev_err(icd->parent, "Field type %d unsupported.\n", 1244 mf.field); 1245 return -EINVAL; 1246 } 1247 1248 pix->width = mf.width; 1249 pix->height = mf.height; 1250 pix->field = mf.field; 1251 pix->colorspace = mf.colorspace; 1252 1253 dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", 1254 __func__, pix->width, pix->height); 1255 1256 return 0; 1257} 1258 1259static int mx2_camera_querycap(struct soc_camera_host *ici, 1260 struct v4l2_capability *cap) 1261{ 1262 /* cap->name is set by the friendly caller:-> */ 1263 strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card)); 1264 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 1265 1266 return 0; 1267} 1268 1269static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) 1270{ 1271 struct soc_camera_device *icd = file->private_data; 1272 1273 return vb2_poll(&icd->vb2_vidq, file, pt); 1274} 1275 1276static struct soc_camera_host_ops mx2_soc_camera_host_ops = { 1277 .owner = THIS_MODULE, 1278 .add = mx2_camera_add_device, 1279 .remove = mx2_camera_remove_device, 1280 .clock_start = mx2_camera_clock_start, 1281 .clock_stop = mx2_camera_clock_stop, 1282 .set_fmt = mx2_camera_set_fmt, 1283 .set_crop = mx2_camera_set_crop, 1284 .get_formats = mx2_camera_get_formats, 1285 .try_fmt = mx2_camera_try_fmt, 1286 .init_videobuf2 = mx2_camera_init_videobuf, 1287 .poll = mx2_camera_poll, 1288 .querycap = mx2_camera_querycap, 1289 .set_bus_param = mx2_camera_set_bus_param, 1290}; 1291 1292static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, 1293 int bufnum, bool err) 1294{ 1295#ifdef DEBUG 1296 struct mx2_fmt_cfg *prp = pcdev->emma_prp; 1297#endif 1298 struct mx2_buf_internal *ibuf; 1299 struct mx2_buffer *buf; 1300 struct vb2_buffer *vb; 1301 unsigned long phys; 1302 1303 ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, 1304 queue); 1305 1306 BUG_ON(ibuf->bufnum != bufnum); 1307 1308 if (ibuf->discard) { 1309 /* 1310 * Discard buffer must not be returned to user space. 1311 * Just return it to the discard queue. 1312 */ 1313 list_move_tail(pcdev->active_bufs.next, &pcdev->discard); 1314 } else { 1315 buf = mx2_ibuf_to_buf(ibuf); 1316 1317 vb = &buf->vb; 1318#ifdef DEBUG 1319 phys = vb2_dma_contig_plane_dma_addr(vb, 0); 1320 if (prp->cfg.channel == 1) { 1321 if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 1322 4 * bufnum) != phys) { 1323 dev_err(pcdev->dev, "%lx != %x\n", phys, 1324 readl(pcdev->base_emma + 1325 PRP_DEST_RGB1_PTR + 4 * bufnum)); 1326 } 1327 } else { 1328 if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - 1329 0x14 * bufnum) != phys) { 1330 dev_err(pcdev->dev, "%lx != %x\n", phys, 1331 readl(pcdev->base_emma + 1332 PRP_DEST_Y_PTR - 0x14 * bufnum)); 1333 } 1334 } 1335#endif 1336 dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, 1337 vb2_plane_vaddr(vb, 0), 1338 vb2_get_plane_payload(vb, 0)); 1339 1340 list_del_init(&buf->internal.queue); 1341 v4l2_get_timestamp(&vb->v4l2_buf.timestamp); 1342 vb->v4l2_buf.sequence = pcdev->frame_count; 1343 if (err) 1344 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); 1345 else 1346 vb2_buffer_done(vb, VB2_BUF_STATE_DONE); 1347 } 1348 1349 pcdev->frame_count++; 1350 1351 if (list_empty(&pcdev->capture)) { 1352 if (list_empty(&pcdev->discard)) { 1353 dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", 1354 __func__); 1355 return; 1356 } 1357 1358 ibuf = list_first_entry(&pcdev->discard, 1359 struct mx2_buf_internal, queue); 1360 ibuf->bufnum = bufnum; 1361 1362 list_move_tail(pcdev->discard.next, &pcdev->active_bufs); 1363 mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); 1364 return; 1365 } 1366 1367 buf = list_first_entry(&pcdev->capture, struct mx2_buffer, 1368 internal.queue); 1369 1370 buf->internal.bufnum = bufnum; 1371 1372 list_move_tail(pcdev->capture.next, &pcdev->active_bufs); 1373 1374 vb = &buf->vb; 1375 1376 phys = vb2_dma_contig_plane_dma_addr(vb, 0); 1377 mx27_update_emma_buf(pcdev, phys, bufnum); 1378} 1379 1380static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) 1381{ 1382 struct mx2_camera_dev *pcdev = data; 1383 unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); 1384 struct mx2_buf_internal *ibuf; 1385 1386 spin_lock(&pcdev->lock); 1387 1388 if (list_empty(&pcdev->active_bufs)) { 1389 dev_warn(pcdev->dev, "%s: called while active list is empty\n", 1390 __func__); 1391 1392 if (!status) { 1393 spin_unlock(&pcdev->lock); 1394 return IRQ_NONE; 1395 } 1396 } 1397 1398 if (status & (1 << 7)) { /* overflow */ 1399 u32 cntl = readl(pcdev->base_emma + PRP_CNTL); 1400 writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), 1401 pcdev->base_emma + PRP_CNTL); 1402 writel(cntl, pcdev->base_emma + PRP_CNTL); 1403 1404 ibuf = list_first_entry(&pcdev->active_bufs, 1405 struct mx2_buf_internal, queue); 1406 mx27_camera_frame_done_emma(pcdev, 1407 ibuf->bufnum, true); 1408 1409 status &= ~(1 << 7); 1410 } else if (((status & (3 << 5)) == (3 << 5)) || 1411 ((status & (3 << 3)) == (3 << 3))) { 1412 /* 1413 * Both buffers have triggered, process the one we're expecting 1414 * to first 1415 */ 1416 ibuf = list_first_entry(&pcdev->active_bufs, 1417 struct mx2_buf_internal, queue); 1418 mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); 1419 status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ 1420 } else if ((status & (1 << 6)) || (status & (1 << 4))) { 1421 mx27_camera_frame_done_emma(pcdev, 0, false); 1422 } else if ((status & (1 << 5)) || (status & (1 << 3))) { 1423 mx27_camera_frame_done_emma(pcdev, 1, false); 1424 } 1425 1426 spin_unlock(&pcdev->lock); 1427 writel(status, pcdev->base_emma + PRP_INTRSTATUS); 1428 1429 return IRQ_HANDLED; 1430} 1431 1432static int mx27_camera_emma_init(struct platform_device *pdev) 1433{ 1434 struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev); 1435 struct resource *res_emma; 1436 int irq_emma; 1437 int err = 0; 1438 1439 res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1440 irq_emma = platform_get_irq(pdev, 1); 1441 if (!res_emma || !irq_emma) { 1442 dev_err(pcdev->dev, "no EMMA resources\n"); 1443 err = -ENODEV; 1444 goto out; 1445 } 1446 1447 pcdev->base_emma = devm_ioremap_resource(pcdev->dev, res_emma); 1448 if (IS_ERR(pcdev->base_emma)) { 1449 err = PTR_ERR(pcdev->base_emma); 1450 goto out; 1451 } 1452 1453 err = devm_request_irq(pcdev->dev, irq_emma, mx27_camera_emma_irq, 0, 1454 MX2_CAM_DRV_NAME, pcdev); 1455 if (err) { 1456 dev_err(pcdev->dev, "Camera EMMA interrupt register failed\n"); 1457 goto out; 1458 } 1459 1460 pcdev->clk_emma_ipg = devm_clk_get(pcdev->dev, "emma-ipg"); 1461 if (IS_ERR(pcdev->clk_emma_ipg)) { 1462 err = PTR_ERR(pcdev->clk_emma_ipg); 1463 goto out; 1464 } 1465 1466 clk_prepare_enable(pcdev->clk_emma_ipg); 1467 1468 pcdev->clk_emma_ahb = devm_clk_get(pcdev->dev, "emma-ahb"); 1469 if (IS_ERR(pcdev->clk_emma_ahb)) { 1470 err = PTR_ERR(pcdev->clk_emma_ahb); 1471 goto exit_clk_emma_ipg; 1472 } 1473 1474 clk_prepare_enable(pcdev->clk_emma_ahb); 1475 1476 err = mx27_camera_emma_prp_reset(pcdev); 1477 if (err) 1478 goto exit_clk_emma_ahb; 1479 1480 return err; 1481 1482exit_clk_emma_ahb: 1483 clk_disable_unprepare(pcdev->clk_emma_ahb); 1484exit_clk_emma_ipg: 1485 clk_disable_unprepare(pcdev->clk_emma_ipg); 1486out: 1487 return err; 1488} 1489 1490static int mx2_camera_probe(struct platform_device *pdev) 1491{ 1492 struct mx2_camera_dev *pcdev; 1493 struct resource *res_csi; 1494 int irq_csi; 1495 int err = 0; 1496 1497 dev_dbg(&pdev->dev, "initialising\n"); 1498 1499 res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1500 irq_csi = platform_get_irq(pdev, 0); 1501 if (res_csi == NULL || irq_csi < 0) { 1502 dev_err(&pdev->dev, "Missing platform resources data\n"); 1503 err = -ENODEV; 1504 goto exit; 1505 } 1506 1507 pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); 1508 if (!pcdev) { 1509 dev_err(&pdev->dev, "Could not allocate pcdev\n"); 1510 err = -ENOMEM; 1511 goto exit; 1512 } 1513 1514 pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb"); 1515 if (IS_ERR(pcdev->clk_csi_ahb)) { 1516 dev_err(&pdev->dev, "Could not get csi ahb clock\n"); 1517 err = PTR_ERR(pcdev->clk_csi_ahb); 1518 goto exit; 1519 } 1520 1521 pcdev->clk_csi_per = devm_clk_get(&pdev->dev, "per"); 1522 if (IS_ERR(pcdev->clk_csi_per)) { 1523 dev_err(&pdev->dev, "Could not get csi per clock\n"); 1524 err = PTR_ERR(pcdev->clk_csi_per); 1525 goto exit; 1526 } 1527 1528 pcdev->pdata = pdev->dev.platform_data; 1529 if (pcdev->pdata) { 1530 long rate; 1531 1532 pcdev->platform_flags = pcdev->pdata->flags; 1533 1534 rate = clk_round_rate(pcdev->clk_csi_per, 1535 pcdev->pdata->clk * 2); 1536 if (rate <= 0) { 1537 err = -ENODEV; 1538 goto exit; 1539 } 1540 err = clk_set_rate(pcdev->clk_csi_per, rate); 1541 if (err < 0) 1542 goto exit; 1543 } 1544 1545 INIT_LIST_HEAD(&pcdev->capture); 1546 INIT_LIST_HEAD(&pcdev->active_bufs); 1547 INIT_LIST_HEAD(&pcdev->discard); 1548 spin_lock_init(&pcdev->lock); 1549 1550 pcdev->base_csi = devm_ioremap_resource(&pdev->dev, res_csi); 1551 if (IS_ERR(pcdev->base_csi)) { 1552 err = PTR_ERR(pcdev->base_csi); 1553 goto exit; 1554 } 1555 1556 pcdev->dev = &pdev->dev; 1557 platform_set_drvdata(pdev, pcdev); 1558 1559 err = mx27_camera_emma_init(pdev); 1560 if (err) 1561 goto exit; 1562 1563 /* 1564 * We're done with drvdata here. Clear the pointer so that 1565 * v4l2 core can start using drvdata on its purpose. 1566 */ 1567 platform_set_drvdata(pdev, NULL); 1568 1569 pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, 1570 pcdev->soc_host.ops = &mx2_soc_camera_host_ops, 1571 pcdev->soc_host.priv = pcdev; 1572 pcdev->soc_host.v4l2_dev.dev = &pdev->dev; 1573 pcdev->soc_host.nr = pdev->id; 1574 1575 pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 1576 if (IS_ERR(pcdev->alloc_ctx)) { 1577 err = PTR_ERR(pcdev->alloc_ctx); 1578 goto eallocctx; 1579 } 1580 err = soc_camera_host_register(&pcdev->soc_host); 1581 if (err) 1582 goto exit_free_emma; 1583 1584 dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n", 1585 clk_get_rate(pcdev->clk_csi_per)); 1586 1587 return 0; 1588 1589exit_free_emma: 1590 vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); 1591eallocctx: 1592 clk_disable_unprepare(pcdev->clk_emma_ipg); 1593 clk_disable_unprepare(pcdev->clk_emma_ahb); 1594exit: 1595 return err; 1596} 1597 1598static int mx2_camera_remove(struct platform_device *pdev) 1599{ 1600 struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); 1601 struct mx2_camera_dev *pcdev = container_of(soc_host, 1602 struct mx2_camera_dev, soc_host); 1603 1604 soc_camera_host_unregister(&pcdev->soc_host); 1605 1606 vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); 1607 1608 clk_disable_unprepare(pcdev->clk_emma_ipg); 1609 clk_disable_unprepare(pcdev->clk_emma_ahb); 1610 1611 dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); 1612 1613 return 0; 1614} 1615 1616static struct platform_driver mx2_camera_driver = { 1617 .driver = { 1618 .name = MX2_CAM_DRV_NAME, 1619 }, 1620 .id_table = mx2_camera_devtype, 1621 .remove = mx2_camera_remove, 1622}; 1623 1624module_platform_driver_probe(mx2_camera_driver, mx2_camera_probe); 1625 1626MODULE_DESCRIPTION("i.MX27 SoC Camera Host driver"); 1627MODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>"); 1628MODULE_LICENSE("GPL"); 1629MODULE_VERSION(MX2_CAM_VERSION);