drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.c
Extension
.c
Size
6533 bytes
Lines
207
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

#include <drm/drm_mipi_dsi.h>
#include <drm/drm_print.h>
#include <video/mipi_display.h>

#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dsi.h"
#include "intel_dsi_dcs_backlight.h"

#define CONTROL_DISPLAY_BCTRL		(1 << 5)
#define CONTROL_DISPLAY_DD		(1 << 3)
#define CONTROL_DISPLAY_BL		(1 << 2)

#define POWER_SAVE_OFF			(0 << 0)
#define POWER_SAVE_LOW			(1 << 0)
#define POWER_SAVE_MEDIUM		(2 << 0)
#define POWER_SAVE_HIGH			(3 << 0)
#define POWER_SAVE_OUTDOOR_MODE		(4 << 0)

#define PANEL_PWM_MAX_VALUE		0xFF

static u32 dcs_get_backlight(struct intel_connector *connector, enum pipe unused)
{
	struct intel_encoder *encoder = intel_attached_encoder(connector);
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
	struct intel_panel *panel = &connector->panel;
	struct mipi_dsi_device *dsi_device;
	u8 data[2] = {};
	enum port port;
	size_t len = panel->backlight.max > U8_MAX ? 2 : 1;

	for_each_dsi_port(port, panel->vbt.dsi.bl_ports) {
		dsi_device = intel_dsi->dsi_hosts[port]->device;
		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
				  &data, len);
		break;
	}

	return (data[1] << 8) | data[0];
}

static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 level)
{
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
	struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
	struct mipi_dsi_device *dsi_device;
	u8 data[2] = {};
	enum port port;
	size_t len = panel->backlight.max > U8_MAX ? 2 : 1;
	unsigned long mode_flags;

	if (len == 1) {
		data[0] = level;
	} else {
		data[0] = level >> 8;
		data[1] = level;
	}

	for_each_dsi_port(port, panel->vbt.dsi.bl_ports) {
		dsi_device = intel_dsi->dsi_hosts[port]->device;
		mode_flags = dsi_device->mode_flags;
		dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM;
		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
				   &data, len);
		dsi_device->mode_flags = mode_flags;
	}
}

static void dcs_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
{
	struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
	struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
	struct mipi_dsi_device *dsi_device;
	enum port port;

	dcs_set_backlight(conn_state, 0);

	for_each_dsi_port(port, panel->vbt.dsi.cabc_ports) {
		u8 cabc = POWER_SAVE_OFF;

		dsi_device = intel_dsi->dsi_hosts[port]->device;
		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
				   &cabc, sizeof(cabc));
	}

	for_each_dsi_port(port, panel->vbt.dsi.bl_ports) {
		u8 ctrl = 0;

		dsi_device = intel_dsi->dsi_hosts[port]->device;

Annotation

Implementation Notes