drivers/gpu/drm/sprd/sprd_dsi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/sprd/sprd_dsi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/sprd/sprd_dsi.c
Extension
.c
Size
27519 bytes
Lines
1067
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 ((hs_to % div) == 0) {
			writel(div, ctx->base + TIMEOUT_CNT_CLK_CONFIG);
			writel(hs_to / div, ctx->base + LRX_H_TO_CONFIG);
			writel(hs_to / div, ctx->base + HTX_TO_CONFIG);
			break;
		}
	}

	if (ctx->burst_mode == VIDEO_BURST_WITH_SYNC_PULSES) {
		dsi_reg_wr(ctx, VIDEO_PKT_CONFIG, VIDEO_PKT_SIZE, 0, video_size);
		writel(0, ctx->base + VIDEO_NULLPKT_SIZE);
		dsi_reg_up(ctx, VIDEO_PKT_CONFIG, VIDEO_LINE_CHUNK_NUM, 0);
	} else {
		/* non burst transmission */
		null_pkt_size = 0;

		/* bytes to be sent - first as one chunk */
		bytes_per_chunk = vm->hactive * bpp_x100 / 100 + pkt_header;

		/* hline total bytes from the DPI interface */
		total_bytes = (vm->hactive + vm->hfront_porch) *
				ratio_x1000 / dsi->slave->lanes / 1000;

		/* check if the pixels actually fit on the DSI link */
		if (total_bytes < bytes_per_chunk) {
			drm_err(dsi->drm, "current resolution can not be set\n");
			return -EINVAL;
		}

		chunk_overhead = total_bytes - bytes_per_chunk;

		/* overhead higher than 1 -> enable multi packets */
		if (chunk_overhead > 1) {
			/* multi packets */
			for (video_size = video_size_step;
			     video_size < vm->hactive;
			     video_size += video_size_step) {
				if (vm->hactive * 1000 / video_size % 1000)
					continue;

				chunks = vm->hactive / video_size;
				bytes_per_chunk = bpp_x100 * video_size / 100
						  + pkt_header;
				if (total_bytes >= (bytes_per_chunk * chunks)) {
					bytes_left = total_bytes -
						     bytes_per_chunk * chunks;
					break;
				}
			}

			/* prevent overflow (unsigned - unsigned) */
			if (bytes_left > (pkt_header * chunks)) {
				null_pkt_size = (bytes_left -
						pkt_header * chunks) / chunks;
				/* avoid register overflow */
				if (null_pkt_size > 1023)
					null_pkt_size = 1023;
			}

		} else {
			/* single packet */
			chunks = 1;

			/* must be a multiple of 4 except 18 loosely */
			for (video_size = vm->hactive;
			    (video_size % video_size_step) != 0;
			     video_size++)
				;
		}

		dsi_reg_wr(ctx, VIDEO_PKT_CONFIG, VIDEO_PKT_SIZE, 0, video_size);
		writel(null_pkt_size, ctx->base + VIDEO_NULLPKT_SIZE);
		dsi_reg_wr(ctx, VIDEO_PKT_CONFIG, VIDEO_LINE_CHUNK_NUM, 16, chunks);
	}

	writel(ctx->int0_mask, ctx->base + MASK_PROTOCOL_INT);
	writel(ctx->int1_mask, ctx->base + MASK_INTERNAL_INT);
	writel(1, ctx->base + SOFT_RESET);

	return 0;
}

static void sprd_dsi_edpi_video(struct dsi_context *ctx)
{
	struct sprd_dsi *dsi = container_of(ctx, struct sprd_dsi, ctx);
	const u32 fifo_depth = 1096;
	const u32 word_length = 4;
	u32 hactive = ctx->vm.hactive;
	u32 bpp_x100;
	u32 max_fifo_len;

Annotation

Implementation Notes