drivers/staging/sm750fb/ddk750_display.c

Source file repositories/reference/linux-study-clean/drivers/staging/sm750fb/ddk750_display.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/sm750fb/ddk750_display.c
Extension
.c
Size
4198 bytes
Lines
159
Domain
Driver Families
Bucket
drivers/staging
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

// SPDX-License-Identifier: GPL-2.0
#include "ddk750_reg.h"
#include "ddk750_chip.h"
#include "ddk750_display.h"
#include "ddk750_power.h"

static void set_display_control(int ctrl, int disp_state)
{
	/* state != 0 means turn on both timing & plane en_bit */
	unsigned long reg, val, reserved;
	int cnt = 0;

	if (!ctrl) {
		reg = PANEL_DISPLAY_CTRL;
		reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK;
	} else {
		reg = CRT_DISPLAY_CTRL;
		reserved = CRT_DISPLAY_CTRL_RESERVED_MASK;
	}

	val = peek32(reg);
	if (disp_state) {
		/*
		 * Timing should be enabled first before enabling the
		 * plane because changing at the same time does not
		 * guarantee that the plane will also enabled or
		 * disabled.
		 */
		val |= DISPLAY_CTRL_TIMING;
		poke32(reg, val);

		val |= DISPLAY_CTRL_PLANE;

		/*
		 * Somehow the register value on the plane is not set
		 * until a few delay. Need to write and read it a
		 * couple times
		 */
		do {
			cnt++;
			poke32(reg, val);
		} while ((peek32(reg) & ~reserved) != (val & ~reserved));
		pr_debug("Set Plane enbit:after tried %d times\n", cnt);
	} else {
		/*
		 * When turning off, there is no rule on the
		 * programming sequence since whenever the clock is
		 * off, then it does not matter whether the plane is
		 * enabled or disabled.  Note: Modifying the plane bit
		 * will take effect on the next vertical sync. Need to
		 * find out if it is necessary to wait for 1 vsync
		 * before modifying the timing enable bit.
		 */
		val &= ~DISPLAY_CTRL_PLANE;
		poke32(reg, val);

		val &= ~DISPLAY_CTRL_TIMING;
		poke32(reg, val);
	}
}

static void primary_wait_vertical_sync(int delay)
{
	unsigned int status;

	/*
	 * Do not wait when the Primary PLL is off or display control is
	 * already off. This will prevent the software to wait forever.
	 */
	if (!(peek32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) ||
	    !(peek32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING))
		return;

	while (delay-- > 0) {
		/* Wait for end of vsync. */
		do {
			status = peek32(SYSTEM_CTRL);
		} while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);

		/* Wait for start of vsync. */
		do {
			status = peek32(SYSTEM_CTRL);
		} while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
	}
}

static void sw_panel_power_sequence(int disp, int delay)
{
	unsigned int reg;

Annotation

Implementation Notes