1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * TI OMAP4 ISS V4L2 Driver 4 * 5 * Copyright (C) 2012, Texas Instruments 6 * 7 * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/delay.h> 12 #include <linux/device.h> 13 #include <linux/dma-mapping.h> 14 #include <linux/i2c.h> 15 #include <linux/interrupt.h> 16 #include <linux/mfd/syscon.h> 17 #include <linux/module.h> 18 #include <linux/platform_device.h> 19 #include <linux/slab.h> 20 #include <linux/sched.h> 21 #include <linux/vmalloc.h> 22 23 #include <media/v4l2-common.h> 24 #include <media/v4l2-device.h> 25 #include <media/v4l2-ctrls.h> 26 27 #include "iss.h" 28 #include "iss_regs.h" 29 30 #define ISS_PRINT_REGISTER(iss, name)\ 31 dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \ 32 iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_##name)) 33 34 static void iss_print_status(struct iss_device *iss) 35 { 36 dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n"); 37 38 ISS_PRINT_REGISTER(iss, HL_REVISION); 39 ISS_PRINT_REGISTER(iss, HL_SYSCONFIG); 40 ISS_PRINT_REGISTER(iss, HL_IRQSTATUS(5)); 41 ISS_PRINT_REGISTER(iss, HL_IRQENABLE_SET(5)); 42 ISS_PRINT_REGISTER(iss, HL_IRQENABLE_CLR(5)); 43 ISS_PRINT_REGISTER(iss, CTRL); 44 ISS_PRINT_REGISTER(iss, CLKCTRL); 45 ISS_PRINT_REGISTER(iss, CLKSTAT); 46 47 dev_dbg(iss->dev, "-----------------------------------------------\n"); 48 } 49 50 /* 51 * omap4iss_flush - Post pending L3 bus writes by doing a register readback 52 * @iss: OMAP4 ISS device 53 * 54 * In order to force posting of pending writes, we need to write and 55 * readback the same register, in this case the revision register. 56 * 57 * See this link for reference: 58 * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html 59 */ 60 static void omap4iss_flush(struct iss_device *iss) 61 { 62 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION, 0); 63 iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); 64 } 65 66 /* 67 * iss_isp_enable_interrupts - Enable ISS ISP interrupts. 68 * @iss: OMAP4 ISS device 69 */ 70 static void omap4iss_isp_enable_interrupts(struct iss_device *iss) 71 { 72 static const u32 isp_irq = ISP5_IRQ_OCP_ERR | 73 ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | 74 ISP5_IRQ_RSZ_FIFO_OVF | 75 ISP5_IRQ_RSZ_INT_DMA | 76 ISP5_IRQ_ISIF_INT(0); 77 78 /* Enable ISP interrupts */ 79 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), isp_irq); 80 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_SET(0), 81 isp_irq); 82 } 83 84 /* 85 * iss_isp_disable_interrupts - Disable ISS interrupts. 86 * @iss: OMAP4 ISS device 87 */ 88 static void omap4iss_isp_disable_interrupts(struct iss_device *iss) 89 { 90 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQENABLE_CLR(0), ~0); 91 } 92 93 /* 94 * iss_enable_interrupts - Enable ISS interrupts. 95 * @iss: OMAP4 ISS device 96 */ 97 static void iss_enable_interrupts(struct iss_device *iss) 98 { 99 static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB 100 | ISS_HL_IRQ_ISP(0); 101 102 /* Enable HL interrupts */ 103 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), hl_irq); 104 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_SET(5), hl_irq); 105 106 if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) 107 omap4iss_isp_enable_interrupts(iss); 108 } 109 110 /* 111 * iss_disable_interrupts - Disable ISS interrupts. 112 * @iss: OMAP4 ISS device 113 */ 114 static void iss_disable_interrupts(struct iss_device *iss) 115 { 116 if (iss->regs[OMAP4_ISS_MEM_ISP_SYS1]) 117 omap4iss_isp_disable_interrupts(iss); 118 119 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQENABLE_CLR(5), ~0); 120 } 121 122 int omap4iss_get_external_info(struct iss_pipeline *pipe, 123 struct media_link *link) 124 { 125 struct iss_device *iss = 126 container_of(pipe, struct iss_video, pipe)->iss; 127 struct v4l2_subdev_format fmt; 128 struct v4l2_ctrl *ctrl; 129 int ret; 130 131 if (!pipe->external) 132 return 0; 133 134 if (pipe->external_rate) 135 return 0; 136 137 memset(&fmt, 0, sizeof(fmt)); 138 139 fmt.pad = link->source->index; 140 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; 141 ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity), 142 pad, get_fmt, NULL, &fmt); 143 if (ret < 0) 144 return -EPIPE; 145 146 pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; 147 148 ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler, 149 V4L2_CID_PIXEL_RATE); 150 if (!ctrl) { 151 dev_warn(iss->dev, "no pixel rate control in subdev %s\n", 152 pipe->external->name); 153 return -EPIPE; 154 } 155 156 pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); 157 158 return 0; 159 } 160 161 /* 162 * Configure the bridge. Valid inputs are 163 * 164 * IPIPEIF_INPUT_CSI2A: CSI2a receiver 165 * IPIPEIF_INPUT_CSI2B: CSI2b receiver 166 * 167 * The bridge and lane shifter are configured according to the selected input 168 * and the ISP platform data. 169 */ 170 void omap4iss_configure_bridge(struct iss_device *iss, 171 enum ipipeif_input_entity input) 172 { 173 u32 issctrl_val; 174 u32 isp5ctrl_val; 175 176 issctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL); 177 issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK; 178 issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK; 179 180 isp5ctrl_val = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL); 181 182 switch (input) { 183 case IPIPEIF_INPUT_CSI2A: 184 issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A; 185 break; 186 187 case IPIPEIF_INPUT_CSI2B: 188 issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B; 189 break; 190 191 default: 192 return; 193 } 194 195 issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING; 196 197 isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL | 198 ISP5_CTRL_SYNC_ENABLE; 199 200 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_CTRL, issctrl_val); 201 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, isp5ctrl_val); 202 } 203 204 #ifdef ISS_ISR_DEBUG 205 static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus) 206 { 207 static const char * const name[] = { 208 "ISP_0", 209 "ISP_1", 210 "ISP_2", 211 "ISP_3", 212 "CSIA", 213 "CSIB", 214 "CCP2_0", 215 "CCP2_1", 216 "CCP2_2", 217 "CCP2_3", 218 "CBUFF", 219 "BTE", 220 "SIMCOP_0", 221 "SIMCOP_1", 222 "SIMCOP_2", 223 "SIMCOP_3", 224 "CCP2_8", 225 "HS_VS", 226 "18", 227 "19", 228 "20", 229 "21", 230 "22", 231 "23", 232 "24", 233 "25", 234 "26", 235 "27", 236 "28", 237 "29", 238 "30", 239 "31", 240 }; 241 unsigned int i; 242 243 dev_dbg(iss->dev, "ISS IRQ: "); 244 245 for (i = 0; i < ARRAY_SIZE(name); i++) { 246 if ((1 << i) & irqstatus) 247 pr_cont("%s ", name[i]); 248 } 249 pr_cont("\n"); 250 } 251 252 static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus) 253 { 254 static const char * const name[] = { 255 "ISIF_0", 256 "ISIF_1", 257 "ISIF_2", 258 "ISIF_3", 259 "IPIPEREQ", 260 "IPIPELAST_PIX", 261 "IPIPEDMA", 262 "IPIPEBSC", 263 "IPIPEHST", 264 "IPIPEIF", 265 "AEW", 266 "AF", 267 "H3A", 268 "RSZ_REG", 269 "RSZ_LAST_PIX", 270 "RSZ_DMA", 271 "RSZ_CYC_RZA", 272 "RSZ_CYC_RZB", 273 "RSZ_FIFO_OVF", 274 "RSZ_FIFO_IN_BLK_ERR", 275 "20", 276 "21", 277 "RSZ_EOF0", 278 "RSZ_EOF1", 279 "H3A_EOF", 280 "IPIPE_EOF", 281 "26", 282 "IPIPE_DPC_INI", 283 "IPIPE_DPC_RNEW0", 284 "IPIPE_DPC_RNEW1", 285 "30", 286 "OCP_ERR", 287 }; 288 unsigned int i; 289 290 dev_dbg(iss->dev, "ISP IRQ: "); 291 292 for (i = 0; i < ARRAY_SIZE(name); i++) { 293 if ((1 << i) & irqstatus) 294 pr_cont("%s ", name[i]); 295 } 296 pr_cont("\n"); 297 } 298 #endif 299 300 /* 301 * iss_isr - Interrupt Service Routine for ISS module. 302 * @irq: Not used currently. 303 * @_iss: Pointer to the OMAP4 ISS device 304 * 305 * Handles the corresponding callback if plugged in. 306 * 307 * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the 308 * IRQ wasn't handled. 309 */ 310 static irqreturn_t iss_isr(int irq, void *_iss) 311 { 312 static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF_IRQ | 313 ISP5_IRQ_ISIF_INT(0); 314 static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK_ERR | 315 ISP5_IRQ_RSZ_FIFO_OVF | 316 ISP5_IRQ_RSZ_INT_DMA; 317 struct iss_device *iss = _iss; 318 u32 irqstatus; 319 320 irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5)); 321 iss_reg_write(iss, OMAP4_ISS_MEM_TOP, ISS_HL_IRQSTATUS(5), irqstatus); 322 323 if (irqstatus & ISS_HL_IRQ_CSIA) 324 omap4iss_csi2_isr(&iss->csi2a); 325 326 if (irqstatus & ISS_HL_IRQ_CSIB) 327 omap4iss_csi2_isr(&iss->csi2b); 328 329 if (irqstatus & ISS_HL_IRQ_ISP(0)) { 330 u32 isp_irqstatus = iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, 331 ISP5_IRQSTATUS(0)); 332 iss_reg_write(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_IRQSTATUS(0), 333 isp_irqstatus); 334 335 if (isp_irqstatus & ISP5_IRQ_OCP_ERR) 336 dev_dbg(iss->dev, "ISP5 OCP Error!\n"); 337 338 if (isp_irqstatus & ipipeif_events) { 339 omap4iss_ipipeif_isr(&iss->ipipeif, 340 isp_irqstatus & ipipeif_events); 341 } 342 343 if (isp_irqstatus & resizer_events) 344 omap4iss_resizer_isr(&iss->resizer, 345 isp_irqstatus & resizer_events); 346 347 #ifdef ISS_ISR_DEBUG 348 iss_isp_isr_dbg(iss, isp_irqstatus); 349 #endif 350 } 351 352 omap4iss_flush(iss); 353 354 #ifdef ISS_ISR_DEBUG 355 iss_isr_dbg(iss, irqstatus); 356 #endif 357 358 return IRQ_HANDLED; 359 } 360 361 static const struct media_device_ops iss_media_ops = { 362 .link_notify = v4l2_pipeline_link_notify, 363 }; 364 365 /* ----------------------------------------------------------------------------- 366 * Pipeline stream management 367 */ 368 369 /* 370 * iss_pipeline_disable - Disable streaming on a pipeline 371 * @pipe: ISS pipeline 372 * @until: entity at which to stop pipeline walk 373 * 374 * Walk the entities chain starting at the pipeline output video node and stop 375 * all modules in the chain. Wait synchronously for the modules to be stopped if 376 * necessary. 377 * 378 * If the until argument isn't NULL, stop the pipeline walk when reaching the 379 * until entity. This is used to disable a partially started pipeline due to a 380 * subdev start error. 381 */ 382 static int iss_pipeline_disable(struct iss_pipeline *pipe, 383 struct media_entity *until) 384 { 385 struct iss_device *iss = pipe->output->iss; 386 struct media_entity *entity; 387 struct media_pad *pad; 388 struct v4l2_subdev *subdev; 389 int failure = 0; 390 int ret; 391 392 entity = &pipe->output->video.entity; 393 while (1) { 394 pad = &entity->pads[0]; 395 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 396 break; 397 398 pad = media_entity_remote_pad(pad); 399 if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 400 break; 401 402 entity = pad->entity; 403 if (entity == until) 404 break; 405 406 subdev = media_entity_to_v4l2_subdev(entity); 407 ret = v4l2_subdev_call(subdev, video, s_stream, 0); 408 if (ret < 0) { 409 dev_warn(iss->dev, "%s: module stop timeout.\n", 410 subdev->name); 411 /* If the entity failed to stopped, assume it has 412 * crashed. Mark it as such, the ISS will be reset when 413 * applications will release it. 414 */ 415 media_entity_enum_set(&iss->crashed, &subdev->entity); 416 failure = -ETIMEDOUT; 417 } 418 } 419 420 return failure; 421 } 422 423 /* 424 * iss_pipeline_enable - Enable streaming on a pipeline 425 * @pipe: ISS pipeline 426 * @mode: Stream mode (single shot or continuous) 427 * 428 * Walk the entities chain starting at the pipeline output video node and start 429 * all modules in the chain in the given mode. 430 * 431 * Return 0 if successful, or the return value of the failed video::s_stream 432 * operation otherwise. 433 */ 434 static int iss_pipeline_enable(struct iss_pipeline *pipe, 435 enum iss_pipeline_stream_state mode) 436 { 437 struct iss_device *iss = pipe->output->iss; 438 struct media_entity *entity; 439 struct media_pad *pad; 440 struct v4l2_subdev *subdev; 441 unsigned long flags; 442 int ret; 443 444 /* If one of the entities in the pipeline has crashed it will not work 445 * properly. Refuse to start streaming in that case. This check must be 446 * performed before the loop below to avoid starting entities if the 447 * pipeline won't start anyway (those entities would then likely fail to 448 * stop, making the problem worse). 449 */ 450 if (media_entity_enum_intersects(&pipe->ent_enum, &iss->crashed)) 451 return -EIO; 452 453 spin_lock_irqsave(&pipe->lock, flags); 454 pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT); 455 spin_unlock_irqrestore(&pipe->lock, flags); 456 457 pipe->do_propagation = false; 458 459 entity = &pipe->output->video.entity; 460 while (1) { 461 pad = &entity->pads[0]; 462 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 463 break; 464 465 pad = media_entity_remote_pad(pad); 466 if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) 467 break; 468 469 entity = pad->entity; 470 subdev = media_entity_to_v4l2_subdev(entity); 471 472 ret = v4l2_subdev_call(subdev, video, s_stream, mode); 473 if (ret < 0 && ret != -ENOIOCTLCMD) { 474 iss_pipeline_disable(pipe, entity); 475 return ret; 476 } 477 478 if (subdev == &iss->csi2a.subdev || 479 subdev == &iss->csi2b.subdev) 480 pipe->do_propagation = true; 481 } 482 483 iss_print_status(pipe->output->iss); 484 return 0; 485 } 486 487 /* 488 * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline 489 * @pipe: ISS pipeline 490 * @state: Stream state (stopped, single shot or continuous) 491 * 492 * Set the pipeline to the given stream state. Pipelines can be started in 493 * single-shot or continuous mode. 494 * 495 * Return 0 if successful, or the return value of the failed video::s_stream 496 * operation otherwise. The pipeline state is not updated when the operation 497 * fails, except when stopping the pipeline. 498 */ 499 int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe, 500 enum iss_pipeline_stream_state state) 501 { 502 int ret; 503 504 if (state == ISS_PIPELINE_STREAM_STOPPED) 505 ret = iss_pipeline_disable(pipe, NULL); 506 else 507 ret = iss_pipeline_enable(pipe, state); 508 509 if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED) 510 pipe->stream_state = state; 511 512 return ret; 513 } 514 515 /* 516 * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline 517 * @pipe: ISS pipeline 518 * 519 * Cancelling a stream mark all buffers on all video nodes in the pipeline as 520 * erroneous and makes sure no new buffer can be queued. This function is called 521 * when a fatal error that prevents any further operation on the pipeline 522 * occurs. 523 */ 524 void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe) 525 { 526 if (pipe->input) 527 omap4iss_video_cancel_stream(pipe->input); 528 if (pipe->output) 529 omap4iss_video_cancel_stream(pipe->output); 530 } 531 532 /* 533 * iss_pipeline_is_last - Verify if entity has an enabled link to the output 534 * video node 535 * @me: ISS module's media entity 536 * 537 * Returns 1 if the entity has an enabled link to the output video node or 0 538 * otherwise. It's true only while pipeline can have no more than one output 539 * node. 540 */ 541 static int iss_pipeline_is_last(struct media_entity *me) 542 { 543 struct iss_pipeline *pipe; 544 struct media_pad *pad; 545 546 if (!me->pipe) 547 return 0; 548 pipe = to_iss_pipeline(me); 549 if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED) 550 return 0; 551 pad = media_entity_remote_pad(&pipe->output->pad); 552 return pad->entity == me; 553 } 554 555 static int iss_reset(struct iss_device *iss) 556 { 557 unsigned int timeout; 558 559 iss_reg_set(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG, 560 ISS_HL_SYSCONFIG_SOFTRESET); 561 562 timeout = iss_poll_condition_timeout( 563 !(iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_SYSCONFIG) & 564 ISS_HL_SYSCONFIG_SOFTRESET), 1000, 10, 100); 565 if (timeout) { 566 dev_err(iss->dev, "ISS reset timeout\n"); 567 return -ETIMEDOUT; 568 } 569 570 media_entity_enum_zero(&iss->crashed); 571 572 return 0; 573 } 574 575 static int iss_isp_reset(struct iss_device *iss) 576 { 577 unsigned int timeout; 578 579 /* Fist, ensure that the ISP is IDLE (no transactions happening) */ 580 iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, 581 ISP5_SYSCONFIG_STANDBYMODE_MASK, 582 ISP5_SYSCONFIG_STANDBYMODE_SMART); 583 584 iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, ISP5_CTRL_MSTANDBY); 585 586 timeout = iss_poll_condition_timeout( 587 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL) & 588 ISP5_CTRL_MSTANDBY_WAIT, 1000000, 1000, 1500); 589 if (timeout) { 590 dev_err(iss->dev, "ISP5 standby timeout\n"); 591 return -ETIMEDOUT; 592 } 593 594 /* Now finally, do the reset */ 595 iss_reg_set(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG, 596 ISP5_SYSCONFIG_SOFTRESET); 597 598 timeout = iss_poll_condition_timeout( 599 !(iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_SYSCONFIG) & 600 ISP5_SYSCONFIG_SOFTRESET), 1000000, 1000, 1500); 601 if (timeout) { 602 dev_err(iss->dev, "ISP5 reset timeout\n"); 603 return -ETIMEDOUT; 604 } 605 606 return 0; 607 } 608 609 /* 610 * iss_module_sync_idle - Helper to sync module with its idle state 611 * @me: ISS submodule's media entity 612 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization 613 * @stopping: flag which tells module wants to stop 614 * 615 * This function checks if ISS submodule needs to wait for next interrupt. If 616 * yes, makes the caller to sleep while waiting for such event. 617 */ 618 int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait, 619 atomic_t *stopping) 620 { 621 struct iss_pipeline *pipe = to_iss_pipeline(me); 622 struct iss_video *video = pipe->output; 623 unsigned long flags; 624 625 if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED || 626 (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT && 627 !iss_pipeline_ready(pipe))) 628 return 0; 629 630 /* 631 * atomic_set() doesn't include memory barrier on ARM platform for SMP 632 * scenario. We'll call it here to avoid race conditions. 633 */ 634 atomic_set(stopping, 1); 635 smp_wmb(); 636 637 /* 638 * If module is the last one, it's writing to memory. In this case, 639 * it's necessary to check if the module is already paused due to 640 * DMA queue underrun or if it has to wait for next interrupt to be 641 * idle. 642 * If it isn't the last one, the function won't sleep but *stopping 643 * will still be set to warn next submodule caller's interrupt the 644 * module wants to be idle. 645 */ 646 if (!iss_pipeline_is_last(me)) 647 return 0; 648 649 spin_lock_irqsave(&video->qlock, flags); 650 if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) { 651 spin_unlock_irqrestore(&video->qlock, flags); 652 atomic_set(stopping, 0); 653 smp_wmb(); 654 return 0; 655 } 656 spin_unlock_irqrestore(&video->qlock, flags); 657 if (!wait_event_timeout(*wait, !atomic_read(stopping), 658 msecs_to_jiffies(1000))) { 659 atomic_set(stopping, 0); 660 smp_wmb(); 661 return -ETIMEDOUT; 662 } 663 664 return 0; 665 } 666 667 /* 668 * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping 669 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization 670 * @stopping: flag which tells module wants to stop 671 * 672 * This function checks if ISS submodule was stopping. In case of yes, it 673 * notices the caller by setting stopping to 0 and waking up the wait queue. 674 * Returns 1 if it was stopping or 0 otherwise. 675 */ 676 int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait, 677 atomic_t *stopping) 678 { 679 if (atomic_cmpxchg(stopping, 1, 0)) { 680 wake_up(wait); 681 return 1; 682 } 683 684 return 0; 685 } 686 687 /* -------------------------------------------------------------------------- 688 * Clock management 689 */ 690 691 #define ISS_CLKCTRL_MASK (ISS_CLKCTRL_CSI2_A |\ 692 ISS_CLKCTRL_CSI2_B |\ 693 ISS_CLKCTRL_ISP) 694 695 static int __iss_subclk_update(struct iss_device *iss) 696 { 697 u32 clk = 0; 698 int ret = 0, timeout = 1000; 699 700 if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A) 701 clk |= ISS_CLKCTRL_CSI2_A; 702 703 if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B) 704 clk |= ISS_CLKCTRL_CSI2_B; 705 706 if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP) 707 clk |= ISS_CLKCTRL_ISP; 708 709 iss_reg_update(iss, OMAP4_ISS_MEM_TOP, ISS_CLKCTRL, 710 ISS_CLKCTRL_MASK, clk); 711 712 /* Wait for HW assertion */ 713 while (--timeout > 0) { 714 udelay(1); 715 if ((iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_CLKSTAT) & 716 ISS_CLKCTRL_MASK) == clk) 717 break; 718 } 719 720 if (!timeout) 721 ret = -EBUSY; 722 723 return ret; 724 } 725 726 int omap4iss_subclk_enable(struct iss_device *iss, 727 enum iss_subclk_resource res) 728 { 729 iss->subclk_resources |= res; 730 731 return __iss_subclk_update(iss); 732 } 733 734 int omap4iss_subclk_disable(struct iss_device *iss, 735 enum iss_subclk_resource res) 736 { 737 iss->subclk_resources &= ~res; 738 739 return __iss_subclk_update(iss); 740 } 741 742 #define ISS_ISP5_CLKCTRL_MASK (ISP5_CTRL_BL_CLK_ENABLE |\ 743 ISP5_CTRL_ISIF_CLK_ENABLE |\ 744 ISP5_CTRL_H3A_CLK_ENABLE |\ 745 ISP5_CTRL_RSZ_CLK_ENABLE |\ 746 ISP5_CTRL_IPIPE_CLK_ENABLE |\ 747 ISP5_CTRL_IPIPEIF_CLK_ENABLE) 748 749 static void __iss_isp_subclk_update(struct iss_device *iss) 750 { 751 u32 clk = 0; 752 753 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF) 754 clk |= ISP5_CTRL_ISIF_CLK_ENABLE; 755 756 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A) 757 clk |= ISP5_CTRL_H3A_CLK_ENABLE; 758 759 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ) 760 clk |= ISP5_CTRL_RSZ_CLK_ENABLE; 761 762 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE) 763 clk |= ISP5_CTRL_IPIPE_CLK_ENABLE; 764 765 if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF) 766 clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE; 767 768 if (clk) 769 clk |= ISP5_CTRL_BL_CLK_ENABLE; 770 771 iss_reg_update(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_CTRL, 772 ISS_ISP5_CLKCTRL_MASK, clk); 773 } 774 775 void omap4iss_isp_subclk_enable(struct iss_device *iss, 776 enum iss_isp_subclk_resource res) 777 { 778 iss->isp_subclk_resources |= res; 779 780 __iss_isp_subclk_update(iss); 781 } 782 783 void omap4iss_isp_subclk_disable(struct iss_device *iss, 784 enum iss_isp_subclk_resource res) 785 { 786 iss->isp_subclk_resources &= ~res; 787 788 __iss_isp_subclk_update(iss); 789 } 790 791 /* 792 * iss_enable_clocks - Enable ISS clocks 793 * @iss: OMAP4 ISS device 794 * 795 * Return 0 if successful, or clk_enable return value if any of tthem fails. 796 */ 797 static int iss_enable_clocks(struct iss_device *iss) 798 { 799 int ret; 800 801 ret = clk_enable(iss->iss_fck); 802 if (ret) { 803 dev_err(iss->dev, "clk_enable iss_fck failed\n"); 804 return ret; 805 } 806 807 ret = clk_enable(iss->iss_ctrlclk); 808 if (ret) { 809 dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n"); 810 clk_disable(iss->iss_fck); 811 return ret; 812 } 813 814 return 0; 815 } 816 817 /* 818 * iss_disable_clocks - Disable ISS clocks 819 * @iss: OMAP4 ISS device 820 */ 821 static void iss_disable_clocks(struct iss_device *iss) 822 { 823 clk_disable(iss->iss_ctrlclk); 824 clk_disable(iss->iss_fck); 825 } 826 827 static int iss_get_clocks(struct iss_device *iss) 828 { 829 iss->iss_fck = devm_clk_get(iss->dev, "iss_fck"); 830 if (IS_ERR(iss->iss_fck)) { 831 dev_err(iss->dev, "Unable to get iss_fck clock info\n"); 832 return PTR_ERR(iss->iss_fck); 833 } 834 835 iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk"); 836 if (IS_ERR(iss->iss_ctrlclk)) { 837 dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n"); 838 return PTR_ERR(iss->iss_ctrlclk); 839 } 840 841 return 0; 842 } 843 844 /* 845 * omap4iss_get - Acquire the ISS resource. 846 * 847 * Initializes the clocks for the first acquire. 848 * 849 * Increment the reference count on the ISS. If the first reference is taken, 850 * enable clocks and power-up all submodules. 851 * 852 * Return a pointer to the ISS device structure, or NULL if an error occurred. 853 */ 854 struct iss_device *omap4iss_get(struct iss_device *iss) 855 { 856 struct iss_device *__iss = iss; 857 858 if (!iss) 859 return NULL; 860 861 mutex_lock(&iss->iss_mutex); 862 if (iss->ref_count > 0) 863 goto out; 864 865 if (iss_enable_clocks(iss) < 0) { 866 __iss = NULL; 867 goto out; 868 } 869 870 iss_enable_interrupts(iss); 871 872 out: 873 if (__iss) 874 iss->ref_count++; 875 mutex_unlock(&iss->iss_mutex); 876 877 return __iss; 878 } 879 880 /* 881 * omap4iss_put - Release the ISS 882 * 883 * Decrement the reference count on the ISS. If the last reference is released, 884 * power-down all submodules, disable clocks and free temporary buffers. 885 */ 886 void omap4iss_put(struct iss_device *iss) 887 { 888 if (!iss) 889 return; 890 891 mutex_lock(&iss->iss_mutex); 892 WARN_ON(iss->ref_count == 0); 893 if (--iss->ref_count == 0) { 894 iss_disable_interrupts(iss); 895 /* Reset the ISS if an entity has failed to stop. This is the 896 * only way to recover from such conditions, although it would 897 * be worth investigating whether resetting the ISP only can't 898 * fix the problem in some cases. 899 */ 900 if (!media_entity_enum_empty(&iss->crashed)) 901 iss_reset(iss); 902 iss_disable_clocks(iss); 903 } 904 mutex_unlock(&iss->iss_mutex); 905 } 906 907 static int iss_map_mem_resource(struct platform_device *pdev, 908 struct iss_device *iss, 909 enum iss_mem_resources res) 910 { 911 iss->regs[res] = devm_platform_ioremap_resource(pdev, res); 912 913 return PTR_ERR_OR_ZERO(iss->regs[res]); 914 } 915 916 static void iss_unregister_entities(struct iss_device *iss) 917 { 918 omap4iss_resizer_unregister_entities(&iss->resizer); 919 omap4iss_ipipe_unregister_entities(&iss->ipipe); 920 omap4iss_ipipeif_unregister_entities(&iss->ipipeif); 921 omap4iss_csi2_unregister_entities(&iss->csi2a); 922 omap4iss_csi2_unregister_entities(&iss->csi2b); 923 924 v4l2_device_unregister(&iss->v4l2_dev); 925 media_device_unregister(&iss->media_dev); 926 } 927 928 /* 929 * iss_register_subdev_group - Register a group of subdevices 930 * @iss: OMAP4 ISS device 931 * @board_info: I2C subdevs board information array 932 * 933 * Register all I2C subdevices in the board_info array. The array must be 934 * terminated by a NULL entry, and the first entry must be the sensor. 935 * 936 * Return a pointer to the sensor media entity if it has been successfully 937 * registered, or NULL otherwise. 938 */ 939 static struct v4l2_subdev * 940 iss_register_subdev_group(struct iss_device *iss, 941 struct iss_subdev_i2c_board_info *board_info) 942 { 943 struct v4l2_subdev *sensor = NULL; 944 unsigned int first; 945 946 if (!board_info->board_info) 947 return NULL; 948 949 for (first = 1; board_info->board_info; ++board_info, first = 0) { 950 struct v4l2_subdev *subdev; 951 struct i2c_adapter *adapter; 952 953 adapter = i2c_get_adapter(board_info->i2c_adapter_id); 954 if (!adapter) { 955 dev_err(iss->dev, 956 "%s: Unable to get I2C adapter %d for device %s\n", 957 __func__, board_info->i2c_adapter_id, 958 board_info->board_info->type); 959 continue; 960 } 961 962 subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter, 963 board_info->board_info, NULL); 964 if (!subdev) { 965 dev_err(iss->dev, "Unable to register subdev %s\n", 966 board_info->board_info->type); 967 continue; 968 } 969 970 if (first) 971 sensor = subdev; 972 } 973 974 return sensor; 975 } 976 977 static int iss_register_entities(struct iss_device *iss) 978 { 979 struct iss_platform_data *pdata = iss->pdata; 980 struct iss_v4l2_subdevs_group *subdevs; 981 int ret; 982 983 iss->media_dev.dev = iss->dev; 984 strscpy(iss->media_dev.model, "TI OMAP4 ISS", 985 sizeof(iss->media_dev.model)); 986 iss->media_dev.hw_revision = iss->revision; 987 iss->media_dev.ops = &iss_media_ops; 988 ret = media_device_register(&iss->media_dev); 989 if (ret < 0) { 990 dev_err(iss->dev, "Media device registration failed (%d)\n", 991 ret); 992 return ret; 993 } 994 995 iss->v4l2_dev.mdev = &iss->media_dev; 996 ret = v4l2_device_register(iss->dev, &iss->v4l2_dev); 997 if (ret < 0) { 998 dev_err(iss->dev, "V4L2 device registration failed (%d)\n", 999 ret); 1000 goto done; 1001 } 1002 1003 /* Register internal entities */ 1004 ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev); 1005 if (ret < 0) 1006 goto done; 1007 1008 ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev); 1009 if (ret < 0) 1010 goto done; 1011 1012 ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev); 1013 if (ret < 0) 1014 goto done; 1015 1016 ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev); 1017 if (ret < 0) 1018 goto done; 1019 1020 ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev); 1021 if (ret < 0) 1022 goto done; 1023 1024 /* Register external entities */ 1025 for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { 1026 struct v4l2_subdev *sensor; 1027 struct media_entity *input; 1028 unsigned int flags; 1029 unsigned int pad; 1030 1031 sensor = iss_register_subdev_group(iss, subdevs->subdevs); 1032 if (!sensor) 1033 continue; 1034 1035 sensor->host_priv = subdevs; 1036 1037 /* Connect the sensor to the correct interface module. 1038 * CSI2a receiver through CSIPHY1, or 1039 * CSI2b receiver through CSIPHY2 1040 */ 1041 switch (subdevs->interface) { 1042 case ISS_INTERFACE_CSI2A_PHY1: 1043 input = &iss->csi2a.subdev.entity; 1044 pad = CSI2_PAD_SINK; 1045 flags = MEDIA_LNK_FL_IMMUTABLE 1046 | MEDIA_LNK_FL_ENABLED; 1047 break; 1048 1049 case ISS_INTERFACE_CSI2B_PHY2: 1050 input = &iss->csi2b.subdev.entity; 1051 pad = CSI2_PAD_SINK; 1052 flags = MEDIA_LNK_FL_IMMUTABLE 1053 | MEDIA_LNK_FL_ENABLED; 1054 break; 1055 1056 default: 1057 dev_err(iss->dev, "invalid interface type %u\n", 1058 subdevs->interface); 1059 ret = -EINVAL; 1060 goto done; 1061 } 1062 1063 ret = media_create_pad_link(&sensor->entity, 0, input, pad, 1064 flags); 1065 if (ret < 0) 1066 goto done; 1067 } 1068 1069 ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev); 1070 1071 done: 1072 if (ret < 0) 1073 iss_unregister_entities(iss); 1074 1075 return ret; 1076 } 1077 1078 /* 1079 * iss_create_links() - Pads links creation for the subdevices 1080 * @iss : Pointer to ISS device 1081 * 1082 * return negative error code or zero on success 1083 */ 1084 static int iss_create_links(struct iss_device *iss) 1085 { 1086 int ret; 1087 1088 ret = omap4iss_csi2_create_links(iss); 1089 if (ret < 0) { 1090 dev_err(iss->dev, "CSI2 pads links creation failed\n"); 1091 return ret; 1092 } 1093 1094 ret = omap4iss_ipipeif_create_links(iss); 1095 if (ret < 0) { 1096 dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n"); 1097 return ret; 1098 } 1099 1100 ret = omap4iss_resizer_create_links(iss); 1101 if (ret < 0) { 1102 dev_err(iss->dev, "ISP RESIZER pads links creation failed\n"); 1103 return ret; 1104 } 1105 1106 /* Connect the submodules. */ 1107 ret = media_create_pad_link( 1108 &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE, 1109 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); 1110 if (ret < 0) 1111 return ret; 1112 1113 ret = media_create_pad_link( 1114 &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE, 1115 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0); 1116 if (ret < 0) 1117 return ret; 1118 1119 ret = media_create_pad_link( 1120 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, 1121 &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); 1122 if (ret < 0) 1123 return ret; 1124 1125 ret = media_create_pad_link( 1126 &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP, 1127 &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0); 1128 if (ret < 0) 1129 return ret; 1130 1131 ret = media_create_pad_link( 1132 &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP, 1133 &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0); 1134 if (ret < 0) 1135 return ret; 1136 1137 return 0; 1138 }; 1139 1140 static void iss_cleanup_modules(struct iss_device *iss) 1141 { 1142 omap4iss_csi2_cleanup(iss); 1143 omap4iss_ipipeif_cleanup(iss); 1144 omap4iss_ipipe_cleanup(iss); 1145 omap4iss_resizer_cleanup(iss); 1146 } 1147 1148 static int iss_initialize_modules(struct iss_device *iss) 1149 { 1150 int ret; 1151 1152 ret = omap4iss_csiphy_init(iss); 1153 if (ret < 0) { 1154 dev_err(iss->dev, "CSI PHY initialization failed\n"); 1155 goto error_csiphy; 1156 } 1157 1158 ret = omap4iss_csi2_init(iss); 1159 if (ret < 0) { 1160 dev_err(iss->dev, "CSI2 initialization failed\n"); 1161 goto error_csi2; 1162 } 1163 1164 ret = omap4iss_ipipeif_init(iss); 1165 if (ret < 0) { 1166 dev_err(iss->dev, "ISP IPIPEIF initialization failed\n"); 1167 goto error_ipipeif; 1168 } 1169 1170 ret = omap4iss_ipipe_init(iss); 1171 if (ret < 0) { 1172 dev_err(iss->dev, "ISP IPIPE initialization failed\n"); 1173 goto error_ipipe; 1174 } 1175 1176 ret = omap4iss_resizer_init(iss); 1177 if (ret < 0) { 1178 dev_err(iss->dev, "ISP RESIZER initialization failed\n"); 1179 goto error_resizer; 1180 } 1181 1182 return 0; 1183 1184 error_resizer: 1185 omap4iss_ipipe_cleanup(iss); 1186 error_ipipe: 1187 omap4iss_ipipeif_cleanup(iss); 1188 error_ipipeif: 1189 omap4iss_csi2_cleanup(iss); 1190 error_csi2: 1191 error_csiphy: 1192 return ret; 1193 } 1194 1195 static int iss_probe(struct platform_device *pdev) 1196 { 1197 struct iss_platform_data *pdata = pdev->dev.platform_data; 1198 struct iss_device *iss; 1199 unsigned int i; 1200 int ret; 1201 1202 if (!pdata) 1203 return -EINVAL; 1204 1205 iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL); 1206 if (!iss) 1207 return -ENOMEM; 1208 1209 mutex_init(&iss->iss_mutex); 1210 1211 iss->dev = &pdev->dev; 1212 iss->pdata = pdata; 1213 1214 iss->raw_dmamask = DMA_BIT_MASK(32); 1215 iss->dev->dma_mask = &iss->raw_dmamask; 1216 iss->dev->coherent_dma_mask = DMA_BIT_MASK(32); 1217 1218 platform_set_drvdata(pdev, iss); 1219 1220 /* 1221 * TODO: When implementing DT support switch to syscon regmap lookup by 1222 * phandle. 1223 */ 1224 iss->syscon = syscon_regmap_lookup_by_compatible("syscon"); 1225 if (IS_ERR(iss->syscon)) { 1226 ret = PTR_ERR(iss->syscon); 1227 goto error; 1228 } 1229 1230 /* Clocks */ 1231 ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP); 1232 if (ret < 0) 1233 goto error; 1234 1235 ret = iss_get_clocks(iss); 1236 if (ret < 0) 1237 goto error; 1238 1239 if (!omap4iss_get(iss)) 1240 goto error; 1241 1242 ret = iss_reset(iss); 1243 if (ret < 0) 1244 goto error_iss; 1245 1246 iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION); 1247 dev_info(iss->dev, "Revision %08x found\n", iss->revision); 1248 1249 for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) { 1250 ret = iss_map_mem_resource(pdev, iss, i); 1251 if (ret) 1252 goto error_iss; 1253 } 1254 1255 /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */ 1256 iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL, 1257 BTE_CTRL_BW_LIMITER_MASK, 1258 18 << BTE_CTRL_BW_LIMITER_SHIFT); 1259 1260 /* Perform ISP reset */ 1261 ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP); 1262 if (ret < 0) 1263 goto error_iss; 1264 1265 ret = iss_isp_reset(iss); 1266 if (ret < 0) 1267 goto error_iss; 1268 1269 dev_info(iss->dev, "ISP Revision %08x found\n", 1270 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION)); 1271 1272 /* Interrupt */ 1273 ret = platform_get_irq(pdev, 0); 1274 if (ret <= 0) { 1275 ret = -ENODEV; 1276 goto error_iss; 1277 } 1278 iss->irq_num = ret; 1279 1280 if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED, 1281 "OMAP4 ISS", iss)) { 1282 dev_err(iss->dev, "Unable to request IRQ\n"); 1283 ret = -EINVAL; 1284 goto error_iss; 1285 } 1286 1287 /* Entities */ 1288 ret = iss_initialize_modules(iss); 1289 if (ret < 0) 1290 goto error_iss; 1291 1292 ret = iss_register_entities(iss); 1293 if (ret < 0) 1294 goto error_modules; 1295 1296 ret = media_entity_enum_init(&iss->crashed, &iss->media_dev); 1297 if (ret) 1298 goto error_entities; 1299 1300 ret = iss_create_links(iss); 1301 if (ret < 0) 1302 goto error_entities; 1303 1304 omap4iss_put(iss); 1305 1306 return 0; 1307 1308 error_entities: 1309 iss_unregister_entities(iss); 1310 media_entity_enum_cleanup(&iss->crashed); 1311 error_modules: 1312 iss_cleanup_modules(iss); 1313 error_iss: 1314 omap4iss_put(iss); 1315 error: 1316 mutex_destroy(&iss->iss_mutex); 1317 1318 return ret; 1319 } 1320 1321 static int iss_remove(struct platform_device *pdev) 1322 { 1323 struct iss_device *iss = platform_get_drvdata(pdev); 1324 1325 iss_unregister_entities(iss); 1326 media_entity_enum_cleanup(&iss->crashed); 1327 iss_cleanup_modules(iss); 1328 1329 return 0; 1330 } 1331 1332 static const struct platform_device_id omap4iss_id_table[] = { 1333 { "omap4iss", 0 }, 1334 { }, 1335 }; 1336 MODULE_DEVICE_TABLE(platform, omap4iss_id_table); 1337 1338 static struct platform_driver iss_driver = { 1339 .probe = iss_probe, 1340 .remove = iss_remove, 1341 .id_table = omap4iss_id_table, 1342 .driver = { 1343 .name = "omap4iss", 1344 }, 1345 }; 1346 1347 module_platform_driver(iss_driver); 1348 1349 MODULE_DESCRIPTION("TI OMAP4 ISS driver"); 1350 MODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>"); 1351 MODULE_LICENSE("GPL"); 1352 MODULE_VERSION(ISS_VIDEO_DRIVER_VERSION); 1353