132a1795fSJyri Sarha // SPDX-License-Identifier: GPL-2.0
232a1795fSJyri Sarha /*
39410113fSAlexander A. Klimov * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
432a1795fSJyri Sarha * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
532a1795fSJyri Sarha */
632a1795fSJyri Sarha
7*5518572dSThomas Zimmermann #include <linux/platform_device.h>
8*5518572dSThomas Zimmermann
9*5518572dSThomas Zimmermann #include <drm/drm_drv.h>
1032a1795fSJyri Sarha #include <drm/drm_print.h>
1132a1795fSJyri Sarha
1232a1795fSJyri Sarha #include "tidss_crtc.h"
1332a1795fSJyri Sarha #include "tidss_dispc.h"
1432a1795fSJyri Sarha #include "tidss_drv.h"
1532a1795fSJyri Sarha #include "tidss_irq.h"
1632a1795fSJyri Sarha #include "tidss_plane.h"
1732a1795fSJyri Sarha
1832a1795fSJyri Sarha /* call with wait_lock and dispc runtime held */
tidss_irq_update(struct tidss_device * tidss)1932a1795fSJyri Sarha static void tidss_irq_update(struct tidss_device *tidss)
2032a1795fSJyri Sarha {
2132a1795fSJyri Sarha assert_spin_locked(&tidss->wait_lock);
2232a1795fSJyri Sarha
2332a1795fSJyri Sarha dispc_set_irqenable(tidss->dispc, tidss->irq_mask);
2432a1795fSJyri Sarha }
2532a1795fSJyri Sarha
tidss_irq_enable_vblank(struct drm_crtc * crtc)2632a1795fSJyri Sarha void tidss_irq_enable_vblank(struct drm_crtc *crtc)
2732a1795fSJyri Sarha {
2832a1795fSJyri Sarha struct drm_device *ddev = crtc->dev;
2902bb1317SDaniel Vetter struct tidss_device *tidss = to_tidss(ddev);
3032a1795fSJyri Sarha struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
3132a1795fSJyri Sarha u32 hw_videoport = tcrtc->hw_videoport;
3232a1795fSJyri Sarha unsigned long flags;
3332a1795fSJyri Sarha
3432a1795fSJyri Sarha spin_lock_irqsave(&tidss->wait_lock, flags);
3532a1795fSJyri Sarha tidss->irq_mask |= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
3632a1795fSJyri Sarha DSS_IRQ_VP_VSYNC_ODD(hw_videoport);
3732a1795fSJyri Sarha tidss_irq_update(tidss);
3832a1795fSJyri Sarha spin_unlock_irqrestore(&tidss->wait_lock, flags);
3932a1795fSJyri Sarha }
4032a1795fSJyri Sarha
tidss_irq_disable_vblank(struct drm_crtc * crtc)4132a1795fSJyri Sarha void tidss_irq_disable_vblank(struct drm_crtc *crtc)
4232a1795fSJyri Sarha {
4332a1795fSJyri Sarha struct drm_device *ddev = crtc->dev;
4402bb1317SDaniel Vetter struct tidss_device *tidss = to_tidss(ddev);
4532a1795fSJyri Sarha struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
4632a1795fSJyri Sarha u32 hw_videoport = tcrtc->hw_videoport;
4732a1795fSJyri Sarha unsigned long flags;
4832a1795fSJyri Sarha
4932a1795fSJyri Sarha spin_lock_irqsave(&tidss->wait_lock, flags);
5032a1795fSJyri Sarha tidss->irq_mask &= ~(DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
5132a1795fSJyri Sarha DSS_IRQ_VP_VSYNC_ODD(hw_videoport));
5232a1795fSJyri Sarha tidss_irq_update(tidss);
5332a1795fSJyri Sarha spin_unlock_irqrestore(&tidss->wait_lock, flags);
5432a1795fSJyri Sarha }
5532a1795fSJyri Sarha
tidss_irq_handler(int irq,void * arg)56*5518572dSThomas Zimmermann static irqreturn_t tidss_irq_handler(int irq, void *arg)
5732a1795fSJyri Sarha {
5832a1795fSJyri Sarha struct drm_device *ddev = (struct drm_device *)arg;
5902bb1317SDaniel Vetter struct tidss_device *tidss = to_tidss(ddev);
6032a1795fSJyri Sarha unsigned int id;
6132a1795fSJyri Sarha dispc_irq_t irqstatus;
6232a1795fSJyri Sarha
6332a1795fSJyri Sarha irqstatus = dispc_read_and_clear_irqstatus(tidss->dispc);
6432a1795fSJyri Sarha
6532a1795fSJyri Sarha for (id = 0; id < tidss->num_crtcs; id++) {
6632a1795fSJyri Sarha struct drm_crtc *crtc = tidss->crtcs[id];
6732a1795fSJyri Sarha struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
6832a1795fSJyri Sarha u32 hw_videoport = tcrtc->hw_videoport;
6932a1795fSJyri Sarha
7032a1795fSJyri Sarha if (irqstatus & (DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
7132a1795fSJyri Sarha DSS_IRQ_VP_VSYNC_ODD(hw_videoport)))
7232a1795fSJyri Sarha tidss_crtc_vblank_irq(crtc);
7332a1795fSJyri Sarha
7432a1795fSJyri Sarha if (irqstatus & (DSS_IRQ_VP_FRAME_DONE(hw_videoport)))
7532a1795fSJyri Sarha tidss_crtc_framedone_irq(crtc);
7632a1795fSJyri Sarha
7732a1795fSJyri Sarha if (irqstatus & DSS_IRQ_VP_SYNC_LOST(hw_videoport))
7832a1795fSJyri Sarha tidss_crtc_error_irq(crtc, irqstatus);
7932a1795fSJyri Sarha }
8032a1795fSJyri Sarha
8132a1795fSJyri Sarha if (irqstatus & DSS_IRQ_DEVICE_OCP_ERR)
8232a1795fSJyri Sarha dev_err_ratelimited(tidss->dev, "OCP error\n");
8332a1795fSJyri Sarha
8432a1795fSJyri Sarha return IRQ_HANDLED;
8532a1795fSJyri Sarha }
8632a1795fSJyri Sarha
tidss_irq_resume(struct tidss_device * tidss)8732a1795fSJyri Sarha void tidss_irq_resume(struct tidss_device *tidss)
8832a1795fSJyri Sarha {
8932a1795fSJyri Sarha unsigned long flags;
9032a1795fSJyri Sarha
9132a1795fSJyri Sarha spin_lock_irqsave(&tidss->wait_lock, flags);
9232a1795fSJyri Sarha tidss_irq_update(tidss);
9332a1795fSJyri Sarha spin_unlock_irqrestore(&tidss->wait_lock, flags);
9432a1795fSJyri Sarha }
9532a1795fSJyri Sarha
tidss_irq_preinstall(struct drm_device * ddev)96*5518572dSThomas Zimmermann static void tidss_irq_preinstall(struct drm_device *ddev)
9732a1795fSJyri Sarha {
9802bb1317SDaniel Vetter struct tidss_device *tidss = to_tidss(ddev);
9932a1795fSJyri Sarha
10032a1795fSJyri Sarha spin_lock_init(&tidss->wait_lock);
10132a1795fSJyri Sarha
10232a1795fSJyri Sarha tidss_runtime_get(tidss);
10332a1795fSJyri Sarha
10432a1795fSJyri Sarha dispc_set_irqenable(tidss->dispc, 0);
10532a1795fSJyri Sarha dispc_read_and_clear_irqstatus(tidss->dispc);
10632a1795fSJyri Sarha
10732a1795fSJyri Sarha tidss_runtime_put(tidss);
10832a1795fSJyri Sarha }
10932a1795fSJyri Sarha
tidss_irq_postinstall(struct drm_device * ddev)110*5518572dSThomas Zimmermann static void tidss_irq_postinstall(struct drm_device *ddev)
11132a1795fSJyri Sarha {
11202bb1317SDaniel Vetter struct tidss_device *tidss = to_tidss(ddev);
11332a1795fSJyri Sarha unsigned long flags;
11432a1795fSJyri Sarha unsigned int i;
11532a1795fSJyri Sarha
11632a1795fSJyri Sarha tidss_runtime_get(tidss);
11732a1795fSJyri Sarha
11832a1795fSJyri Sarha spin_lock_irqsave(&tidss->wait_lock, flags);
11932a1795fSJyri Sarha
12032a1795fSJyri Sarha tidss->irq_mask = DSS_IRQ_DEVICE_OCP_ERR;
12132a1795fSJyri Sarha
12232a1795fSJyri Sarha for (i = 0; i < tidss->num_crtcs; ++i) {
12332a1795fSJyri Sarha struct tidss_crtc *tcrtc = to_tidss_crtc(tidss->crtcs[i]);
12432a1795fSJyri Sarha
12532a1795fSJyri Sarha tidss->irq_mask |= DSS_IRQ_VP_SYNC_LOST(tcrtc->hw_videoport);
12632a1795fSJyri Sarha
12732a1795fSJyri Sarha tidss->irq_mask |= DSS_IRQ_VP_FRAME_DONE(tcrtc->hw_videoport);
12832a1795fSJyri Sarha }
12932a1795fSJyri Sarha
13032a1795fSJyri Sarha tidss_irq_update(tidss);
13132a1795fSJyri Sarha
13232a1795fSJyri Sarha spin_unlock_irqrestore(&tidss->wait_lock, flags);
13332a1795fSJyri Sarha
13432a1795fSJyri Sarha tidss_runtime_put(tidss);
135*5518572dSThomas Zimmermann }
136*5518572dSThomas Zimmermann
tidss_irq_install(struct drm_device * ddev,unsigned int irq)137*5518572dSThomas Zimmermann int tidss_irq_install(struct drm_device *ddev, unsigned int irq)
138*5518572dSThomas Zimmermann {
139*5518572dSThomas Zimmermann int ret;
140*5518572dSThomas Zimmermann
141*5518572dSThomas Zimmermann if (irq == IRQ_NOTCONNECTED)
142*5518572dSThomas Zimmermann return -ENOTCONN;
143*5518572dSThomas Zimmermann
144*5518572dSThomas Zimmermann tidss_irq_preinstall(ddev);
145*5518572dSThomas Zimmermann
146*5518572dSThomas Zimmermann ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev);
147*5518572dSThomas Zimmermann if (ret)
148*5518572dSThomas Zimmermann return ret;
149*5518572dSThomas Zimmermann
150*5518572dSThomas Zimmermann tidss_irq_postinstall(ddev);
15132a1795fSJyri Sarha
15232a1795fSJyri Sarha return 0;
15332a1795fSJyri Sarha }
15432a1795fSJyri Sarha
tidss_irq_uninstall(struct drm_device * ddev)15532a1795fSJyri Sarha void tidss_irq_uninstall(struct drm_device *ddev)
15632a1795fSJyri Sarha {
15702bb1317SDaniel Vetter struct tidss_device *tidss = to_tidss(ddev);
15832a1795fSJyri Sarha
15932a1795fSJyri Sarha tidss_runtime_get(tidss);
16032a1795fSJyri Sarha dispc_set_irqenable(tidss->dispc, 0);
16132a1795fSJyri Sarha tidss_runtime_put(tidss);
162*5518572dSThomas Zimmermann
163*5518572dSThomas Zimmermann free_irq(tidss->irq, ddev);
16432a1795fSJyri Sarha }
165