drivers/auxdisplay/charlcd.c

Source file repositories/reference/linux-study-clean/drivers/auxdisplay/charlcd.c

File Facts

System
Linux kernel
Corpus path
drivers/auxdisplay/charlcd.c
Extension
.c
Size
15657 bytes
Lines
685
Domain
Driver Families
Bucket
drivers/auxdisplay
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations charlcd_fops = {
	.write   = charlcd_write,
	.open    = charlcd_open,
	.release = charlcd_release,
};

static struct miscdevice charlcd_dev = {
	.minor	= LCD_MINOR,
	.name	= "lcd",
	.fops	= &charlcd_fops,
};

static void charlcd_puts(struct charlcd *lcd, const char *s)
{
	const char *tmp = s;
	int count = strlen(s);

	for (; count-- > 0; tmp++) {
		if (((count + 1) & 0x1f) == 0)
			cond_resched();

		charlcd_write_char(lcd, *tmp);
	}
}

#ifdef CONFIG_PANEL_BOOT_MESSAGE
#define LCD_INIT_TEXT CONFIG_PANEL_BOOT_MESSAGE
#else
#define LCD_INIT_TEXT "Linux-" UTS_RELEASE "\n"
#endif

#ifdef CONFIG_CHARLCD_BL_ON
#define LCD_INIT_BL "\x1b[L+"
#elif defined(CONFIG_CHARLCD_BL_FLASH)
#define LCD_INIT_BL "\x1b[L*"
#else
#define LCD_INIT_BL "\x1b[L-"
#endif

/* initialize the LCD driver */
static int charlcd_init(struct charlcd *lcd)
{
	struct charlcd_priv *priv = charlcd_to_priv(lcd);
	int ret;

	priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
		      LCD_FLAG_C | LCD_FLAG_B;
	if (lcd->ops->backlight) {
		mutex_init(&priv->bl_tempo_lock);
		INIT_DELAYED_WORK(&priv->bl_work, charlcd_bl_off);
	}

	/*
	 * before this line, we must NOT send anything to the display.
	 * Since charlcd_init_display() needs to write data, we have to
	 * enable mark the LCD initialized just before.
	 */
	if (WARN_ON(!lcd->ops->init_display))
		return -EINVAL;

	ret = lcd->ops->init_display(lcd);
	if (ret)
		return ret;

	/* display a short message */
	charlcd_puts(lcd, "\x1b[Lc\x1b[Lb" LCD_INIT_BL LCD_INIT_TEXT);

	/* clear the display on the next device opening */
	priv->must_clear = true;
	charlcd_home(lcd);
	return 0;
}

struct charlcd *charlcd_alloc(unsigned int drvdata_size)
{
	struct charlcd_priv *priv;
	struct charlcd *lcd;

	priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL);
	if (!priv)
		return NULL;

	priv->esc_seq.len = -1;

	lcd = &priv->lcd;
	lcd->drvdata = priv->drvdata;

	return lcd;
}
EXPORT_SYMBOL_GPL(charlcd_alloc);

Annotation

Implementation Notes