Merge branches 'acpi-processor', 'acpi-cppc', 'acpi-apei' and 'acpi-sleep'
[linux-2.6-block.git] / drivers / gpu / drm / sun4i / sun4i_crtc.c
CommitLineData
9026e0d1
MR
1/*
2 * Copyright (C) 2015 Free Electrons
3 * Copyright (C) 2015 NextThing Co
4 *
5 * Maxime Ripard <maxime.ripard@free-electrons.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 */
12
13#include <drm/drmP.h>
14#include <drm/drm_atomic_helper.h>
15#include <drm/drm_crtc.h>
16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_modes.h>
18
19#include <linux/clk-provider.h>
20#include <linux/ioport.h>
21#include <linux/of_address.h>
22#include <linux/of_irq.h>
23#include <linux/regmap.h>
24
25#include <video/videomode.h>
26
27#include "sun4i_backend.h"
28#include "sun4i_crtc.h"
29#include "sun4i_drv.h"
30#include "sun4i_tcon.h"
31
32static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
33 struct drm_crtc_state *old_state)
34{
35 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
36 struct drm_device *dev = crtc->dev;
37 unsigned long flags;
38
39 if (crtc->state->event) {
40 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
41
42 spin_lock_irqsave(&dev->event_lock, flags);
43 scrtc->event = crtc->state->event;
44 spin_unlock_irqrestore(&dev->event_lock, flags);
45 crtc->state->event = NULL;
46 }
47}
48
49static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
50 struct drm_crtc_state *old_state)
51{
52 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
53 struct sun4i_drv *drv = scrtc->drv;
54
55 DRM_DEBUG_DRIVER("Committing plane changes\n");
56
57 sun4i_backend_commit(drv->backend);
58}
59
60static void sun4i_crtc_disable(struct drm_crtc *crtc)
61{
62 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
63 struct sun4i_drv *drv = scrtc->drv;
64
65 DRM_DEBUG_DRIVER("Disabling the CRTC\n");
66
67 sun4i_tcon_disable(drv->tcon);
2cd36830
MR
68
69 if (crtc->state->event && !crtc->state->active) {
70 spin_lock_irq(&crtc->dev->event_lock);
71 drm_crtc_send_vblank_event(crtc, crtc->state->event);
72 spin_unlock_irq(&crtc->dev->event_lock);
73
74 crtc->state->event = NULL;
75 }
9026e0d1
MR
76}
77
78static void sun4i_crtc_enable(struct drm_crtc *crtc)
79{
80 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
81 struct sun4i_drv *drv = scrtc->drv;
82
83 DRM_DEBUG_DRIVER("Enabling the CRTC\n");
84
85 sun4i_tcon_enable(drv->tcon);
86}
87
88static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
89 .atomic_begin = sun4i_crtc_atomic_begin,
90 .atomic_flush = sun4i_crtc_atomic_flush,
91 .disable = sun4i_crtc_disable,
92 .enable = sun4i_crtc_enable,
93};
94
95static const struct drm_crtc_funcs sun4i_crtc_funcs = {
96 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
97 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
98 .destroy = drm_crtc_cleanup,
99 .page_flip = drm_atomic_helper_page_flip,
100 .reset = drm_atomic_helper_crtc_reset,
101 .set_config = drm_atomic_helper_set_config,
102};
103
104struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm)
105{
106 struct sun4i_drv *drv = drm->dev_private;
107 struct sun4i_crtc *scrtc;
108 int ret;
109
110 scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
111 if (!scrtc)
112 return NULL;
113 scrtc->drv = drv;
114
115 ret = drm_crtc_init_with_planes(drm, &scrtc->crtc,
116 drv->primary,
117 NULL,
118 &sun4i_crtc_funcs,
119 NULL);
120 if (ret) {
121 dev_err(drm->dev, "Couldn't init DRM CRTC\n");
122 return NULL;
123 }
124
125 drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs);
126
127 return scrtc;
128}