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