drivers/gpu/drm/tegra/gr3d.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/tegra/gr3d.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/tegra/gr3d.c
Extension
.c
Size
14559 bytes
Lines
616
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

struct gr3d_soc {
	unsigned int version;
	unsigned int num_clocks;
	unsigned int num_resets;
};

struct gr3d {
	struct tegra_drm_client client;
	struct host1x_channel *channel;

	const struct gr3d_soc *soc;
	struct clk_bulk_data *clocks;
	unsigned int nclocks;
	struct reset_control_bulk_data resets[RST_GR3D_MAX];
	unsigned int nresets;
	struct tegra_pmc *pmc;
	struct dev_pm_domain_list *pd_list;

	DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
};

static inline struct gr3d *to_gr3d(struct tegra_drm_client *client)
{
	return container_of(client, struct gr3d, client);
}

static int gr3d_init(struct host1x_client *client)
{
	struct tegra_drm_client *drm = host1x_to_drm_client(client);
	struct drm_device *dev = dev_get_drvdata(client->host);
	unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
	struct gr3d *gr3d = to_gr3d(drm);
	int err;

	gr3d->channel = host1x_channel_request(client);
	if (!gr3d->channel)
		return -ENOMEM;

	client->syncpts[0] = host1x_syncpt_request(client, flags);
	if (!client->syncpts[0]) {
		err = -ENOMEM;
		dev_err(client->dev, "failed to request syncpoint: %d\n", err);
		goto put;
	}

	err = host1x_client_iommu_attach(client);
	if (err < 0) {
		dev_err(client->dev, "failed to attach to domain: %d\n", err);
		goto free;
	}

	err = tegra_drm_register_client(dev->dev_private, drm);
	if (err < 0) {
		dev_err(client->dev, "failed to register client: %d\n", err);
		goto detach_iommu;
	}

	return 0;

detach_iommu:
	host1x_client_iommu_detach(client);
free:
	host1x_syncpt_put(client->syncpts[0]);
put:
	host1x_channel_put(gr3d->channel);
	return err;
}

static int gr3d_exit(struct host1x_client *client)
{
	struct tegra_drm_client *drm = host1x_to_drm_client(client);
	struct drm_device *dev = dev_get_drvdata(client->host);
	struct gr3d *gr3d = to_gr3d(drm);
	int err;

	err = tegra_drm_unregister_client(dev->dev_private, drm);
	if (err < 0)
		return err;

	host1x_client_iommu_detach(client);
	host1x_syncpt_put(client->syncpts[0]);
	host1x_channel_put(gr3d->channel);

	gr3d->channel = NULL;

	return 0;
}

static const struct host1x_client_ops gr3d_client_ops = {
	.init = gr3d_init,

Annotation

Implementation Notes