drivers/gpu/drm/tiny/sharp-memory.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/tiny/sharp-memory.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/tiny/sharp-memory.c
Extension
.c
Size
19703 bytes
Lines
670
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 sharp_memory_device {
	struct drm_device drm;
	struct spi_device *spi;

	const struct drm_display_mode *mode;

	struct drm_crtc crtc;
	struct drm_plane plane;
	struct drm_encoder encoder;
	struct drm_connector connector;

	struct gpio_desc *enable_gpio;

	struct task_struct *sw_vcom_signal;
	struct pwm_device *pwm_vcom_signal;

	enum sharp_memory_vcom_mode vcom_mode;
	u8 vcom;

	u32 pitch;
	u32 tx_buffer_size;
	u8 *tx_buffer;

	/* When vcom_mode == "software" a kthread is used to periodically send a
	 * 'maintain display' message over spi. This mutex ensures tx_buffer access
	 * and spi bus usage is synchronized in this case.
	 */
	struct mutex tx_mutex;
};

static inline int sharp_memory_spi_write(struct spi_device *spi, void *buf, size_t len)
{
	/* Reverse the bit order */
	for (u8 *b = buf; b < ((u8 *)buf) + len; ++b)
		*b = bitrev8(*b);

	return spi_write(spi, buf, len);
}

static inline struct sharp_memory_device *drm_to_sharp_memory_device(struct drm_device *drm)
{
	return container_of(drm, struct sharp_memory_device, drm);
}

DEFINE_DRM_GEM_DMA_FOPS(sharp_memory_fops);

static const struct drm_driver sharp_memory_drm_driver = {
	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
	.fops			= &sharp_memory_fops,
	DRM_GEM_DMA_DRIVER_OPS_VMAP,
	DRM_FBDEV_DMA_DRIVER_OPS,
	.name			= "sharp_memory_display",
	.desc			= "Sharp Display Memory LCD",
	.major			= 1,
	.minor			= 0,
};

static inline void sharp_memory_set_tx_buffer_mode(u8 *buffer, u8 mode, u8 vcom)
{
	*buffer = mode | (vcom << 1);
}

static inline void sharp_memory_set_tx_buffer_addresses(u8 *buffer,
							struct drm_rect clip,
							u32 pitch)
{
	for (u32 line = 0; line < clip.y2; ++line)
		buffer[line * pitch] = line + 1;
}

static void sharp_memory_set_tx_buffer_data(u8 *buffer,
					    struct drm_framebuffer *fb,
					    const struct iosys_map *vmap,
					    struct drm_rect clip,
					    u32 pitch,
					    struct drm_format_conv_state *fmtcnv_state)
{
	int ret;
	struct iosys_map dst;

	ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
	if (ret)
		return;

	iosys_map_set_vaddr(&dst, buffer);

	drm_fb_xrgb8888_to_mono(&dst, &pitch, vmap, fb, &clip, fmtcnv_state);

	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
}

Annotation

Implementation Notes