This source file includes following definitions.
- iss_print_status
 
- omap4iss_flush
 
- omap4iss_isp_enable_interrupts
 
- omap4iss_isp_disable_interrupts
 
- iss_enable_interrupts
 
- iss_disable_interrupts
 
- omap4iss_get_external_info
 
- omap4iss_configure_bridge
 
- iss_isr_dbg
 
- iss_isp_isr_dbg
 
- iss_isr
 
- iss_pipeline_disable
 
- iss_pipeline_enable
 
- omap4iss_pipeline_set_stream
 
- omap4iss_pipeline_cancel_stream
 
- iss_pipeline_is_last
 
- iss_reset
 
- iss_isp_reset
 
- omap4iss_module_sync_idle
 
- omap4iss_module_sync_is_stopping
 
- __iss_subclk_update
 
- omap4iss_subclk_enable
 
- omap4iss_subclk_disable
 
- __iss_isp_subclk_update
 
- omap4iss_isp_subclk_enable
 
- omap4iss_isp_subclk_disable
 
- iss_enable_clocks
 
- iss_disable_clocks
 
- iss_get_clocks
 
- omap4iss_get
 
- omap4iss_put
 
- iss_map_mem_resource
 
- iss_unregister_entities
 
- iss_register_subdev_group
 
- iss_register_entities
 
- iss_create_links
 
- iss_cleanup_modules
 
- iss_initialize_modules
 
- iss_probe
 
- iss_remove
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   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 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  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 
  68 
  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         
  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 
  86 
  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 
  95 
  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         
 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 
 112 
 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 
 163 
 164 
 165 
 166 
 167 
 168 
 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 
 302 
 303 
 304 
 305 
 306 
 307 
 308 
 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 
 367 
 368 
 369 
 370 
 371 
 372 
 373 
 374 
 375 
 376 
 377 
 378 
 379 
 380 
 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                         
 412 
 413 
 414 
 415                         media_entity_enum_set(&iss->crashed, &subdev->entity);
 416                         failure = -ETIMEDOUT;
 417                 }
 418         }
 419 
 420         return failure;
 421 }
 422 
 423 
 424 
 425 
 426 
 427 
 428 
 429 
 430 
 431 
 432 
 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         
 445 
 446 
 447 
 448 
 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 
 489 
 490 
 491 
 492 
 493 
 494 
 495 
 496 
 497 
 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 
 517 
 518 
 519 
 520 
 521 
 522 
 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 
 534 
 535 
 536 
 537 
 538 
 539 
 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         
 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         
 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 
 611 
 612 
 613 
 614 
 615 
 616 
 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 
 632 
 633 
 634         atomic_set(stopping, 1);
 635         smp_wmb();
 636 
 637         
 638 
 639 
 640 
 641 
 642 
 643 
 644 
 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 
 669 
 670 
 671 
 672 
 673 
 674 
 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 
 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         
 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 
 793 
 794 
 795 
 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 
 819 
 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 
 846 
 847 
 848 
 849 
 850 
 851 
 852 
 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 
 882 
 883 
 884 
 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                 
 896 
 897 
 898 
 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         struct resource *mem;
 912 
 913         mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
 914 
 915         iss->regs[res] = devm_ioremap_resource(iss->dev, mem);
 916 
 917         return PTR_ERR_OR_ZERO(iss->regs[res]);
 918 }
 919 
 920 static void iss_unregister_entities(struct iss_device *iss)
 921 {
 922         omap4iss_resizer_unregister_entities(&iss->resizer);
 923         omap4iss_ipipe_unregister_entities(&iss->ipipe);
 924         omap4iss_ipipeif_unregister_entities(&iss->ipipeif);
 925         omap4iss_csi2_unregister_entities(&iss->csi2a);
 926         omap4iss_csi2_unregister_entities(&iss->csi2b);
 927 
 928         v4l2_device_unregister(&iss->v4l2_dev);
 929         media_device_unregister(&iss->media_dev);
 930 }
 931 
 932 
 933 
 934 
 935 
 936 
 937 
 938 
 939 
 940 
 941 
 942 
 943 static struct v4l2_subdev *
 944 iss_register_subdev_group(struct iss_device *iss,
 945                           struct iss_subdev_i2c_board_info *board_info)
 946 {
 947         struct v4l2_subdev *sensor = NULL;
 948         unsigned int first;
 949 
 950         if (!board_info->board_info)
 951                 return NULL;
 952 
 953         for (first = 1; board_info->board_info; ++board_info, first = 0) {
 954                 struct v4l2_subdev *subdev;
 955                 struct i2c_adapter *adapter;
 956 
 957                 adapter = i2c_get_adapter(board_info->i2c_adapter_id);
 958                 if (!adapter) {
 959                         dev_err(iss->dev,
 960                                 "%s: Unable to get I2C adapter %d for device %s\n",
 961                                 __func__, board_info->i2c_adapter_id,
 962                                 board_info->board_info->type);
 963                         continue;
 964                 }
 965 
 966                 subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
 967                                 board_info->board_info, NULL);
 968                 if (!subdev) {
 969                         dev_err(iss->dev, "Unable to register subdev %s\n",
 970                                 board_info->board_info->type);
 971                         continue;
 972                 }
 973 
 974                 if (first)
 975                         sensor = subdev;
 976         }
 977 
 978         return sensor;
 979 }
 980 
 981 static int iss_register_entities(struct iss_device *iss)
 982 {
 983         struct iss_platform_data *pdata = iss->pdata;
 984         struct iss_v4l2_subdevs_group *subdevs;
 985         int ret;
 986 
 987         iss->media_dev.dev = iss->dev;
 988         strscpy(iss->media_dev.model, "TI OMAP4 ISS",
 989                 sizeof(iss->media_dev.model));
 990         iss->media_dev.hw_revision = iss->revision;
 991         iss->media_dev.ops = &iss_media_ops;
 992         ret = media_device_register(&iss->media_dev);
 993         if (ret < 0) {
 994                 dev_err(iss->dev, "Media device registration failed (%d)\n",
 995                         ret);
 996                 return ret;
 997         }
 998 
 999         iss->v4l2_dev.mdev = &iss->media_dev;
1000         ret = v4l2_device_register(iss->dev, &iss->v4l2_dev);
1001         if (ret < 0) {
1002                 dev_err(iss->dev, "V4L2 device registration failed (%d)\n",
1003                         ret);
1004                 goto done;
1005         }
1006 
1007         
1008         ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev);
1009         if (ret < 0)
1010                 goto done;
1011 
1012         ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev);
1013         if (ret < 0)
1014                 goto done;
1015 
1016         ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev);
1017         if (ret < 0)
1018                 goto done;
1019 
1020         ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev);
1021         if (ret < 0)
1022                 goto done;
1023 
1024         ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev);
1025         if (ret < 0)
1026                 goto done;
1027 
1028         
1029         for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
1030                 struct v4l2_subdev *sensor;
1031                 struct media_entity *input;
1032                 unsigned int flags;
1033                 unsigned int pad;
1034 
1035                 sensor = iss_register_subdev_group(iss, subdevs->subdevs);
1036                 if (!sensor)
1037                         continue;
1038 
1039                 sensor->host_priv = subdevs;
1040 
1041                 
1042 
1043 
1044 
1045                 switch (subdevs->interface) {
1046                 case ISS_INTERFACE_CSI2A_PHY1:
1047                         input = &iss->csi2a.subdev.entity;
1048                         pad = CSI2_PAD_SINK;
1049                         flags = MEDIA_LNK_FL_IMMUTABLE
1050                               | MEDIA_LNK_FL_ENABLED;
1051                         break;
1052 
1053                 case ISS_INTERFACE_CSI2B_PHY2:
1054                         input = &iss->csi2b.subdev.entity;
1055                         pad = CSI2_PAD_SINK;
1056                         flags = MEDIA_LNK_FL_IMMUTABLE
1057                               | MEDIA_LNK_FL_ENABLED;
1058                         break;
1059 
1060                 default:
1061                         dev_err(iss->dev, "invalid interface type %u\n",
1062                                 subdevs->interface);
1063                         ret = -EINVAL;
1064                         goto done;
1065                 }
1066 
1067                 ret = media_create_pad_link(&sensor->entity, 0, input, pad,
1068                                             flags);
1069                 if (ret < 0)
1070                         goto done;
1071         }
1072 
1073         ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev);
1074 
1075 done:
1076         if (ret < 0)
1077                 iss_unregister_entities(iss);
1078 
1079         return ret;
1080 }
1081 
1082 
1083 
1084 
1085 
1086 
1087 
1088 static int iss_create_links(struct iss_device *iss)
1089 {
1090         int ret;
1091 
1092         ret = omap4iss_csi2_create_links(iss);
1093         if (ret < 0) {
1094                 dev_err(iss->dev, "CSI2 pads links creation failed\n");
1095                 return ret;
1096         }
1097 
1098         ret = omap4iss_ipipeif_create_links(iss);
1099         if (ret < 0) {
1100                 dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n");
1101                 return ret;
1102         }
1103 
1104         ret = omap4iss_resizer_create_links(iss);
1105         if (ret < 0) {
1106                 dev_err(iss->dev, "ISP RESIZER pads links creation failed\n");
1107                 return ret;
1108         }
1109 
1110         
1111         ret = media_create_pad_link(
1112                         &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
1113                         &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
1114         if (ret < 0)
1115                 return ret;
1116 
1117         ret = media_create_pad_link(
1118                         &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
1119                         &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
1120         if (ret < 0)
1121                 return ret;
1122 
1123         ret = media_create_pad_link(
1124                         &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
1125                         &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
1126         if (ret < 0)
1127                 return ret;
1128 
1129         ret = media_create_pad_link(
1130                         &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
1131                         &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
1132         if (ret < 0)
1133                 return ret;
1134 
1135         ret = media_create_pad_link(
1136                         &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
1137                         &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
1138         if (ret < 0)
1139                 return ret;
1140 
1141         return 0;
1142 };
1143 
1144 static void iss_cleanup_modules(struct iss_device *iss)
1145 {
1146         omap4iss_csi2_cleanup(iss);
1147         omap4iss_ipipeif_cleanup(iss);
1148         omap4iss_ipipe_cleanup(iss);
1149         omap4iss_resizer_cleanup(iss);
1150 }
1151 
1152 static int iss_initialize_modules(struct iss_device *iss)
1153 {
1154         int ret;
1155 
1156         ret = omap4iss_csiphy_init(iss);
1157         if (ret < 0) {
1158                 dev_err(iss->dev, "CSI PHY initialization failed\n");
1159                 goto error_csiphy;
1160         }
1161 
1162         ret = omap4iss_csi2_init(iss);
1163         if (ret < 0) {
1164                 dev_err(iss->dev, "CSI2 initialization failed\n");
1165                 goto error_csi2;
1166         }
1167 
1168         ret = omap4iss_ipipeif_init(iss);
1169         if (ret < 0) {
1170                 dev_err(iss->dev, "ISP IPIPEIF initialization failed\n");
1171                 goto error_ipipeif;
1172         }
1173 
1174         ret = omap4iss_ipipe_init(iss);
1175         if (ret < 0) {
1176                 dev_err(iss->dev, "ISP IPIPE initialization failed\n");
1177                 goto error_ipipe;
1178         }
1179 
1180         ret = omap4iss_resizer_init(iss);
1181         if (ret < 0) {
1182                 dev_err(iss->dev, "ISP RESIZER initialization failed\n");
1183                 goto error_resizer;
1184         }
1185 
1186         return 0;
1187 
1188 error_resizer:
1189         omap4iss_ipipe_cleanup(iss);
1190 error_ipipe:
1191         omap4iss_ipipeif_cleanup(iss);
1192 error_ipipeif:
1193         omap4iss_csi2_cleanup(iss);
1194 error_csi2:
1195 error_csiphy:
1196         return ret;
1197 }
1198 
1199 static int iss_probe(struct platform_device *pdev)
1200 {
1201         struct iss_platform_data *pdata = pdev->dev.platform_data;
1202         struct iss_device *iss;
1203         unsigned int i;
1204         int ret;
1205 
1206         if (!pdata)
1207                 return -EINVAL;
1208 
1209         iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
1210         if (!iss)
1211                 return -ENOMEM;
1212 
1213         mutex_init(&iss->iss_mutex);
1214 
1215         iss->dev = &pdev->dev;
1216         iss->pdata = pdata;
1217 
1218         iss->raw_dmamask = DMA_BIT_MASK(32);
1219         iss->dev->dma_mask = &iss->raw_dmamask;
1220         iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);
1221 
1222         platform_set_drvdata(pdev, iss);
1223 
1224         
1225 
1226 
1227 
1228         iss->syscon = syscon_regmap_lookup_by_compatible("syscon");
1229         if (IS_ERR(iss->syscon)) {
1230                 ret = PTR_ERR(iss->syscon);
1231                 goto error;
1232         }
1233 
1234         
1235         ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
1236         if (ret < 0)
1237                 goto error;
1238 
1239         ret = iss_get_clocks(iss);
1240         if (ret < 0)
1241                 goto error;
1242 
1243         if (!omap4iss_get(iss))
1244                 goto error;
1245 
1246         ret = iss_reset(iss);
1247         if (ret < 0)
1248                 goto error_iss;
1249 
1250         iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
1251         dev_info(iss->dev, "Revision %08x found\n", iss->revision);
1252 
1253         for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
1254                 ret = iss_map_mem_resource(pdev, iss, i);
1255                 if (ret)
1256                         goto error_iss;
1257         }
1258 
1259         
1260         iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
1261                        BTE_CTRL_BW_LIMITER_MASK,
1262                        18 << BTE_CTRL_BW_LIMITER_SHIFT);
1263 
1264         
1265         ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
1266         if (ret < 0)
1267                 goto error_iss;
1268 
1269         ret = iss_isp_reset(iss);
1270         if (ret < 0)
1271                 goto error_iss;
1272 
1273         dev_info(iss->dev, "ISP Revision %08x found\n",
1274                  iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));
1275 
1276         
1277         ret = platform_get_irq(pdev, 0);
1278         if (ret <= 0) {
1279                 ret = -ENODEV;
1280                 goto error_iss;
1281         }
1282         iss->irq_num = ret;
1283 
1284         if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
1285                              "OMAP4 ISS", iss)) {
1286                 dev_err(iss->dev, "Unable to request IRQ\n");
1287                 ret = -EINVAL;
1288                 goto error_iss;
1289         }
1290 
1291         
1292         ret = iss_initialize_modules(iss);
1293         if (ret < 0)
1294                 goto error_iss;
1295 
1296         ret = iss_register_entities(iss);
1297         if (ret < 0)
1298                 goto error_modules;
1299 
1300         ret = media_entity_enum_init(&iss->crashed, &iss->media_dev);
1301         if (ret)
1302                 goto error_entities;
1303 
1304         ret = iss_create_links(iss);
1305         if (ret < 0)
1306                 goto error_entities;
1307 
1308         omap4iss_put(iss);
1309 
1310         return 0;
1311 
1312 error_entities:
1313         iss_unregister_entities(iss);
1314         media_entity_enum_cleanup(&iss->crashed);
1315 error_modules:
1316         iss_cleanup_modules(iss);
1317 error_iss:
1318         omap4iss_put(iss);
1319 error:
1320         mutex_destroy(&iss->iss_mutex);
1321 
1322         return ret;
1323 }
1324 
1325 static int iss_remove(struct platform_device *pdev)
1326 {
1327         struct iss_device *iss = platform_get_drvdata(pdev);
1328 
1329         iss_unregister_entities(iss);
1330         media_entity_enum_cleanup(&iss->crashed);
1331         iss_cleanup_modules(iss);
1332 
1333         return 0;
1334 }
1335 
1336 static const struct platform_device_id omap4iss_id_table[] = {
1337         { "omap4iss", 0 },
1338         { },
1339 };
1340 MODULE_DEVICE_TABLE(platform, omap4iss_id_table);
1341 
1342 static struct platform_driver iss_driver = {
1343         .probe          = iss_probe,
1344         .remove         = iss_remove,
1345         .id_table       = omap4iss_id_table,
1346         .driver = {
1347                 .name   = "omap4iss",
1348         },
1349 };
1350 
1351 module_platform_driver(iss_driver);
1352 
1353 MODULE_DESCRIPTION("TI OMAP4 ISS driver");
1354 MODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>");
1355 MODULE_LICENSE("GPL");
1356 MODULE_VERSION(ISS_VIDEO_DRIVER_VERSION);