From 18faa1b68a54ff976dd03bfd9ace2c4ef4f7315c Mon Sep 17 00:00:00 2001 From: Sumit Semwal Date: Thu, 2 Dec 2010 11:27:14 +0000 Subject: [PATCH] OMAP: DSS2: Introduce omap_channel as an omap_dss_device parameter, add new overlay manager. A panel connects to one of the overlay managers of DSS through some interface block. On OMAP4, specifying the type of the display is not sufficient to conclude which manager the panel should be connected to. Hence, a new member 'channel' is introduced in omap_dss_device structure to determine which manager the panel uses. The dss_recheck_connections() called in dss_driver_probe() uses this channel parameter to set the correct manager to the corresponding omap_dss_device. The channel parameter is used only once to ensure the correct managers are set for each panel. The parameter dssdev->manager->id will take care of ensuring that the panel and then the interface driver configures the correct DISPC channel. Also, add a new Overlay Manager in manager.c, make other changes needed for LCD2 channel. Signed-off-by: Sumit Semwal Signed-off-by: Mukund Mittal Signed-off-by: Samreen Signed-off-by: Tomi Valkeinen --- arch/arm/plat-omap/include/plat/display.h | 2 + drivers/video/omap2/dss/dispc.c | 21 +++---- drivers/video/omap2/dss/dss.h | 4 +- drivers/video/omap2/dss/manager.c | 77 ++++++++++++++--------- drivers/video/omap2/dss/overlay.c | 14 ++++- 5 files changed, 74 insertions(+), 44 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 0180f25d1c8b..537f4e449f50 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -358,6 +358,8 @@ struct omap_dss_device { enum omap_display_type type; + enum omap_channel channel; + union { struct { u8 data_lines; diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 6171bcc589f8..9f8c69f16e61 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1610,8 +1610,8 @@ static int _dispc_setup_plane(enum omap_plane plane, bool ilace, enum omap_dss_rotation_type rotation_type, u8 rotation, int mirror, - u8 global_alpha, - u8 pre_mult_alpha) + u8 global_alpha, u8 pre_mult_alpha, + enum omap_channel channel) { const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; bool five_taps = 0; @@ -1667,8 +1667,8 @@ static int _dispc_setup_plane(enum omap_plane plane, five_taps = height > out_height * 2; if (!five_taps) { - fclk = calc_fclk(OMAP_DSS_CHANNEL_LCD, width, height, - out_width, out_height); + fclk = calc_fclk(channel, width, height, out_width, + out_height); /* Try 5-tap filter if 3-tap fclk is too high */ if (cpu_is_omap34xx() && height > out_height && @@ -1682,9 +1682,8 @@ static int _dispc_setup_plane(enum omap_plane plane, } if (five_taps) - fclk = calc_fclk_five_taps(OMAP_DSS_CHANNEL_LCD, width, - height, out_width, out_height, - color_mode); + fclk = calc_fclk_five_taps(channel, width, height, + out_width, out_height, color_mode); DSSDBG("required fclk rate = %lu Hz\n", fclk); DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); @@ -3331,17 +3330,17 @@ int dispc_setup_plane(enum omap_plane plane, bool ilace, enum omap_dss_rotation_type rotation_type, u8 rotation, bool mirror, u8 global_alpha, - u8 pre_mult_alpha) + u8 pre_mult_alpha, enum omap_channel channel) { int r = 0; DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " - "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", + "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", plane, paddr, screen_width, pos_x, pos_y, width, height, out_width, out_height, ilace, color_mode, - rotation, mirror); + rotation, mirror, channel); enable_clocks(1); @@ -3354,7 +3353,7 @@ int dispc_setup_plane(enum omap_plane plane, rotation_type, rotation, mirror, global_alpha, - pre_mult_alpha); + pre_mult_alpha, channel); enable_clocks(0); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 3fcb8ab781af..b394951120ac 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -359,8 +359,8 @@ int dispc_setup_plane(enum omap_plane plane, bool ilace, enum omap_dss_rotation_type rotation_type, u8 rotation, bool mirror, - u8 global_alpha, - u8 pre_mult_alpha); + u8 global_alpha, u8 pre_mult_alpha, + enum omap_channel channel); bool dispc_go_busy(enum omap_channel channel); void dispc_go(enum omap_channel channel); diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 873b33469060..172d4e697309 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -513,11 +513,14 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) unsigned long timeout = msecs_to_jiffies(500); u32 irq; - if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) + if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { irq = DISPC_IRQ_EVSYNC_ODD; - else - irq = DISPC_IRQ_VSYNC; - + } else { + if (mgr->id == OMAP_DSS_CHANNEL_LCD) + irq = DISPC_IRQ_VSYNC; + else + irq = DISPC_IRQ_VSYNC2; + } return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); } @@ -525,7 +528,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); struct manager_cache_data *mc; - enum omap_channel channel; u32 irq; int r; int i; @@ -536,7 +538,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; - channel = OMAP_DSS_CHANNEL_DIGIT; } else { if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { enum omap_dss_update_mode mode; @@ -544,11 +545,14 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) if (mode != OMAP_DSS_UPDATE_AUTO) return 0; - irq = DISPC_IRQ_FRAMEDONE; + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_FRAMEDONE + : DISPC_IRQ_FRAMEDONE2; } else { - irq = DISPC_IRQ_VSYNC; + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_VSYNC + : DISPC_IRQ_VSYNC2; } - channel = OMAP_DSS_CHANNEL_LCD; } mc = &dss_cache.manager_cache[mgr->id]; @@ -595,7 +599,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) { unsigned long timeout = msecs_to_jiffies(500); - enum omap_channel channel; struct overlay_cache_data *oc; struct omap_dss_device *dssdev; u32 irq; @@ -612,7 +615,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; - channel = OMAP_DSS_CHANNEL_DIGIT; } else { if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { enum omap_dss_update_mode mode; @@ -620,11 +622,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) if (mode != OMAP_DSS_UPDATE_AUTO) return 0; - irq = DISPC_IRQ_FRAMEDONE; + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_FRAMEDONE + : DISPC_IRQ_FRAMEDONE2; } else { - irq = DISPC_IRQ_VSYNC; + irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? + DISPC_IRQ_VSYNC + : DISPC_IRQ_VSYNC2; } - channel = OMAP_DSS_CHANNEL_LCD; } oc = &dss_cache.overlay_cache[ovl->id]; @@ -844,7 +849,8 @@ static int configure_overlay(enum omap_plane plane) c->rotation, c->mirror, c->global_alpha, - c->pre_mult_alpha); + c->pre_mult_alpha, + c->channel); if (r) { /* this shouldn't happen */ @@ -896,10 +902,10 @@ static int configure_dispc(void) r = 0; busy = false; - mgr_busy[0] = dispc_go_busy(0); - mgr_busy[1] = dispc_go_busy(1); - mgr_go[0] = false; - mgr_go[1] = false; + for (i = 0; i < num_mgrs; i++) { + mgr_busy[i] = dispc_go_busy(i); + mgr_go[i] = false; + } /* Commit overlay settings */ for (i = 0; i < num_ovls; ++i) { @@ -1158,9 +1164,10 @@ static void dss_apply_irq_handler(void *data, u32 mask) const int num_mgrs = dss_feat_get_num_mgrs(); int i, r; bool mgr_busy[MAX_DSS_MANAGERS]; + u32 irq_mask; - mgr_busy[0] = dispc_go_busy(0); - mgr_busy[1] = dispc_go_busy(1); + for (i = 0; i < num_mgrs; i++) + mgr_busy[i] = dispc_go_busy(i); spin_lock(&dss_cache.lock); @@ -1181,8 +1188,8 @@ static void dss_apply_irq_handler(void *data, u32 mask) goto end; /* re-read busy flags */ - mgr_busy[0] = dispc_go_busy(0); - mgr_busy[1] = dispc_go_busy(1); + for (i = 0; i < num_mgrs; i++) + mgr_busy[i] = dispc_go_busy(i); /* keep running as long as there are busy managers, so that * we can collect overlay-applied information */ @@ -1191,9 +1198,12 @@ static void dss_apply_irq_handler(void *data, u32 mask) goto end; } - omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, - DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | - DISPC_IRQ_EVSYNC_EVEN); + irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | + DISPC_IRQ_EVSYNC_EVEN; + if (dss_has_feature(FEAT_MGR_LCD2)) + irq_mask |= DISPC_IRQ_VSYNC2; + + omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask); dss_cache.irq_enabled = false; end: @@ -1386,9 +1396,14 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) r = 0; dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); if (!dss_cache.irq_enabled) { - r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, - DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | - DISPC_IRQ_EVSYNC_EVEN); + u32 mask; + + mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | + DISPC_IRQ_EVSYNC_EVEN; + if (dss_has_feature(FEAT_MGR_LCD2)) + mask |= DISPC_IRQ_VSYNC2; + + r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); dss_cache.irq_enabled = true; } configure_dispc(); @@ -1480,6 +1495,10 @@ int dss_init_overlay_managers(struct platform_device *pdev) mgr->name = "tv"; mgr->id = OMAP_DSS_CHANNEL_DIGIT; break; + case 2: + mgr->name = "lcd2"; + mgr->id = OMAP_DSS_CHANNEL_LCD2; + break; } mgr->set_device = &omap_dss_set_device; diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 41a29024a8d0..456efef03c20 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -664,12 +664,22 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) int i; struct omap_overlay_manager *lcd_mgr; struct omap_overlay_manager *tv_mgr; + struct omap_overlay_manager *lcd2_mgr = NULL; struct omap_overlay_manager *mgr = NULL; lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); - - if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { + if (dss_has_feature(FEAT_MGR_LCD2)) + lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2); + + if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) { + if (!lcd2_mgr->device || force) { + if (lcd2_mgr->device) + lcd2_mgr->unset_device(lcd2_mgr); + lcd2_mgr->set_device(lcd2_mgr, dssdev); + mgr = lcd2_mgr; + } + } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { if (!lcd_mgr->device || force) { if (lcd_mgr->device) lcd_mgr->unset_device(lcd_mgr); -- GitLab