drivers/gpu/host1x/hw/channel_hw.c

Source file repositories/reference/linux-study-clean/drivers/gpu/host1x/hw/channel_hw.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/host1x/hw/channel_hw.c
Extension
.c
Size
9975 bytes
Lines
390
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

if (cmd->is_wait) {
			if (cmd->wait.relative)
				threshold = job_syncpt_base + cmd->wait.threshold;
			else
				threshold = cmd->wait.threshold;

			submit_wait(job, cmd->wait.id, threshold);
			submit_setclass(job, cmd->wait.next_class);
		} else {
			struct host1x_job_gather *g = &cmd->gather;

			dma_addr_t addr = g->base + g->offset;
			u32 op2, op3;

			op2 = lower_32_bits(addr);
			op3 = upper_32_bits(addr);

			trace_write_gather(cdma, g->bo, g->offset, g->words);

			if (op3 != 0) {
#if HOST1X_HW >= 6
				u32 op1 = host1x_opcode_gather_wide(g->words);
				u32 op4 = HOST1X_OPCODE_NOP;

				host1x_cdma_push_wide(cdma, op1, op2, op3, op4);
#else
				dev_err(dev, "invalid gather for push buffer %pad\n",
					&addr);
				continue;
#endif
			} else {
				u32 op1 = host1x_opcode_gather(g->words);

				host1x_cdma_push(cdma, op1, op2);
			}
		}
	}
}

static inline void synchronize_syncpt_base(struct host1x_job *job)
{
	struct host1x_syncpt *sp = job->syncpt;
	unsigned int id;
	u32 value;

	value = host1x_syncpt_read_max(sp);
	id = sp->base->id;

	host1x_cdma_push(&job->channel->cdma,
			 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
				HOST1X_UCLASS_LOAD_SYNCPT_BASE, 1),
			 HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(id) |
			 HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(value));
}

static void host1x_channel_set_streamid(struct host1x_channel *channel)
{
#if HOST1X_HW >= 6
	u32 stream_id;

	if (!tegra_dev_iommu_get_stream_id(channel->dev->parent, &stream_id))
		stream_id = TEGRA_STREAM_ID_BYPASS;

	host1x_ch_writel(channel, stream_id, HOST1X_CHANNEL_SMMU_STREAMID);
#endif
}

static void host1x_enable_gather_filter(struct host1x_channel *ch)
{
#if HOST1X_HW >= 6
	struct host1x *host = dev_get_drvdata(ch->dev->parent);
	u32 val;

	if (!host->hv_regs)
		return;

	val = host1x_hypervisor_readl(
		host, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32));
	val |= BIT(ch->id % 32);
	host1x_hypervisor_writel(
		host, val, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32));
#elif HOST1X_HW >= 4
	host1x_ch_writel(ch,
			 HOST1X_CHANNEL_CHANNELCTRL_KERNEL_FILTER_GBUFFER(1),
			 HOST1X_CHANNEL_CHANNELCTRL);
#endif
}

static void channel_program_cdma(struct host1x_job *job)
{

Annotation

Implementation Notes