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;
}
Exemplo n.º 2
0
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;
}