Skip to contentSkip to conversation

OMAP: DSS2: Have separate irq handlers for DISPC and DSI

PATCH Superseded Archit Taneja 3 participants 9 messages Feb 17, 2011 – Feb 18, 2011

Subsystems (5)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 OMAP: DSS2: Have separate irq handlers for DISPC and DSI

Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.

On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI.

On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no DSS_IRQSTATUS register.

Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.

Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.

The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.

---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c |   13 +++----
 arch/arm/mach-omap2/omap_hwmod_2430_data.c |   12 +++---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   21 +++++++-----
 drivers/video/omap2/dss/dispc.c            |   39 ++++++++++++++++++++--
 drivers/video/omap2/dss/dsi.c              |   30 ++++++++++++++++-
 drivers/video/omap2/dss/dss.c              |   50 ++++-----------------------
 drivers/video/omap2/dss/dss.h              |    6 +++
 drivers/video/omap2/dss/dss_features.c     |    5 ++-
 drivers/video/omap2/dss/dss_features.h     |   17 +++++----
 9 files changed, 115 insertions(+), 78 deletions(-)
arch/arm/mach-omap2/omap_hwmod_2420_data.c +6 -7
index 21014de..028bcab 100644
@@ -506,11 +506,6 @@ static struct omap_hwmod_class omap2420_dss_hwmod_class = {
 	.sysc = &omap2420_dss_sysc,
 };
 
-/* dss */
-static struct omap_hwmod_irq_info omap2420_dss_irqs[] = {
-	{ .irq = 25 },
-};
-
 static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = {
 	{ .name = "dispc", .dma_req = 5 },
 };
@@ -559,8 +554,6 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap2420_dss_hwmod_class,
 	.main_clk	= "dss1_fck", /* instead of dss_fck */
-	.mpu_irqs	= omap2420_dss_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dss_irqs),
 	.sdma_reqs	= omap2420_dss_sdma_chs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_dss_sdma_chs),
 	.prcm		= {
@@ -603,6 +596,10 @@ static struct omap_hwmod_class omap2420_dispc_hwmod_class = {
 	.sysc = &omap2420_dispc_sysc,
 };
 
+static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = {
+	{ .irq = 25 },
+};
+
 static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = {
 	{
 		.pa_start	= 0x48050400,
@@ -635,6 +632,8 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
 static struct omap_hwmod omap2420_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2420_dispc_hwmod_class,
+	.mpu_irqs	= omap2420_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dispc_irqs),
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
arch/arm/mach-omap2/omap_hwmod_2430_data.c +6 -6
index 1ef3f3f..777b1ca 100644
@@ -505,10 +505,6 @@ static struct omap_hwmod_class omap2430_dss_hwmod_class = {
 	.sysc = &omap2430_dss_sysc,
 };
 
-/* dss */
-static struct omap_hwmod_irq_info omap2430_dss_irqs[] = {
-	{ .irq = 25 },
-};
 static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = {
 	{ .name = "dispc", .dma_req = 5 },
 };
@@ -551,8 +547,6 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap2430_dss_hwmod_class,
 	.main_clk	= "dss1_fck", /* instead of dss_fck */
-	.mpu_irqs	= omap2430_dss_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dss_irqs),
 	.sdma_reqs	= omap2430_dss_sdma_chs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_dss_sdma_chs),
 	.prcm		= {
@@ -595,6 +589,10 @@ static struct omap_hwmod_class omap2430_dispc_hwmod_class = {
 	.sysc = &omap2430_dispc_sysc,
 };
 
+static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = {
+	{ .irq = 25 },
+};
+
 static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = {
 	{
 		.pa_start	= 0x48050400,
@@ -621,6 +619,8 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
 static struct omap_hwmod omap2430_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2430_dispc_hwmod_class,
+	.mpu_irqs	= omap2430_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dispc_irqs),
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +12 -9
index cb0c624..a9b4857 100644
@@ -702,11 +702,6 @@ static struct omap_hwmod_class omap3xxx_dss_hwmod_class = {
 	.sysc = &omap3xxx_dss_sysc,
 };
 
-/* dss */
-static struct omap_hwmod_irq_info omap3xxx_dss_irqs[] = {
-	{ .irq = 25 },
-};
-
 static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
 	{ .name = "dispc", .dma_req = 5 },
 	{ .name = "dsi1", .dma_req = 74 },
@@ -778,8 +773,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap3xxx_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
-	.mpu_irqs	= omap3xxx_dss_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dss_irqs),
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
 
@@ -806,8 +799,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {
 	.name		= "dss_core",
 	.class		= &omap3xxx_dss_hwmod_class,
 	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
-	.mpu_irqs	= omap3xxx_dss_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dss_irqs),
 	.sdma_reqs	= omap3xxx_dss_sdma_chs,
 	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
 
@@ -853,6 +844,10 @@ static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = {
 	.sysc = &omap3xxx_dispc_sysc,
 };
 
+static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = {
+	{ .irq = 25 },
+};
+
 static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = {
 	{
 		.pa_start	= 0x48050400,
@@ -886,6 +881,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
 static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap3xxx_dispc_hwmod_class,
+	.mpu_irqs	= omap3xxx_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dispc_irqs),
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
@@ -911,6 +908,10 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
 	.name = "dsi",
 };
 
+static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
+	{ .irq = 25 },
+};
+
 /* dss_dsi1 */
 static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
 	{
@@ -944,6 +945,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
+	.mpu_irqs	= omap3xxx_dsi1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dsi1_irqs),
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
drivers/video/omap2/dss/dispc.c +36 -3
index cc58208..52a3c18 100644
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/hardirq.h>
+#include <linux/interrupt.h>
 
 #include <plat/sram.h>
 #include <plat/clock.h>
@@ -178,6 +179,7 @@ struct dispc_irq_stats {
 static struct {
 	struct platform_device *pdev;
 	void __iomem    *base;
+	int irq;
 
 	u32	fifo_size[3];
 
@@ -2930,6 +2932,18 @@ void dispc_irq_handler(void)
 	spin_unlock(&dispc.irq_lock);
 }
 
+static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
+{
+	if (dss_has_feature(FEAT_COMMON_IRQ_DISPC_DSI)) {
+		if (!(dss_get_irq_source() & DSS_IRQ_SRC_DISPC))
+			return IRQ_HANDLED;
+	}
+
+	dispc_irq_handler();
+
+	return IRQ_HANDLED;
+}
+
 static void dispc_error_worker(struct work_struct *work)
 {
 	int i;
@@ -3322,6 +3336,7 @@ int dispc_setup_plane(enum omap_plane plane,
 static int omap_dispchw_probe(struct platform_device *pdev)
 {
 	u32 rev;
+	int r = 0;
 	struct resource *dispc_mem;
 
 	dispc.pdev = pdev;
@@ -3338,12 +3353,27 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 	dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
 	if (!dispc_mem) {
 		DSSERR("can't get IORESOURCE_MEM DISPC\n");
-		return -EINVAL;
+		r = -EINVAL;
+		goto fail0;
 	}
 	dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
 	if (!dispc.base) {
 		DSSERR("can't ioremap DISPC\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto fail0;
+	}
+	dispc.irq = platform_get_irq(dispc.pdev, 0);
+	if (dispc.irq < 0) {
+		DSSERR("omap2 dispc: platform_get_irq failed\n");
+		r = -ENODEV;
+		goto fail1;
+	}
+
+	r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
+		"OMAP DISPC", dispc.pdev);
+	if (r < 0) {
+		DSSERR("omap2 dispc: request_irq failed\n");
+		goto fail1;
 	}
 
 	enable_clocks(1);
@@ -3359,12 +3389,15 @@ static int omap_dispchw_probe(struct platform_device *pdev)
 	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
 
 	enable_clocks(0);
-
+fail1:
+	iounmap(dispc.base);
+fail0:
 	return 0;
 }
 
 static int omap_dispchw_remove(struct platform_device *pdev)
 {
+	free_irq(dispc.irq, NULL);
 	iounmap(dispc.base);
 	return 0;
 }
drivers/video/omap2/dss/dsi.c +29 -1
index 1802057..3298169 100644
@@ -38,6 +38,7 @@
 #include <plat/clock.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /*#define VERBOSE_IRQ*/
 #define DSI_CATCH_MISSING_TE
@@ -222,6 +223,7 @@ static struct
 {
 	struct platform_device *pdev;
 	void __iomem	*base;
+	int irq;
 
 	struct dsi_clock_info current_cinfo;
 
@@ -580,7 +582,17 @@ void dsi_irq_handler(void)
 #endif
 }
 
+static irqreturn_t omap_dsi_irq_handler(int irq, void *arg)
+{
+	if (dss_has_feature(FEAT_COMMON_IRQ_DISPC_DSI)) {
+		if (!(dss_get_irq_source() & DSS_IRQ_SRC_DSI))
+			return IRQ_HANDLED;
+	}
 
+	dsi_irq_handler();
+
+	return IRQ_HANDLED;
+}
 static void _dsi_initialize_irq(void)
 {
 	u32 l;
@@ -3294,12 +3306,25 @@ static int dsi_init(struct platform_device *pdev)
 		r = -ENOMEM;
 		goto err1;
 	}
+	dsi.irq	= platform_get_irq(dsi.pdev, 0);
+	if (dsi.irq < 0) {
+		DSSERR("omap2 dsi: platform_get_irq failed\n");
+		r = -ENODEV;
+		goto err2;
+	}
+
+	r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED,
+		"OMAP DSI1", dsi.pdev);
+	if (r < 0) {
+		DSSERR("omap2 dsi: request_irq failed\n");
+		goto err2;
+	}
 
 	dsi.vdds_dsi_reg = dsi_get_vdds_dsi();
 	if (IS_ERR(dsi.vdds_dsi_reg)) {
 		DSSERR("can't get VDDS_DSI regulator\n");
 		r = PTR_ERR(dsi.vdds_dsi_reg);
-		goto err2;
+		goto err3;
 	}
 
 	enable_clocks(1);
@@ -3311,6 +3336,8 @@ static int dsi_init(struct platform_device *pdev)
 	enable_clocks(0);
 
 	return 0;
+err3:
+	free_irq(dsi.irq, NULL);
 err2:
 	iounmap(dsi.base);
 err1:
@@ -3326,6 +3353,7 @@ static void dsi_exit(void)
 		dsi.vdds_dsi_reg = NULL;
 	}
 
+	free_irq(dsi.irq, NULL);
 	iounmap(dsi.base);
 
 	destroy_workqueue(dsi.workqueue);
drivers/video/omap2/dss/dss.c +8 -42

97 lines not on this page · raw message

drivers/video/omap2/dss/dss.h +6 -0
index 4b02e07..ecf9ebf 100644
@@ -125,6 +125,11 @@ enum dss_clk_source {
 	DSS_SRC_DSS1_ALWON_FCLK,
 };
 
+enum dss_irq_source {
+	DSS_IRQ_SRC_DISPC	= 1 << 0,
+	DSS_IRQ_SRC_DSI		= 1 << 1,
+};
+
 struct dss_clock_info {
 	/* rates that we get with dividers below */
 	unsigned long fck;
@@ -243,6 +248,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo);
 int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
 		struct dss_clock_info *dss_cinfo,
 		struct dispc_clock_info *dispc_cinfo);
+enum dss_irq_source dss_get_irq_source(void);
 
 /* SDI */
 #ifdef CONFIG_OMAP2_DSS_SDI
drivers/video/omap2/dss/dss_features.c +3 -2
index cf3ef69..f3ef929 100644
@@ -157,7 +157,7 @@ static struct omap_dss_features omap3430_dss_features = {
 	.has_feature	=
 		FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
 		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-		FEAT_FUNCGATED,
+		FEAT_FUNCGATED | FEAT_COMMON_IRQ_DISPC_DSI,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
@@ -172,7 +172,8 @@ static struct omap_dss_features omap3630_dss_features = {
 	.has_feature    =
 		FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
 		FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
-		FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED,
+		FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
+		FEAT_COMMON_IRQ_DISPC_DSI,
 
 	.num_mgrs = 2,
 	.num_ovls = 3,
drivers/video/omap2/dss/dss_features.h +9 -8
index b9c70be..1c93a49 100644
@@ -25,14 +25,15 @@
 
 /* DSS has feature id */
 enum dss_feat_id {
-	FEAT_GLOBAL_ALPHA	= 1 << 0,
-	FEAT_GLOBAL_ALPHA_VID1	= 1 << 1,
-	FEAT_PRE_MULT_ALPHA	= 1 << 2,
-	FEAT_LCDENABLEPOL	= 1 << 3,
-	FEAT_LCDENABLESIGNAL	= 1 << 4,
-	FEAT_PCKFREEENABLE	= 1 << 5,
-	FEAT_FUNCGATED		= 1 << 6,
-	FEAT_MGR_LCD2		= 1 << 7,
+	FEAT_GLOBAL_ALPHA		= 1 << 0,
+	FEAT_GLOBAL_ALPHA_VID1		= 1 << 1,
+	FEAT_PRE_MULT_ALPHA		= 1 << 2,
+	FEAT_LCDENABLEPOL		= 1 << 3,
+	FEAT_LCDENABLESIGNAL		= 1 << 4,
+	FEAT_PCKFREEENABLE		= 1 << 5,
+	FEAT_FUNCGATED			= 1 << 6,
+	FEAT_MGR_LCD2			= 1 << 7,
+	FEAT_COMMON_IRQ_DISPC_DSI	= 1 << 8,
 };
 
 /* DSS register field id */
Signature · 1 line
1.7.1
#1 lore raw

Hi,

Quoted 12 lines · Archit

Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.

On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI.

On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no DSS_IRQSTATUS register.

Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.

Quoted 7 lines

Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.

The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.

Yes, I think this looks much cleaner.

However, I'm not sure if it's necessary to check the DSS_IRQSTATUS. It depends a bit on how DSS_IRQSTATUS works. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up in DSI_IRQSTATUS, the DSI bit in DSS_IRQSTATUS is up), we can do without it.

For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.

Now, if DSI_IRQSTATUS is all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well check DSI_IRQSTATUS, and exit if it's all zeroes.

If, on the other hand, DSI_IRQSTATUS has any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.

So in both cases the end result is the same, and we can do with less code by not using DSS_IRQSTATUS.

However, I'm not 100% sure DSS_IRQSTATUS works like that, but it would sound logical and I don't know how could it work otherwise.

Tomi

#2 lore raw

Hi,

Quoted 39 lines · Tomi

Hi,

Quoted 12 lines · Archit

Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.

On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI.

On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no DSS_IRQSTATUS register.

Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.

Quoted 7 lines

Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.

The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.

Yes, I think this looks much cleaner.

However, I'm not sure if it's necessary to check the DSS_IRQSTATUS. It depends a bit on how DSS_IRQSTATUS works. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up in DSI_IRQSTATUS, the DSI bit in DSS_IRQSTATUS is up), we can do without it.

For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.

Now, if DSI_IRQSTATUS is all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well check DSI_IRQSTATUS, and exit if it's all zeroes.

Quoted 8 lines

If, on the other hand, DSI_IRQSTATUS has any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.

So in both cases the end result is the same, and we can do with less code by not using DSS_IRQSTATUS.

However, I'm not 100% sure DSS_IRQSTATUS works like that, but it would sound logical and I don't know how could it work otherwise.

I can give it a try.

There is a figure in the OMAP3 TRM titled "DISPC and DSS Interrupts tree" which shows its logical OR. How the bits are set in DSS_IRQSTATUS is not mentioned anywhere though

Quoted 3 lines

Tomi

#3 lore raw
Quoted 59 lines · archit taneja

Hi,

Quoted 56 lines · Tomi

Hi,

Quoted 22 lines · Archit

Currently, the core DSS platform device requests for an irq line for OMAP2 and
OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.

On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There
is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI.

On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no
DSS_IRQSTATUS register.

Hence, it makes more sense to have separate irq handlers corresponding to the
DSS sub modules instead of having a common handler.

Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared
among the IRQ handlers.

Quoted 7 lines

The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3
hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss
feature is also added to tell whether the irq lines is shared between DISPC and
DSI or not.

Yes, I think this looks much cleaner.

However, I'm not sure if it's necessary to check the DSS_IRQSTATUS. It depends a bit on how DSS_IRQSTATUS works. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up in DSI_IRQSTATUS, the DSI bit in DSS_IRQSTATUS is up), we can do without it.

For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.

Now, if DSI_IRQSTATUS is all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well check DSI_IRQSTATUS, and exit if it's all zeroes.

If, on the other hand, DSI_IRQSTATUS has any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.

So in both cases the end result is the same, and we can do with less code by not using DSS_IRQSTATUS.

Quoted 8 lines
Quoted 2 lines

However, I'm not 100% sure DSS_IRQSTATUS works like that, but it would sound logical and I don't know how could it work otherwise.

I can give it a try.

There is a figure in the OMAP3 TRM titled "DISPC and DSS Interrupts tree" which shows its logical OR. How the bits are set in DSS_IRQSTATUS is not mentioned anywhere though

PRM_IRQSTATUS_* registers will have status bits set even when the corresponding PRM_IRQENABLE_* bits are not set. The common assumption was that status bits would not be set if interrupts weren't enabled and this caused us some issues in prcm_interrupt_handler some time back. I don't know how DSS_IRQSTATUS works under the hood, but be careful of such assumptions :-)

Regards,
Mike

Quoted 9 lines
Quoted 3 lines

 Tomi

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

On Fri, 2011-02-18 at 03:45 -0600, Turquette, Mike wrote:

<snip>

Quoted 6 lines

PRM_IRQSTATUS_* registers will have status bits set even when the corresponding PRM_IRQENABLE_* bits are not set. The common assumption was that status bits would not be set if interrupts weren't enabled and this caused us some issues in prcm_interrupt_handler some time back. I don't know how DSS_IRQSTATUS works under the hood, but be careful of such assumptions :-)

That's how DISPC_IRQ* and DSI_IRQ* also works. But that's not what this discussion was about =). DISPC and DSI have a shared interrupt line, and there's a DSS_IRQSTATUS register with two bits, telling if the interrupt was for DISPC or DSI.

Tomi

#5 lore raw
Quoted 10 lines · Tomi

On Fri, 2011-02-18 at 03:45 -0600, Turquette, Mike wrote:

<snip>

Quoted 6 lines

PRM_IRQSTATUS_* registers will have status bits set even when the corresponding PRM_IRQENABLE_* bits are not set. The common assumption was that status bits would not be set if interrupts weren't enabled and this caused us some issues in prcm_interrupt_handler some time back. I don't know how DSS_IRQSTATUS works under the hood, but be careful of such assumptions :-)

And, there is no DSS_IRQENABLE at all in our case :)

Quoted 9 lines

That's how DISPC_IRQ* and DSI_IRQ* also works. But that's not what this discussion was about =). DISPC and DSI have a shared interrupt line, and there's a DSS_IRQSTATUS register with two bits, telling if the interrupt was for DISPC or DSI.

Tomi

#6 lore raw
In reply to archit taneja
Quoted 48 lines · Archit

Hi,

Quoted 45 lines · Tomi

Hi,

Quoted 12 lines · Archit

Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.

On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI.

On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no DSS_IRQSTATUS register.

Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.

Quoted 7 lines

Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.

The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.

Yes, I think this looks much cleaner.

However, I'm not sure if it's necessary to check the DSS_IRQSTATUS. It depends a bit on how DSS_IRQSTATUS works. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up in DSI_IRQSTATUS, the DSI bit in DSS_IRQSTATUS is up), we can do without it.

For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.

Now, if DSI_IRQSTATUS is all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well check DSI_IRQSTATUS, and exit if it's all zeroes.

If, on the other hand, DSI_IRQSTATUS has any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.

So in both cases the end result is the same, and we can do with less code by not using DSS_IRQSTATUS.

Quoted 8 lines
Quoted 2 lines

However, I'm not 100% sure DSS_IRQSTATUS works like that, but it would sound logical and I don't know how could it work otherwise.

I can give it a try.

There is a figure in the OMAP3 TRM titled "DISPC and DSS Interrupts tree" which shows its logical OR. How the bits are set in DSS_IRQSTATUS is not mentioned anywhere though

Well, if DSS_IRQSTATUS doesn't work as I described above, in the worst case we will just run a few more lines of code in the irq handler, as we check for registered interrupts. But that would only happen if either DISPC or DSI has no interrupts enabled, which is... never?

So I think it should work fine anyway.

Tomi

#7 lore raw

Hi,

On Friday 18 February 2011 03:30 PM, Valkeinen, Tomi wrote:

<snip>

Quoted 8 lines

Well, if DSS_IRQSTATUS doesn't work as I described above, in the worst case we will just run a few more lines of code in the irq handler, as we check for registered interrupts. But that would only happen if either DISPC or DSI has no interrupts enabled, which is... never?

So I think it should work fine anyway.

Tomi

I tried to read IRQSTATUS registers in 2 the cases:

With DSS_IRQSTATUS:

[   51.166503] DSS_IRQSTATUS 2 -> DSI
[   51.170135] DSS_IRQSTATUS 2 -> DSI
[   51.173095] DSI_IRQSTATUS 20001 -> TE_TRIGGER | VC0_IRQ
[   51.208282] DSS_IRQSTATUS 1 -> DISPC
[   51.211242] DISPC_IRQSTATUS 81
[   51.214508] DSS_IRQSTATUS 2 -> FRAMEDONE | GFX_END_WINDOW
[   51.217437] DSI_IRQSTATUS 20001 -> TE_TRIGGER | VC0_IRQ

The cat /proc/interrupts increments by 2 for every manual update call.

Without DSS_IRQSTATUS:

Doing a ./upd (from omapfb-tests) on 3430sdp with Taal:

[   77.060668] DISPC irqstatus 0
[   77.064270] DSI irqstatus 20001-> TE_TRIGGER | VC0_IRQ
[   77.104888] DISPC irqstatus 81 -> FRAMEDONE | GFX_END_WINDOW
[   77.108154] DSI irqstatus 20001 -> TE_TRIGGER | VC0_IRQ

VC0_IRQSTATUS came as 0x24 -> BTA_ACK | PACKET_SENT

The cat /proc/interrupts increments by 2 for every manual update call as before.

One strange thing I see though is the increment with and without printks in the irq handler in both the cases. I always see increments of 2 when I put prints. I see 3 when I don't. That's a bit peculiar.

Behavior looks as expected. I guess we can go without DSS_IRQSTATUS then. Should I send out a patch? Also, should we remove DSS_IRQSTATUS in totality from the code now?

Archit

#8 lore raw
Quoted 2 lines · Archit

Hi,

<snip>

Quoted 3 lines

One strange thing I see though is the increment with and without printks in the irq handler in both the cases. I always see increments of 2 when I put prints. I see 3 when I don't. That's a bit peculiar.

Hmm. That's probably because prints make it slower. TE_TRIGGER and VC0_IRQ probably happen at different times. If you have printks, they are combined into one interrupt. If no printk, the code is faster and handles them separately.

Quoted 3 lines

Behavior looks as expected. I guess we can go without DSS_IRQSTATUS then. Should I send out a patch? Also, should we remove DSS_IRQSTATUS in totality from the code now?

Ok. Yes, please send a patch. Is DSS_IRQSTATUS used anywhere after the patch? I guess not. But let's leave the define there, as the register still exists.

Tomi