drivers/gpu/drm/mxsfb/lcdif_drv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/mxsfb/lcdif_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/mxsfb/lcdif_drv.c
Extension
.c
Size
9623 bytes
Lines
379
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2022 Marek Vasut <marex@denx.de>
 *
 * This code is based on drivers/gpu/drm/mxsfb/mxsfb*
 */

#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

#include <drm/clients/drm_client_setup.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_drv.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fbdev_dma.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_mode_config.h>
#include <drm/drm_module.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>

#include "lcdif_drv.h"
#include "lcdif_regs.h"

static const struct drm_mode_config_funcs lcdif_mode_config_funcs = {
	.fb_create		= drm_gem_fb_create,
	.atomic_check		= drm_atomic_helper_check,
	.atomic_commit		= drm_atomic_helper_commit,
};

static const struct drm_mode_config_helper_funcs lcdif_mode_config_helpers = {
	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
};

static const struct drm_encoder_funcs lcdif_encoder_funcs = {
	.destroy = drm_encoder_cleanup,
};

static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
{
	struct device *dev = lcdif->drm->dev;
	struct device_node *ep __free(device_node) = NULL;

	for_each_endpoint_of_node(dev->of_node, ep) {
		struct device_node *remote __free(device_node) =
			of_graph_get_remote_port_parent(ep);
		struct of_endpoint of_ep;
		struct drm_bridge *bridge;
		struct drm_encoder *encoder;
		struct drm_connector *connector;
		int ret;

		if (!of_device_is_available(remote))
			continue;

		ret = of_graph_parse_endpoint(ep, &of_ep);
		if (ret < 0)
			return dev_err_probe(dev, ret, "Failed to parse endpoint %pOF\n", ep);

		bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
		if (IS_ERR(bridge))
			return dev_err_probe(dev, PTR_ERR(bridge),
					     "Failed to get bridge for endpoint%u\n",
					     of_ep.id);

		encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
		if (!encoder)
			return dev_err_probe(dev, -ENOMEM,
					     "Failed to allocate encoder for endpoint%u\n",
					     of_ep.id);

		encoder->possible_crtcs = drm_crtc_mask(&lcdif->crtc);
		ret = drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
				       DRM_MODE_ENCODER_NONE, NULL);
		if (ret)
			return dev_err_probe(dev, ret,
					     "Failed to initialize encoder for endpoint%u\n",
					     of_ep.id);

Annotation

Implementation Notes