1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
214be3200SRob Clark /*
314be3200SRob Clark  * Copyright (C) 2013 Red Hat
414be3200SRob Clark  * Author: Rob Clark <robdclark@gmail.com>
514be3200SRob Clark  */
614be3200SRob Clark 
714be3200SRob Clark #include <linux/irq.h>
814be3200SRob Clark 
914be3200SRob Clark #include <drm/drm_print.h>
10feea39a8SSam Ravnborg #include <drm/drm_vblank.h>
1114be3200SRob Clark 
1214be3200SRob Clark #include "msm_drv.h"
1314be3200SRob Clark #include "mdp5_kms.h"
1414be3200SRob Clark 
mdp5_set_irqmask(struct mdp_kms * mdp_kms,uint32_t irqmask,uint32_t old_irqmask)1514be3200SRob Clark void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
1614be3200SRob Clark 		uint32_t old_irqmask)
1714be3200SRob Clark {
1814be3200SRob Clark 	mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_INTR_CLEAR,
1914be3200SRob Clark 		   irqmask ^ (irqmask & old_irqmask));
2014be3200SRob Clark 	mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_INTR_EN, irqmask);
2114be3200SRob Clark }
2214be3200SRob Clark 
mdp5_irq_error_handler(struct mdp_irq * irq,uint32_t irqstatus)2314be3200SRob Clark static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
2414be3200SRob Clark {
2514be3200SRob Clark 	struct mdp5_kms *mdp5_kms = container_of(irq, struct mdp5_kms, error_handler);
2614be3200SRob Clark 	static DEFINE_RATELIMIT_STATE(rs, 5*HZ, 1);
2714be3200SRob Clark 	extern bool dumpstate;
2814be3200SRob Clark 
2914be3200SRob Clark 	DRM_ERROR_RATELIMITED("errors: %08x\n", irqstatus);
3014be3200SRob Clark 
3114be3200SRob Clark 	if (dumpstate && __ratelimit(&rs)) {
3214be3200SRob Clark 		struct drm_printer p = drm_info_printer(mdp5_kms->dev->dev);
3314be3200SRob Clark 		drm_state_dump(mdp5_kms->dev, &p);
3414be3200SRob Clark 		if (mdp5_kms->smp)
3514be3200SRob Clark 			mdp5_smp_dump(mdp5_kms->smp, &p);
3614be3200SRob Clark 	}
3714be3200SRob Clark }
3814be3200SRob Clark 
mdp5_irq_preinstall(struct msm_kms * kms)3914be3200SRob Clark void mdp5_irq_preinstall(struct msm_kms *kms)
4014be3200SRob Clark {
4114be3200SRob Clark 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
4214be3200SRob Clark 	struct device *dev = &mdp5_kms->pdev->dev;
4314be3200SRob Clark 
4414be3200SRob Clark 	pm_runtime_get_sync(dev);
4514be3200SRob Clark 	mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff);
4614be3200SRob Clark 	mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
4714be3200SRob Clark 	pm_runtime_put_sync(dev);
4814be3200SRob Clark }
4914be3200SRob Clark 
mdp5_irq_postinstall(struct msm_kms * kms)5014be3200SRob Clark int mdp5_irq_postinstall(struct msm_kms *kms)
5114be3200SRob Clark {
5214be3200SRob Clark 	struct mdp_kms *mdp_kms = to_mdp_kms(kms);
5314be3200SRob Clark 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
5414be3200SRob Clark 	struct device *dev = &mdp5_kms->pdev->dev;
5514be3200SRob Clark 	struct mdp_irq *error_handler = &mdp5_kms->error_handler;
5614be3200SRob Clark 
5714be3200SRob Clark 	error_handler->irq = mdp5_irq_error_handler;
5814be3200SRob Clark 	error_handler->irqmask = MDP5_IRQ_INTF0_UNDER_RUN |
5914be3200SRob Clark 			MDP5_IRQ_INTF1_UNDER_RUN |
6014be3200SRob Clark 			MDP5_IRQ_INTF2_UNDER_RUN |
6114be3200SRob Clark 			MDP5_IRQ_INTF3_UNDER_RUN;
6214be3200SRob Clark 
6314be3200SRob Clark 	pm_runtime_get_sync(dev);
6414be3200SRob Clark 	mdp_irq_register(mdp_kms, error_handler);
6514be3200SRob Clark 	pm_runtime_put_sync(dev);
6614be3200SRob Clark 
6714be3200SRob Clark 	return 0;
6814be3200SRob Clark }
6914be3200SRob Clark 
mdp5_irq_uninstall(struct msm_kms * kms)7014be3200SRob Clark void mdp5_irq_uninstall(struct msm_kms *kms)
7114be3200SRob Clark {
7214be3200SRob Clark 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
7314be3200SRob Clark 	struct device *dev = &mdp5_kms->pdev->dev;
7414be3200SRob Clark 
7514be3200SRob Clark 	pm_runtime_get_sync(dev);
7614be3200SRob Clark 	mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
7714be3200SRob Clark 	pm_runtime_put_sync(dev);
7814be3200SRob Clark }
7914be3200SRob Clark 
mdp5_irq(struct msm_kms * kms)8014be3200SRob Clark irqreturn_t mdp5_irq(struct msm_kms *kms)
8114be3200SRob Clark {
8214be3200SRob Clark 	struct mdp_kms *mdp_kms = to_mdp_kms(kms);
8314be3200SRob Clark 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
8414be3200SRob Clark 	struct drm_device *dev = mdp5_kms->dev;
85*e96c08e9SDmitry Baryshkov 	struct drm_crtc *crtc;
8614be3200SRob Clark 	uint32_t status, enable;
8714be3200SRob Clark 
8814be3200SRob Clark 	enable = mdp5_read(mdp5_kms, REG_MDP5_INTR_EN);
8914be3200SRob Clark 	status = mdp5_read(mdp5_kms, REG_MDP5_INTR_STATUS) & enable;
9014be3200SRob Clark 	mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, status);
9114be3200SRob Clark 
9214be3200SRob Clark 	VERB("status=%08x", status);
9314be3200SRob Clark 
9414be3200SRob Clark 	mdp_dispatch_irqs(mdp_kms, status);
9514be3200SRob Clark 
96*e96c08e9SDmitry Baryshkov 	drm_for_each_crtc(crtc, dev)
97*e96c08e9SDmitry Baryshkov 		if (status & mdp5_crtc_vblank(crtc))
98*e96c08e9SDmitry Baryshkov 			drm_crtc_handle_vblank(crtc);
9914be3200SRob Clark 
10014be3200SRob Clark 	return IRQ_HANDLED;
10114be3200SRob Clark }
10214be3200SRob Clark 
mdp5_enable_vblank(struct msm_kms * kms,struct drm_crtc * crtc)10314be3200SRob Clark int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
10414be3200SRob Clark {
10514be3200SRob Clark 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
10614be3200SRob Clark 	struct device *dev = &mdp5_kms->pdev->dev;
10714be3200SRob Clark 
10814be3200SRob Clark 	pm_runtime_get_sync(dev);
10914be3200SRob Clark 	mdp_update_vblank_mask(to_mdp_kms(kms),
11014be3200SRob Clark 			mdp5_crtc_vblank(crtc), true);
11114be3200SRob Clark 	pm_runtime_put_sync(dev);
11214be3200SRob Clark 
11314be3200SRob Clark 	return 0;
11414be3200SRob Clark }
11514be3200SRob Clark 
mdp5_disable_vblank(struct msm_kms * kms,struct drm_crtc * crtc)11614be3200SRob Clark void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
11714be3200SRob Clark {
11814be3200SRob Clark 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
11914be3200SRob Clark 	struct device *dev = &mdp5_kms->pdev->dev;
12014be3200SRob Clark 
12114be3200SRob Clark 	pm_runtime_get_sync(dev);
12214be3200SRob Clark 	mdp_update_vblank_mask(to_mdp_kms(kms),
12314be3200SRob Clark 			mdp5_crtc_vblank(crtc), false);
12414be3200SRob Clark 	pm_runtime_put_sync(dev);
12514be3200SRob Clark }
126