Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83585886 authored by Gilad Broner's avatar Gilad Broner
Browse files

msm: tspp: Request IRQs on first use



Reserving the IRQs on driver initialization is redundant and should
be done only when client first uses the driver. Also, it may prevent
transition to power saving modes.
Move IRQ requests to be done when first stream is opened, and free
when last stream is closed.

Change-Id: I7147335aa51e047df8b173a05e057f77dc1c4894
Signed-off-by: default avatarGilad Broner <gbroner@codeaurora.org>
parent 538c521c
Loading
Loading
Loading
Loading
+88 −36
Original line number Diff line number Diff line
@@ -464,7 +464,6 @@ struct tspp_device {
	struct dentry *debugfs_regs[ARRAY_SIZE(debugfs_tspp_regs)];
};


static int tspp_key_entry;
static u32 channel_id;  /* next channel id number to assign */

@@ -909,9 +908,11 @@ static int tspp_start_tsif(struct tspp_tsif_device *tsif_device)
	}

	ctl = readl_relaxed(tsif_device->base + TSIF_STS_CTL_OFF);
	tsif_device->ref_count++;
	if (!(ctl & TSIF_STS_CTL_START))
		return -EBUSY;

	return (ctl & TSIF_STS_CTL_START) ? 0 : -EBUSY;
	tsif_device->ref_count++;
	return 0;
}

static void tspp_stop_tsif(struct tspp_tsif_device *tsif_device)
@@ -1252,6 +1253,56 @@ static void tspp_destroy_buffers(u32 channel_id, struct tspp_channel *channel)
	}
}

static int msm_tspp_req_irqs(struct tspp_device *device)
{
	int rc;
	int i;
	int j;

	rc = request_irq(device->tspp_irq, tspp_isr, IRQF_SHARED,
		dev_name(&device->pdev->dev), device);
	if (rc) {
		dev_err(&device->pdev->dev,
			"failed to request TSPP IRQ %d : %d",
			device->tspp_irq, rc);
		return rc;
	}

	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
		rc = request_irq(device->tsif[i].tsif_irq,
			tsif_isr, IRQF_SHARED, dev_name(&device->pdev->dev),
			&device->tsif[i]);
		if (rc) {
			dev_err(&device->pdev->dev,
				"failed to request TSIF%d IRQ: %d",
				i, rc);
			goto failed;
		}
	}

	return 0;

failed:
	free_irq(device->tspp_irq, device);
	for (j = 0; j < i; j++)
		free_irq(device->tsif[j].tsif_irq, device);

	return rc;
}

static inline void msm_tspp_free_irqs(struct tspp_device *device)
{
	int i;

	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
		if (device->tsif[i].tsif_irq)
			free_irq(device->tsif[i].tsif_irq,  &device->tsif[i]);
	}

	if (device->tspp_irq)
		free_irq(device->tspp_irq, device);
}

/*** TSPP API functions ***/

/**
@@ -1268,6 +1319,8 @@ int tspp_open_stream(u32 dev, u32 channel_id,
			struct tspp_select_source *source)
{
	u32 val;
	int rc;
	bool req_irq = false;
	struct tspp_device *pdev;
	struct tspp_channel *channel;

@@ -1296,16 +1349,30 @@ int tspp_open_stream(u32 dev, u32 channel_id,
			source->data_inverse, source->sync_inverse,
			source->enable_inverse);

	/* Request IRQ resources on first open */
	if ((source->source == TSPP_SOURCE_TSIF0 ||
		source->source == TSPP_SOURCE_TSIF1) &&
		(pdev->tsif[0].ref_count + pdev->tsif[1].ref_count) == 0) {
		rc = msm_tspp_req_irqs(pdev);
		if (rc) {
			pr_err("tspp: error requesting irqs\n");
			return rc;
		}
		req_irq = true;
	}

	switch (source->source) {
	case TSPP_SOURCE_TSIF0:
		if (tspp_config_gpios(pdev, channel->src, 1) != 0) {
			rc = -EBUSY;
			pr_err("tspp: error enabling tsif0 GPIOs\n");
			return -EBUSY;
			goto free_irq;
		}
		/* make sure TSIF0 is running & enabled */
		if (tspp_start_tsif(&pdev->tsif[0]) != 0) {
			rc = -EBUSY;
			pr_err("tspp: error starting tsif0");
			return -EBUSY;
			goto free_irq;
		}
		if (pdev->tsif[0].ref_count == 1) {
			val = readl_relaxed(pdev->base + TSPP_CONTROL);
@@ -1316,13 +1383,15 @@ int tspp_open_stream(u32 dev, u32 channel_id,
		break;
	case TSPP_SOURCE_TSIF1:
		if (tspp_config_gpios(pdev, channel->src, 1) != 0) {
			rc = -EBUSY;
			pr_err("tspp: error enabling tsif1 GPIOs\n");
			return -EBUSY;
			goto free_irq;
		}
		/* make sure TSIF1 is running & enabled */
		if (tspp_start_tsif(&pdev->tsif[1]) != 0) {
			rc = -EBUSY;
			pr_err("tspp: error starting tsif1");
			return -EBUSY;
			goto free_irq;
		}
		if (pdev->tsif[1].ref_count == 1) {
			val = readl_relaxed(pdev->base + TSPP_CONTROL);
@@ -1340,6 +1409,11 @@ int tspp_open_stream(u32 dev, u32 channel_id,
	}

	return 0;

free_irq:
	if (req_irq)
		msm_tspp_free_irqs(pdev);
	return rc;
}
EXPORT_SYMBOL(tspp_open_stream);

@@ -1355,7 +1429,7 @@ EXPORT_SYMBOL(tspp_open_stream);
int tspp_close_stream(u32 dev, u32 channel_id)
{
	u32 val;
	u32 prev_ref_count;
	u32 prev_ref_count = 0;
	struct tspp_device *pdev;
	struct tspp_channel *channel;

@@ -1404,6 +1478,12 @@ int tspp_close_stream(u32 dev, u32 channel_id)
	}

	channel->src = TSPP_SOURCE_NONE;

	/* Free requested interrupts to save power */
	if ((pdev->tsif[0].ref_count + pdev->tsif[1].ref_count) == 0 &&
		prev_ref_count)
		msm_tspp_free_irqs(pdev);

	return 0;
}
EXPORT_SYMBOL(tspp_close_stream);
@@ -2542,7 +2622,6 @@ static int msm_tspp_map_irqs(struct platform_device *pdev,
				struct tspp_device *device)
{
	int rc;
	int i;

	/* get IRQ numbers from platform information */

@@ -2550,15 +2629,6 @@ static int msm_tspp_map_irqs(struct platform_device *pdev,
	rc = platform_get_irq_byname(pdev, "TSIF_TSPP_IRQ");
	if (rc > 0) {
		device->tspp_irq = rc;
		rc = request_irq(device->tspp_irq, tspp_isr, IRQF_SHARED,
				 dev_name(&pdev->dev), device);
		if (rc) {
			dev_err(&pdev->dev,
				"failed to request TSPP IRQ %d : %d",
				device->tspp_irq, rc);
			device->tspp_irq = 0;
			return -EINVAL;
		}
	} else {
		dev_err(&pdev->dev, "failed to get TSPP IRQ");
		return -EINVAL;
@@ -2581,17 +2651,6 @@ static int msm_tspp_map_irqs(struct platform_device *pdev,
		return -EINVAL;
	}

	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
		rc = request_irq(device->tsif[i].tsif_irq,
				tsif_isr, IRQF_SHARED,
				dev_name(&pdev->dev), &device->tsif[i]);
		if (rc) {
			dev_warn(&pdev->dev, "failed to request TSIF%d IRQ: %d",
				i, rc);
			device->tsif[i].tsif_irq = 0;
		}
	}

	/* map BAM IRQ */
	rc = platform_get_irq_byname(pdev, "TSIF_BAM_IRQ");
	if (rc > 0) {
@@ -2850,13 +2909,6 @@ err_bam:
	for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
		tsif_debugfs_exit(&device->tsif[i]);
err_irq:
	for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
		if (device->tsif[i].tsif_irq)
			free_irq(device->tsif[i].tsif_irq,  &device->tsif[i]);
	}
	if (device->tspp_irq)
		free_irq(device->tspp_irq, device);

	iounmap(device->bam_props.virt_addr);
err_map_bam:
err_res_bam: