linux/drivers/gpu/drm/sti/sti_compositor.c
Sam Ravnborg 5e2f97a93f drm/sti: drop use of drmP.h
Stop using the deprecated drmP.h header file.
Replaced with relevant forwards or headers files.
Header files sorted in all files touched.

Build tested with allyesconfig, allmodconfig for a number of
architectures.

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Cc: Vincent Abriou <vincent.abriou@st.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190605134835.25112-2-sam@ravnborg.org
2019-06-06 17:11:26 +02:00

282 lines
7.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) STMicroelectronics SA 2014
* Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
* Fabien Dessenne <fabien.dessenne@st.com>
* for STMicroelectronics.
*/
#include <linux/component.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include "sti_compositor.h"
#include "sti_crtc.h"
#include "sti_cursor.h"
#include "sti_drv.h"
#include "sti_gdp.h"
#include "sti_plane.h"
#include "sti_vid.h"
#include "sti_vtg.h"
/*
* stiH407 compositor properties
*/
static const struct sti_compositor_data stih407_compositor_data = {
.nb_subdev = 8,
.subdev_desc = {
{STI_CURSOR_SUBDEV, (int)STI_CURSOR, 0x000},
{STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100},
{STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200},
{STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300},
{STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400},
{STI_VID_SUBDEV, (int)STI_HQVDP_0, 0x700},
{STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00},
{STI_MIXER_AUX_SUBDEV, STI_MIXER_AUX, 0xD00},
},
};
int sti_compositor_debugfs_init(struct sti_compositor *compo,
struct drm_minor *minor)
{
unsigned int i;
for (i = 0; i < STI_MAX_VID; i++)
if (compo->vid[i])
vid_debugfs_init(compo->vid[i], minor);
for (i = 0; i < STI_MAX_MIXER; i++)
if (compo->mixer[i])
sti_mixer_debugfs_init(compo->mixer[i], minor);
return 0;
}
static int sti_compositor_bind(struct device *dev,
struct device *master,
void *data)
{
struct sti_compositor *compo = dev_get_drvdata(dev);
struct drm_device *drm_dev = data;
unsigned int i, mixer_id = 0, vid_id = 0, crtc_id = 0;
struct sti_private *dev_priv = drm_dev->dev_private;
struct drm_plane *cursor = NULL;
struct drm_plane *primary = NULL;
struct sti_compositor_subdev_descriptor *desc = compo->data.subdev_desc;
unsigned int array_size = compo->data.nb_subdev;
dev_priv->compo = compo;
/* Register mixer subdev and video subdev first */
for (i = 0; i < array_size; i++) {
switch (desc[i].type) {
case STI_VID_SUBDEV:
compo->vid[vid_id++] =
sti_vid_create(compo->dev, drm_dev, desc[i].id,
compo->regs + desc[i].offset);
break;
case STI_MIXER_MAIN_SUBDEV:
case STI_MIXER_AUX_SUBDEV:
compo->mixer[mixer_id++] =
sti_mixer_create(compo->dev, drm_dev, desc[i].id,
compo->regs + desc[i].offset);
break;
case STI_GPD_SUBDEV:
case STI_CURSOR_SUBDEV:
/* Nothing to do, wait for the second round */
break;
default:
DRM_ERROR("Unknown subdev component type\n");
return 1;
}
}
/* Register the other subdevs, create crtc and planes */
for (i = 0; i < array_size; i++) {
enum drm_plane_type plane_type = DRM_PLANE_TYPE_OVERLAY;
if (crtc_id < mixer_id)
plane_type = DRM_PLANE_TYPE_PRIMARY;
switch (desc[i].type) {
case STI_MIXER_MAIN_SUBDEV:
case STI_MIXER_AUX_SUBDEV:
case STI_VID_SUBDEV:
/* Nothing to do, already done at the first round */
break;
case STI_CURSOR_SUBDEV:
cursor = sti_cursor_create(drm_dev, compo->dev,
desc[i].id,
compo->regs + desc[i].offset,
1);
if (!cursor) {
DRM_ERROR("Can't create CURSOR plane\n");
break;
}
break;
case STI_GPD_SUBDEV:
primary = sti_gdp_create(drm_dev, compo->dev,
desc[i].id,
compo->regs + desc[i].offset,
(1 << mixer_id) - 1,
plane_type);
if (!primary) {
DRM_ERROR("Can't create GDP plane\n");
break;
}
break;
default:
DRM_ERROR("Unknown subdev component type\n");
return 1;
}
/* The first planes are reserved for primary planes*/
if (crtc_id < mixer_id && primary) {
sti_crtc_init(drm_dev, compo->mixer[crtc_id],
primary, cursor);
crtc_id++;
cursor = NULL;
primary = NULL;
}
}
drm_vblank_init(drm_dev, crtc_id);
/* Allow usage of vblank without having to call drm_irq_install */
drm_dev->irq_enabled = 1;
return 0;
}
static void sti_compositor_unbind(struct device *dev, struct device *master,
void *data)
{
/* do nothing */
}
static const struct component_ops sti_compositor_ops = {
.bind = sti_compositor_bind,
.unbind = sti_compositor_unbind,
};
static const struct of_device_id compositor_of_match[] = {
{
.compatible = "st,stih407-compositor",
.data = &stih407_compositor_data,
}, {
/* end node */
}
};
MODULE_DEVICE_TABLE(of, compositor_of_match);
static int sti_compositor_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct device_node *vtg_np;
struct sti_compositor *compo;
struct resource *res;
unsigned int i;
compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL);
if (!compo) {
DRM_ERROR("Failed to allocate compositor context\n");
return -ENOMEM;
}
compo->dev = dev;
for (i = 0; i < STI_MAX_MIXER; i++)
compo->vtg_vblank_nb[i].notifier_call = sti_crtc_vblank_cb;
/* populate data structure depending on compatibility */
BUG_ON(!of_match_node(compositor_of_match, np)->data);
memcpy(&compo->data, of_match_node(compositor_of_match, np)->data,
sizeof(struct sti_compositor_data));
/* Get Memory ressources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
DRM_ERROR("Get memory resource failed\n");
return -ENXIO;
}
compo->regs = devm_ioremap(dev, res->start, resource_size(res));
if (compo->regs == NULL) {
DRM_ERROR("Register mapping failed\n");
return -ENXIO;
}
/* Get clock resources */
compo->clk_compo_main = devm_clk_get(dev, "compo_main");
if (IS_ERR(compo->clk_compo_main)) {
DRM_ERROR("Cannot get compo_main clock\n");
return PTR_ERR(compo->clk_compo_main);
}
compo->clk_compo_aux = devm_clk_get(dev, "compo_aux");
if (IS_ERR(compo->clk_compo_aux)) {
DRM_ERROR("Cannot get compo_aux clock\n");
return PTR_ERR(compo->clk_compo_aux);
}
compo->clk_pix_main = devm_clk_get(dev, "pix_main");
if (IS_ERR(compo->clk_pix_main)) {
DRM_ERROR("Cannot get pix_main clock\n");
return PTR_ERR(compo->clk_pix_main);
}
compo->clk_pix_aux = devm_clk_get(dev, "pix_aux");
if (IS_ERR(compo->clk_pix_aux)) {
DRM_ERROR("Cannot get pix_aux clock\n");
return PTR_ERR(compo->clk_pix_aux);
}
/* Get reset resources */
compo->rst_main = devm_reset_control_get_shared(dev, "compo-main");
/* Take compo main out of reset */
if (!IS_ERR(compo->rst_main))
reset_control_deassert(compo->rst_main);
compo->rst_aux = devm_reset_control_get_shared(dev, "compo-aux");
/* Take compo aux out of reset */
if (!IS_ERR(compo->rst_aux))
reset_control_deassert(compo->rst_aux);
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0);
if (vtg_np)
compo->vtg[STI_MIXER_MAIN] = of_vtg_find(vtg_np);
of_node_put(vtg_np);
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1);
if (vtg_np)
compo->vtg[STI_MIXER_AUX] = of_vtg_find(vtg_np);
of_node_put(vtg_np);
platform_set_drvdata(pdev, compo);
return component_add(&pdev->dev, &sti_compositor_ops);
}
static int sti_compositor_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &sti_compositor_ops);
return 0;
}
struct platform_driver sti_compositor_driver = {
.driver = {
.name = "sti-compositor",
.of_match_table = compositor_of_match,
},
.probe = sti_compositor_probe,
.remove = sti_compositor_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");