Commit 08818e6a authored by Heiko Stuebner's avatar Heiko Stuebner Committed by Mauro Carvalho Chehab
Browse files

media: rockchip: rkisp1: allow separate interrupts



Depending on the per-soc implementation there can be one interrupt
for isp, mipi and capture events or separate per-event interrupts.

So simply check for the presence of a named "mi" interrupt
to differentiate between the two cases.

Signed-off-by: default avatarHeiko Stuebner <heiko.stuebner@theobroma-systems.com>
Reviewed-by: default avatarDafna Hirschfeld <dafna.hirschfeld@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 098d9cdf
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -685,12 +685,17 @@ static void rkisp1_handle_buffer(struct rkisp1_capture *cap)
	spin_unlock(&cap->buf.lock);
}

void rkisp1_capture_isr(struct rkisp1_device *rkisp1)
irqreturn_t rkisp1_capture_isr(int irq, void *ctx)
{
	struct device *dev = ctx;
	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
	unsigned int i;
	u32 status;

	status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS);
	if (!status)
		return IRQ_NONE;

	rkisp1_write(rkisp1, status, RKISP1_CIF_MI_ICR);

	for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); ++i) {
@@ -718,6 +723,8 @@ void rkisp1_capture_isr(struct rkisp1_device *rkisp1)
		cap->is_streaming = false;
		wake_up(&cap->done);
	}

	return IRQ_HANDLED;
}

/* ----------------------------------------------------------------------------
+4 −3
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#define _RKISP1_COMMON_H

#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <linux/rkisp1-config.h>
#include <media/media-device.h>
@@ -455,9 +456,9 @@ void rkisp1_params_configure(struct rkisp1_params *params,
void rkisp1_params_disable(struct rkisp1_params *params);

/* irq handlers */
void rkisp1_isp_isr(struct rkisp1_device *rkisp1);
void rkisp1_mipi_isr(struct rkisp1_device *rkisp1);
void rkisp1_capture_isr(struct rkisp1_device *rkisp1);
irqreturn_t rkisp1_isp_isr(int irq, void *ctx);
irqreturn_t rkisp1_mipi_isr(int irq, void *ctx);
irqreturn_t rkisp1_capture_isr(int irq, void *ctx);
void rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris);
void rkisp1_params_isr(struct rkisp1_device *rkisp1);

+34 −20
Original line number Diff line number Diff line
@@ -101,9 +101,16 @@
 *  +-----------+    +-----------+
 */

struct rkisp1_isr_data {
	const char *name;
	irqreturn_t (*isr)(int irq, void *ctx);
};

struct rkisp1_match_data {
	const char * const *clks;
	unsigned int size;
	unsigned int clk_size;
	const struct rkisp1_isr_data *isrs;
	unsigned int isr_size;
	enum rkisp1_cif_isp_version isp_ver;
};

@@ -386,18 +393,15 @@ static int rkisp1_entities_register(struct rkisp1_device *rkisp1)

static irqreturn_t rkisp1_isr(int irq, void *ctx)
{
	struct device *dev = ctx;
	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);

	/*
	 * Call rkisp1_capture_isr() first to handle the frame that
	 * potentially completed using the current frame_sequence number before
	 * it is potentially incremented by rkisp1_isp_isr() in the vertical
	 * sync.
	 */
	rkisp1_capture_isr(rkisp1);
	rkisp1_isp_isr(rkisp1);
	rkisp1_mipi_isr(rkisp1);
	rkisp1_capture_isr(irq, ctx);
	rkisp1_isp_isr(irq, ctx);
	rkisp1_mipi_isr(irq, ctx);

	return IRQ_HANDLED;
}
@@ -408,9 +412,15 @@ static const char * const rk3399_isp_clks[] = {
	"hclk",
};

static const struct rkisp1_isr_data rk3399_isp_isrs[] = {
	{ NULL, rkisp1_isr },
};

static const struct rkisp1_match_data rk3399_isp_match_data = {
	.clks = rk3399_isp_clks,
	.size = ARRAY_SIZE(rk3399_isp_clks),
	.clk_size = ARRAY_SIZE(rk3399_isp_clks),
	.isrs = rk3399_isp_isrs,
	.isr_size = ARRAY_SIZE(rk3399_isp_isrs),
	.isp_ver = RKISP1_V10,
};

@@ -479,23 +489,27 @@ static int rkisp1_probe(struct platform_device *pdev)
	if (IS_ERR(rkisp1->base_addr))
		return PTR_ERR(rkisp1->base_addr);

	irq = platform_get_irq(pdev, 0);
	for (i = 0; i < match_data->isr_size; i++) {
		irq = (match_data->isrs[i].name) ?
				platform_get_irq_byname(pdev, match_data->isrs[i].name) :
				platform_get_irq(pdev, i);
		if (irq < 0)
			return irq;

	ret = devm_request_irq(dev, irq, rkisp1_isr, IRQF_SHARED,
		ret = devm_request_irq(dev, irq, match_data->isrs[i].isr, IRQF_SHARED,
				       dev_driver_string(dev), dev);
		if (ret) {
			dev_err(dev, "request irq failed: %d\n", ret);
			return ret;
		}
	}

	for (i = 0; i < match_data->size; i++)
	for (i = 0; i < match_data->clk_size; i++)
		rkisp1->clks[i].id = match_data->clks[i];
	ret = devm_clk_bulk_get(dev, match_data->size, rkisp1->clks);
	ret = devm_clk_bulk_get(dev, match_data->clk_size, rkisp1->clks);
	if (ret)
		return ret;
	rkisp1->clk_size = match_data->size;
	rkisp1->clk_size = match_data->clk_size;

	pm_runtime_enable(&pdev->dev);

+12 −4
Original line number Diff line number Diff line
@@ -1106,13 +1106,15 @@ void rkisp1_isp_unregister(struct rkisp1_device *rkisp1)
 * Interrupt handlers
 */

void rkisp1_mipi_isr(struct rkisp1_device *rkisp1)
irqreturn_t rkisp1_mipi_isr(int irq, void *ctx)
{
	struct device *dev = ctx;
	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
	u32 val, status;

	status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS);
	if (!status)
		return;
		return IRQ_NONE;

	rkisp1_write(rkisp1, status, RKISP1_CIF_MIPI_ICR);

@@ -1147,6 +1149,8 @@ void rkisp1_mipi_isr(struct rkisp1_device *rkisp1)
	} else {
		rkisp1->debug.mipi_error++;
	}

	return IRQ_HANDLED;
}

static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp)
@@ -1159,13 +1163,15 @@ static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp)
	v4l2_event_queue(isp->sd.devnode, &event);
}

void rkisp1_isp_isr(struct rkisp1_device *rkisp1)
irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
{
	struct device *dev = ctx;
	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
	u32 status, isp_err;

	status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS);
	if (!status)
		return;
		return IRQ_NONE;

	rkisp1_write(rkisp1, status, RKISP1_CIF_ISP_ICR);

@@ -1207,4 +1213,6 @@ void rkisp1_isp_isr(struct rkisp1_device *rkisp1)
		 */
		rkisp1_params_isr(rkisp1);
	}

	return IRQ_HANDLED;
}