Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/sti/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  sti_compositor.c   Sprache: 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/of.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},
 },
};

void 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);
}

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);

 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;
 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));
 compo->regs = devm_platform_ioremap_resource(pdev, 0);
 if (IS_ERR(compo->regs)) {
  DRM_ERROR("Register mapping failed\n");
  return PTR_ERR(compo->regs);
 }

 /* 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 void sti_compositor_remove(struct platform_device *pdev)
{
 component_del(&pdev->dev, &sti_compositor_ops);
}

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 ");
MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
MODULE_LICENSE("GPL");

Messung V0.5
C=96 H=90 G=93

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.