linux/drivers/acpi/acpi_video.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  video.c - ACPI Video Driver
 *
 *  Copyright (C) 2004 Luming Yu <[email protected]>
 *  Copyright (C) 2004 Bruno Ducrot <[email protected]>
 *  Copyright (C) 2006 Thomas Tuttle <[email protected]>
 */

#define pr_fmt(fmt)

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/input.h>
#include <linux/backlight.h>
#include <linux/thermal.h>
#include <linux/sort.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/suspend.h>
#include <linux/acpi.h>
#include <acpi/video.h>
#include <linux/uaccess.h>

#define ACPI_VIDEO_BUS_NAME
#define ACPI_VIDEO_DEVICE_NAME

#define MAX_NAME_LEN

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

static bool brightness_switch_enabled =;
module_param(brightness_switch_enabled, bool, 0644);

/*
 * By default, we don't allow duplicate ACPI video bus devices
 * under the same VGA controller
 */
static bool allow_duplicates;
module_param(allow_duplicates, bool, 0644);

#define REPORT_OUTPUT_KEY_EVENTS
#define REPORT_BRIGHTNESS_KEY_EVENTS
static int report_key_events =;
module_param(report_key_events, int, 0644);
MODULE_PARM_DESC();

static int hw_changes_brightness =;
module_param(hw_changes_brightness, int, 0644);
MODULE_PARM_DESC();

/*
 * Whether the struct acpi_video_device_attrib::device_id_scheme bit should be
 * assumed even if not actually set.
 */
static bool device_id_scheme =;
module_param(device_id_scheme, bool, 0444);

static int only_lcd;
module_param(only_lcd, int, 0444);

static bool may_report_brightness_keys;
static int register_count;
static DEFINE_MUTEX(register_count_mutex);
static DEFINE_MUTEX(video_list_lock);
static LIST_HEAD(video_bus_head);
static int acpi_video_bus_add(struct acpi_device *device);
static void acpi_video_bus_remove(struct acpi_device *device);
static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data);

/*
 * Indices in the _BCL method response: the first two items are special,
 * the rest are all supported levels.
 *
 * See page 575 of the ACPI spec 3.0
 */
enum acpi_video_level_idx {};

static const struct acpi_device_id video_device_ids[] =;
MODULE_DEVICE_TABLE(acpi, video_device_ids);

static struct acpi_driver acpi_video_bus =;

struct acpi_video_bus_flags {};

struct acpi_video_bus_cap {};

struct acpi_video_device_attrib {};

struct acpi_video_enumerated_device {};

struct acpi_video_bus {};

struct acpi_video_device_flags {};

struct acpi_video_device_cap {};

struct acpi_video_device {};

static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
static void acpi_video_device_rebind(struct acpi_video_bus *video);
static void acpi_video_device_bind(struct acpi_video_bus *video,
				   struct acpi_video_device *device);
static int acpi_video_device_enumerate(struct acpi_video_bus *video);
static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
			int level);
static int acpi_video_device_lcd_get_level_current(
			struct acpi_video_device *device,
			unsigned long long *level, bool raw);
static int acpi_video_get_next_level(struct acpi_video_device *device,
				     u32 level_current, u32 event);
static void acpi_video_switch_brightness(struct work_struct *work);

/* backlight device sysfs support */
static int acpi_video_get_brightness(struct backlight_device *bd)
{}

static int acpi_video_set_brightness(struct backlight_device *bd)
{}

static const struct backlight_ops acpi_backlight_ops =;

/* thermal cooling device callbacks */
static int video_get_max_state(struct thermal_cooling_device *cooling_dev,
			       unsigned long *state)
{}

static int video_get_cur_state(struct thermal_cooling_device *cooling_dev,
			       unsigned long *state)
{}

static int
video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state)
{}

static const struct thermal_cooling_device_ops video_cooling_ops =;

/*
 * --------------------------------------------------------------------------
 *                             Video Management
 * --------------------------------------------------------------------------
 */

static int
acpi_video_device_lcd_query_levels(acpi_handle handle,
				   union acpi_object **levels)
{}

static int
acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
{}

/*
 * For some buggy _BQC methods, we need to add a constant value to
 * the _BQC return value to get the actual current brightness level
 */

static int bqc_offset_aml_bug_workaround;
static int video_set_bqc_offset(const struct dmi_system_id *d)
{}

static int video_set_device_id_scheme(const struct dmi_system_id *d)
{}

static int video_enable_only_lcd(const struct dmi_system_id *d)
{}

static int video_set_report_key_events(const struct dmi_system_id *id)
{}

static int video_hw_changes_brightness(
	const struct dmi_system_id *d)
{}

static const struct dmi_system_id video_dmi_table[] =;

static unsigned long long
acpi_video_bqc_value_to_level(struct acpi_video_device *device,
			      unsigned long long bqc_value)
{}

static int
acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
					unsigned long long *level, bool raw)
{}

static int
acpi_video_device_EDID(struct acpi_video_device *device,
		       union acpi_object **edid, int length)
{}

/* bus */

/*
 *  Arg:
 *	video		: video bus device pointer
 *	bios_flag	:
 *		0.	The system BIOS should NOT automatically switch(toggle)
 *			the active display output.
 *		1.	The system BIOS should automatically switch (toggle) the
 *			active display output. No switch event.
 *		2.	The _DGS value should be locked.
 *		3.	The system BIOS should not automatically switch (toggle) the
 *			active display output, but instead generate the display switch
 *			event notify code.
 *	lcd_flag	:
 *		0.	The system BIOS should automatically control the brightness level
 *			of the LCD when:
 *			- the power changes from AC to DC (ACPI appendix B)
 *			- a brightness hotkey gets pressed (implied by Win7/8 backlight docs)
 *		1.	The system BIOS should NOT automatically control the brightness
 *			level of the LCD when:
 *			- the power changes from AC to DC (ACPI appendix B)
 *			- a brightness hotkey gets pressed (implied by Win7/8 backlight docs)
 *  Return Value:
 *		-EINVAL	wrong arg.
 */

static int
acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
{}

/*
 * Simple comparison function used to sort backlight levels.
 */

static int
acpi_video_cmp_level(const void *a, const void *b)
{}

/*
 * Decides if _BQC/_BCQ for this system is usable
 *
 * We do this by changing the level first and then read out the current
 * brightness level, if the value does not match, find out if it is using
 * index. If not, clear the _BQC/_BCQ capability.
 */
static int acpi_video_bqc_quirk(struct acpi_video_device *device,
				int max_level, int current_level)
{}

int acpi_video_get_levels(struct acpi_device *device,
			  struct acpi_video_device_brightness **dev_br,
			  int *pmax_level)
{}
EXPORT_SYMBOL();

/*
 *  Arg:
 *	device	: video output device (LCD, CRT, ..)
 *
 *  Return Value:
 *	Maximum brightness level
 *
 *  Allocate and initialize device->brightness.
 */

static int
acpi_video_init_brightness(struct acpi_video_device *device)
{}

/*
 *  Arg:
 *	device	: video output device (LCD, CRT, ..)
 *
 *  Return Value:
 *	None
 *
 *  Find out all required AML methods defined under the output
 *  device.
 */

static void acpi_video_device_find_cap(struct acpi_video_device *device)
{}

/*
 *  Arg:
 *	device	: video output device (VGA)
 *
 *  Return Value:
 *	None
 *
 *  Find out all required AML methods defined under the video bus device.
 */

static void acpi_video_bus_find_cap(struct acpi_video_bus *video)
{}

/*
 * Check whether the video bus device has required AML method to
 * support the desired features
 */

static int acpi_video_bus_check(struct acpi_video_bus *video)
{}

/*
 * --------------------------------------------------------------------------
 *                               Driver Interface
 * --------------------------------------------------------------------------
 */

/* device interface */
static struct acpi_video_device_attrib *
acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id)
{}

static int
acpi_video_get_device_type(struct acpi_video_bus *video,
			   unsigned long device_id)
{}

static int acpi_video_bus_get_one_device(struct acpi_device *device, void *arg)
{}

/*
 *  Arg:
 *	video	: video bus device
 *
 *  Return:
 *	none
 *
 *  Enumerate the video device list of the video bus,
 *  bind the ids with the corresponding video devices
 *  under the video bus.
 */

static void acpi_video_device_rebind(struct acpi_video_bus *video)
{}

/*
 *  Arg:
 *	video	: video bus device
 *	device	: video output device under the video
 *		bus
 *
 *  Return:
 *	none
 *
 *  Bind the ids with the corresponding video devices
 *  under the video bus.
 */

static void
acpi_video_device_bind(struct acpi_video_bus *video,
		       struct acpi_video_device *device)
{}

static bool acpi_video_device_in_dod(struct acpi_video_device *device)
{}

/*
 *  Arg:
 *	video	: video bus device
 *
 *  Return:
 *	< 0	: error
 *
 *  Call _DOD to enumerate all devices attached to display adapter
 *
 */

static int acpi_video_device_enumerate(struct acpi_video_bus *video)
{}

static int
acpi_video_get_next_level(struct acpi_video_device *device,
			  u32 level_current, u32 event)
{}

static void
acpi_video_switch_brightness(struct work_struct *work)
{}

int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
			void **edid)
{}
EXPORT_SYMBOL();

static int
acpi_video_bus_get_devices(struct acpi_video_bus *video,
			   struct acpi_device *device)
{}

/* acpi_video interface */

/*
 * Win8 requires setting bit2 of _DOS to let firmware know it shouldn't
 * perform any automatic brightness change on receiving a notification.
 */
static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
{}

static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
{}

static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
{}

static void brightness_switch_event(struct acpi_video_device *video_device,
				    u32 event)
{}

static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
{}

static int acpi_video_resume(struct notifier_block *nb,
				unsigned long val, void *ign)
{}

static acpi_status
acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
			void **return_value)
{}

static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
{}

static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video)
{}

static bool acpi_video_should_register_backlight(struct acpi_video_device *dev)
{}

static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
{}

static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device)
{}

static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video)
{}

static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device)
{}

static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video)
{}

static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev)
{}

static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
{}

static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{}

static int instance;

static int acpi_video_bus_add(struct acpi_device *device)
{}

static void acpi_video_bus_remove(struct acpi_device *device)
{}

static int __init is_i740(struct pci_dev *dev)
{}

static int __init intel_opregion_present(void)
{}

int acpi_video_register(void)
{}
EXPORT_SYMBOL();

void acpi_video_unregister(void)
{}
EXPORT_SYMBOL();

void acpi_video_register_backlight(void)
{}
EXPORT_SYMBOL();

bool acpi_video_handles_brightness_key_presses(void)
{}
EXPORT_SYMBOL();

/*
 * This is kind of nasty. Hardware using Intel chipsets may require
 * the video opregion code to be run first in order to initialise
 * state before any ACPI video calls are made. To handle this we defer
 * registration of the video class until the opregion code has run.
 */

static int __init acpi_video_init(void)
{}

static void __exit acpi_video_exit(void)
{}

module_init();
module_exit(acpi_video_exit);