diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 55 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dsi.c | 20 |
2 files changed, 68 insertions, 7 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 2bbdb7ff7daf..b37e3fbf60cc 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -101,6 +101,8 @@ static struct { | |||
101 | void __iomem *base; | 101 | void __iomem *base; |
102 | 102 | ||
103 | int irq; | 103 | int irq; |
104 | irq_handler_t user_handler; | ||
105 | void *user_data; | ||
104 | 106 | ||
105 | unsigned long core_clk_rate; | 107 | unsigned long core_clk_rate; |
106 | unsigned long tv_pclk_rate; | 108 | unsigned long tv_pclk_rate; |
@@ -113,6 +115,8 @@ static struct { | |||
113 | u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; | 115 | u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; |
114 | 116 | ||
115 | const struct dispc_features *feat; | 117 | const struct dispc_features *feat; |
118 | |||
119 | bool is_enabled; | ||
116 | } dispc; | 120 | } dispc; |
117 | 121 | ||
118 | enum omap_color_component { | 122 | enum omap_color_component { |
@@ -3669,16 +3673,44 @@ static int __init dispc_init_features(struct platform_device *pdev) | |||
3669 | return 0; | 3673 | return 0; |
3670 | } | 3674 | } |
3671 | 3675 | ||
3676 | static irqreturn_t dispc_irq_handler(int irq, void *arg) | ||
3677 | { | ||
3678 | if (!dispc.is_enabled) | ||
3679 | return IRQ_NONE; | ||
3680 | |||
3681 | return dispc.user_handler(irq, dispc.user_data); | ||
3682 | } | ||
3683 | |||
3672 | int dispc_request_irq(irq_handler_t handler, void *dev_id) | 3684 | int dispc_request_irq(irq_handler_t handler, void *dev_id) |
3673 | { | 3685 | { |
3674 | return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler, | 3686 | int r; |
3675 | IRQF_SHARED, "OMAP DISPC", dev_id); | 3687 | |
3688 | if (dispc.user_handler != NULL) | ||
3689 | return -EBUSY; | ||
3690 | |||
3691 | dispc.user_handler = handler; | ||
3692 | dispc.user_data = dev_id; | ||
3693 | |||
3694 | /* ensure the dispc_irq_handler sees the values above */ | ||
3695 | smp_wmb(); | ||
3696 | |||
3697 | r = devm_request_irq(&dispc.pdev->dev, dispc.irq, dispc_irq_handler, | ||
3698 | IRQF_SHARED, "OMAP DISPC", &dispc); | ||
3699 | if (r) { | ||
3700 | dispc.user_handler = NULL; | ||
3701 | dispc.user_data = NULL; | ||
3702 | } | ||
3703 | |||
3704 | return r; | ||
3676 | } | 3705 | } |
3677 | EXPORT_SYMBOL(dispc_request_irq); | 3706 | EXPORT_SYMBOL(dispc_request_irq); |
3678 | 3707 | ||
3679 | void dispc_free_irq(void *dev_id) | 3708 | void dispc_free_irq(void *dev_id) |
3680 | { | 3709 | { |
3681 | devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id); | 3710 | devm_free_irq(&dispc.pdev->dev, dispc.irq, &dispc); |
3711 | |||
3712 | dispc.user_handler = NULL; | ||
3713 | dispc.user_data = NULL; | ||
3682 | } | 3714 | } |
3683 | EXPORT_SYMBOL(dispc_free_irq); | 3715 | EXPORT_SYMBOL(dispc_free_irq); |
3684 | 3716 | ||
@@ -3750,6 +3782,12 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev) | |||
3750 | 3782 | ||
3751 | static int dispc_runtime_suspend(struct device *dev) | 3783 | static int dispc_runtime_suspend(struct device *dev) |
3752 | { | 3784 | { |
3785 | dispc.is_enabled = false; | ||
3786 | /* ensure the dispc_irq_handler sees the is_enabled value */ | ||
3787 | smp_wmb(); | ||
3788 | /* wait for current handler to finish before turning the DISPC off */ | ||
3789 | synchronize_irq(dispc.irq); | ||
3790 | |||
3753 | dispc_save_context(); | 3791 | dispc_save_context(); |
3754 | 3792 | ||
3755 | return 0; | 3793 | return 0; |
@@ -3763,12 +3801,15 @@ static int dispc_runtime_resume(struct device *dev) | |||
3763 | * _omap_dispc_initial_config(). We can thus use it to detect if | 3801 | * _omap_dispc_initial_config(). We can thus use it to detect if |
3764 | * we have lost register context. | 3802 | * we have lost register context. |
3765 | */ | 3803 | */ |
3766 | if (REG_GET(DISPC_CONFIG, 2, 1) == OMAP_DSS_LOAD_FRAME_ONLY) | 3804 | if (REG_GET(DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) { |
3767 | return 0; | 3805 | _omap_dispc_initial_config(); |
3768 | 3806 | ||
3769 | _omap_dispc_initial_config(); | 3807 | dispc_restore_context(); |
3808 | } | ||
3770 | 3809 | ||
3771 | dispc_restore_context(); | 3810 | dispc.is_enabled = true; |
3811 | /* ensure the dispc_irq_handler sees the is_enabled value */ | ||
3812 | smp_wmb(); | ||
3772 | 3813 | ||
3773 | return 0; | 3814 | return 0; |
3774 | } | 3815 | } |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 121d1049d0bc..8be9b04d8849 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -297,6 +297,8 @@ struct dsi_data { | |||
297 | 297 | ||
298 | int irq; | 298 | int irq; |
299 | 299 | ||
300 | bool is_enabled; | ||
301 | |||
300 | struct clk *dss_clk; | 302 | struct clk *dss_clk; |
301 | struct clk *sys_clk; | 303 | struct clk *sys_clk; |
302 | 304 | ||
@@ -795,6 +797,9 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) | |||
795 | dsidev = (struct platform_device *) arg; | 797 | dsidev = (struct platform_device *) arg; |
796 | dsi = dsi_get_dsidrv_data(dsidev); | 798 | dsi = dsi_get_dsidrv_data(dsidev); |
797 | 799 | ||
800 | if (!dsi->is_enabled) | ||
801 | return IRQ_NONE; | ||
802 | |||
798 | spin_lock(&dsi->irq_lock); | 803 | spin_lock(&dsi->irq_lock); |
799 | 804 | ||
800 | irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS); | 805 | irqstatus = dsi_read_reg(dsidev, DSI_IRQSTATUS); |
@@ -5671,6 +5676,15 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) | |||
5671 | 5676 | ||
5672 | static int dsi_runtime_suspend(struct device *dev) | 5677 | static int dsi_runtime_suspend(struct device *dev) |
5673 | { | 5678 | { |
5679 | struct platform_device *pdev = to_platform_device(dev); | ||
5680 | struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); | ||
5681 | |||
5682 | dsi->is_enabled = false; | ||
5683 | /* ensure the irq handler sees the is_enabled value */ | ||
5684 | smp_wmb(); | ||
5685 | /* wait for current handler to finish before turning the DSI off */ | ||
5686 | synchronize_irq(dsi->irq); | ||
5687 | |||
5674 | dispc_runtime_put(); | 5688 | dispc_runtime_put(); |
5675 | 5689 | ||
5676 | return 0; | 5690 | return 0; |
@@ -5678,12 +5692,18 @@ static int dsi_runtime_suspend(struct device *dev) | |||
5678 | 5692 | ||
5679 | static int dsi_runtime_resume(struct device *dev) | 5693 | static int dsi_runtime_resume(struct device *dev) |
5680 | { | 5694 | { |
5695 | struct platform_device *pdev = to_platform_device(dev); | ||
5696 | struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); | ||
5681 | int r; | 5697 | int r; |
5682 | 5698 | ||
5683 | r = dispc_runtime_get(); | 5699 | r = dispc_runtime_get(); |
5684 | if (r) | 5700 | if (r) |
5685 | return r; | 5701 | return r; |
5686 | 5702 | ||
5703 | dsi->is_enabled = true; | ||
5704 | /* ensure the irq handler sees the is_enabled value */ | ||
5705 | smp_wmb(); | ||
5706 | |||
5687 | return 0; | 5707 | return 0; |
5688 | } | 5708 | } |
5689 | 5709 | ||