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