root/drivers/staging/media/omap4iss/iss.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iss_print_status
  2. omap4iss_flush
  3. omap4iss_isp_enable_interrupts
  4. omap4iss_isp_disable_interrupts
  5. iss_enable_interrupts
  6. iss_disable_interrupts
  7. omap4iss_get_external_info
  8. omap4iss_configure_bridge
  9. iss_isr_dbg
  10. iss_isp_isr_dbg
  11. iss_isr
  12. iss_pipeline_disable
  13. iss_pipeline_enable
  14. omap4iss_pipeline_set_stream
  15. omap4iss_pipeline_cancel_stream
  16. iss_pipeline_is_last
  17. iss_reset
  18. iss_isp_reset
  19. omap4iss_module_sync_idle
  20. omap4iss_module_sync_is_stopping
  21. __iss_subclk_update
  22. omap4iss_subclk_enable
  23. omap4iss_subclk_disable
  24. __iss_isp_subclk_update
  25. omap4iss_isp_subclk_enable
  26. omap4iss_isp_subclk_disable
  27. iss_enable_clocks
  28. iss_disable_clocks
  29. iss_get_clocks
  30. omap4iss_get
  31. omap4iss_put
  32. iss_map_mem_resource
  33. iss_unregister_entities
  34. iss_register_subdev_group
  35. iss_register_entities
  36. iss_create_links
  37. iss_cleanup_modules
  38. iss_initialize_modules
  39. iss_probe
  40. iss_remove

   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         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  * iss_register_subdev_group - Register a group of subdevices
 934  * @iss: OMAP4 ISS device
 935  * @board_info: I2C subdevs board information array
 936  *
 937  * Register all I2C subdevices in the board_info array. The array must be
 938  * terminated by a NULL entry, and the first entry must be the sensor.
 939  *
 940  * Return a pointer to the sensor media entity if it has been successfully
 941  * registered, or NULL otherwise.
 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         /* Register internal entities */
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         /* Register external entities */
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                 /* Connect the sensor to the correct interface module.
1042                  * CSI2a receiver through CSIPHY1, or
1043                  * CSI2b receiver through CSIPHY2
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  * iss_create_links() - Pads links creation for the subdevices
1084  * @iss : Pointer to ISS device
1085  *
1086  * return negative error code or zero on success
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         /* Connect the submodules. */
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          * TODO: When implementing DT support switch to syscon regmap lookup by
1226          * phandle.
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         /* Clocks */
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         /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
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         /* Perform ISP reset */
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         /* Interrupt */
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         /* Entities */
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);

/* [<][>][^][v][top][bottom][index][help] */