long msm_irqrouter_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd); struct msm_camera_irq_cfg *irq_cfg; struct intr_table_entry irq_req; int rc = 0; /* Handle all IRQ Router Subdev IOCTLs here. * Userspace sends the composite irq configuration. * IRQ Router subdev then configures the registers to group * together individual core hw irqs into a composite IRQ * to the MSM IRQ controller. It also registers them with * the irq manager in the camera server. */ switch (cmd) { case MSM_IRQROUTER_CFG_COMPIRQ: COPY_FROM_USER(rc, &irq_cfg, (void __user *)arg, sizeof(struct msm_camera_irq_cfg)); if (rc) { ERR_COPY_FROM_USER(); break; } if (!irq_cfg || (irq_cfg->irq_idx < CAMERA_SS_IRQ_0) || (irq_cfg->irq_idx >= CAMERA_SS_IRQ_MAX)) { pr_err("%s Invalid input", __func__); return -EINVAL; } else { irq_req.cam_hw_mask = irq_cfg->cam_hw_mask; irq_req.irq_idx = irq_cfg->irq_idx; irq_req.irq_num = irqrouter_ctrl->def_hw_irqmap[irq_cfg->irq_idx].irq_num; irq_req.is_composite = 1; irq_req.irq_trigger_type = IRQF_TRIGGER_RISING; irq_req.num_hwcore = irq_cfg->num_hwcore; irq_req.data = NULL; rc = msm_cam_server_request_irq(&irq_req); if (rc < 0) { pr_err("%s Error requesting comp irq %d ", __func__, irq_req.irq_idx); return rc; } irqrouter_ctrl->def_hw_irqmap [irq_cfg->irq_idx].is_composite = 1; } break; default: pr_err("%s Invalid cmd %d ", __func__, cmd); break; } return rc; }
static int __devinit csid_probe(struct platform_device *pdev) { struct csid_device *new_csid_dev; struct msm_cam_subdev_info sd_info; struct intr_table_entry irq_req; int rc = 0; CDBG("%s:%d called\n", __func__, __LINE__); new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL); if (!new_csid_dev) { pr_err("%s: no enough memory\n", __func__); return -ENOMEM; } v4l2_subdev_init(&new_csid_dev->subdev, &msm_csid_subdev_ops); new_csid_dev->subdev.internal_ops = &msm_csid_internal_ops; new_csid_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(new_csid_dev->subdev.name, ARRAY_SIZE(new_csid_dev->subdev.name), "msm_csid"); v4l2_set_subdevdata(&new_csid_dev->subdev, new_csid_dev); platform_set_drvdata(pdev, &new_csid_dev->subdev); mutex_init(&new_csid_dev->mutex); if (pdev->dev.of_node) of_property_read_u32((&pdev->dev)->of_node, "cell-index", &pdev->id); CDBG("%s device id %d\n", __func__, pdev->id); new_csid_dev->mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csid"); if (!new_csid_dev->mem) { pr_err("%s: no mem resource?\n", __func__); rc = -ENODEV; goto csid_no_resource; } new_csid_dev->irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "csid"); if (!new_csid_dev->irq) { pr_err("%s: no irq resource?\n", __func__); rc = -ENODEV; goto csid_no_resource; } new_csid_dev->io = request_mem_region(new_csid_dev->mem->start, resource_size(new_csid_dev->mem), pdev->name); if (!new_csid_dev->io) { pr_err("%s: no valid mem region\n", __func__); rc = -EBUSY; goto csid_no_resource; } new_csid_dev->pdev = pdev; sd_info.sdev_type = CSID_DEV; sd_info.sd_index = pdev->id; sd_info.irq_num = new_csid_dev->irq->start; msm_cam_register_subdev_node(&new_csid_dev->subdev, &sd_info); media_entity_init(&new_csid_dev->subdev.entity, 0, NULL, 0); new_csid_dev->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; new_csid_dev->subdev.entity.group_id = CSID_DEV; new_csid_dev->subdev.entity.name = pdev->name; new_csid_dev->subdev.entity.revision = new_csid_dev->subdev.devnode->num; /* Request for this device irq from the camera server. If the * IRQ Router is present on this target, the interrupt will be * handled by the camera server and the interrupt service * routine called. If the request_irq call returns ENXIO, then * the IRQ Router hardware is not present on this target. We * have to request for the irq ourselves and register the * appropriate interrupt handler. */ irq_req.cam_hw_idx = MSM_CAM_HW_CSI0 + pdev->id; irq_req.dev_name = "csid"; irq_req.irq_idx = CAMERA_SS_IRQ_2 + pdev->id; irq_req.irq_num = new_csid_dev->irq->start; irq_req.is_composite = 0; irq_req.irq_trigger_type = IRQF_TRIGGER_RISING; irq_req.num_hwcore = 1; irq_req.subdev_list[0] = &new_csid_dev->subdev; irq_req.data = (void *)new_csid_dev; rc = msm_cam_server_request_irq(&irq_req); if (rc == -ENXIO) { /* IRQ Router hardware is not present on this hardware. * Request for the IRQ and register the interrupt handler. */ rc = request_irq(new_csid_dev->irq->start, msm_csid_irq, IRQF_TRIGGER_RISING, "csid", new_csid_dev); if (rc < 0) { release_mem_region(new_csid_dev->mem->start, resource_size(new_csid_dev->mem)); pr_err("%s: irq request fail\n", __func__); rc = -EBUSY; goto csid_no_resource; } disable_irq(new_csid_dev->irq->start); } else if (rc < 0) { release_mem_region(new_csid_dev->mem->start, resource_size(new_csid_dev->mem)); pr_err("%s Error registering irq ", __func__); goto csid_no_resource; } new_csid_dev->csid_state = CSID_POWER_DOWN; if (pdev->id >= 0 && pdev->id < MAX_CSID) { pr_debug("Init csid %d\n", pdev->id); lsh_csid_dev[pdev->id] = new_csid_dev; } return 0; csid_no_resource: mutex_destroy(&new_csid_dev->mutex); kfree(new_csid_dev); return rc; }