Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
Note: File does not exist in v3.1.
  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	struct drm_pending_vblank_event *event = crtc->state->event;
 55
 56	DRM_DEBUG_DRIVER("Committing plane changes\n");
 57
 58	sun4i_backend_commit(drv->backend);
 59
 60	if (event) {
 61		crtc->state->event = NULL;
 62
 63		spin_lock_irq(&crtc->dev->event_lock);
 64		if (drm_crtc_vblank_get(crtc) == 0)
 65			drm_crtc_arm_vblank_event(crtc, event);
 66		else
 67			drm_crtc_send_vblank_event(crtc, event);
 68		spin_unlock_irq(&crtc->dev->event_lock);
 69	}
 70}
 71
 72static void sun4i_crtc_disable(struct drm_crtc *crtc)
 73{
 74	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 75	struct sun4i_drv *drv = scrtc->drv;
 76
 77	DRM_DEBUG_DRIVER("Disabling the CRTC\n");
 78
 79	sun4i_tcon_disable(drv->tcon);
 80
 81	if (crtc->state->event && !crtc->state->active) {
 82		spin_lock_irq(&crtc->dev->event_lock);
 83		drm_crtc_send_vblank_event(crtc, crtc->state->event);
 84		spin_unlock_irq(&crtc->dev->event_lock);
 85
 86		crtc->state->event = NULL;
 87	}
 88}
 89
 90static void sun4i_crtc_enable(struct drm_crtc *crtc)
 91{
 92	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 93	struct sun4i_drv *drv = scrtc->drv;
 94
 95	DRM_DEBUG_DRIVER("Enabling the CRTC\n");
 96
 97	sun4i_tcon_enable(drv->tcon);
 98}
 99
100static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
101	.atomic_begin	= sun4i_crtc_atomic_begin,
102	.atomic_flush	= sun4i_crtc_atomic_flush,
103	.disable	= sun4i_crtc_disable,
104	.enable		= sun4i_crtc_enable,
105};
106
107static const struct drm_crtc_funcs sun4i_crtc_funcs = {
108	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
109	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
110	.destroy		= drm_crtc_cleanup,
111	.page_flip		= drm_atomic_helper_page_flip,
112	.reset			= drm_atomic_helper_crtc_reset,
113	.set_config		= drm_atomic_helper_set_config,
114};
115
116struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm)
117{
118	struct sun4i_drv *drv = drm->dev_private;
119	struct sun4i_crtc *scrtc;
120	int ret;
121
122	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
123	if (!scrtc)
124		return NULL;
125	scrtc->drv = drv;
126
127	ret = drm_crtc_init_with_planes(drm, &scrtc->crtc,
128					drv->primary,
129					NULL,
130					&sun4i_crtc_funcs,
131					NULL);
132	if (ret) {
133		dev_err(drm->dev, "Couldn't init DRM CRTC\n");
134		return NULL;
135	}
136
137	drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs);
138
139	return scrtc;
140}