File Index
Files and directories
Sign in
FILE

backlight.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/powermac/backlight.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Miscellaneous procedures for dealing with the PowerMac hardware.
  4 * Contains support for the backlight.
  5 *
  6 *   Copyright (C) 2000 Benjamin Herrenschmidt
  7 *   Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
  8 *
  9 */
 10
 11#include <linux/kernel.h>
 12#include <linux/backlight.h>
 13#include <linux/adb.h>
 14#include <linux/of.h>
 15#include <linux/pmu.h>
 16#include <linux/atomic.h>
 17#include <linux/export.h>
 18#include <asm/backlight.h>
 19
 20#define OLD_BACKLIGHT_MAX 15
 21
 22static void pmac_backlight_key_worker(struct work_struct *work);
 23static void pmac_backlight_set_legacy_worker(struct work_struct *work);
 24
 25static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker);
 26static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker);
 27
 28/* Although these variables are used in interrupt context, it makes no sense to
 29 * protect them. No user is able to produce enough key events per second and
 30 * notice the errors that might happen.
 31 */
 32static int pmac_backlight_key_queued;
 33static int pmac_backlight_set_legacy_queued;
 34
 35/* The via-pmu code allows the backlight to be grabbed, in which case the
 36 * in-kernel control of the brightness needs to be disabled. This should
 37 * only be used by really old PowerBooks.
 38 */
 39static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
 40
 41/* Protect the pmac_backlight variable below.
 42   You should hold this lock when using the pmac_backlight pointer to
 43   prevent its potential removal. */
 44DEFINE_MUTEX(pmac_backlight_mutex);
 45
 46/* Main backlight storage
 47 *
 48 * Backlight drivers in this variable are required to have the "ops"
 49 * attribute set and to have an update_status function.
 50 *
 51 * We can only store one backlight here, but since Apple laptops have only one
 52 * internal display, it doesn't matter. Other backlight drivers can be used
 53 * independently.
 54 *
 55 */
 56struct backlight_device *pmac_backlight;
 57
 58int pmac_has_backlight_type(const char *type)
 59{
 60	struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");
 61	int i = of_property_match_string(bk_node, "backlight-control", type);
 62
 63	of_node_put(bk_node);
 64	return i >= 0;
 65}
 66
 67static void pmac_backlight_key_worker(struct work_struct *work)
 68{
 69	if (atomic_read(&kernel_backlight_disabled))
 70		return;
 71
 72	mutex_lock(&pmac_backlight_mutex);
 73	if (pmac_backlight) {
 74		struct backlight_properties *props;
 75		int brightness;
 76
 77		props = &pmac_backlight->props;
 78
 79		brightness = props->brightness +
 80			((pmac_backlight_key_queued?-1:1) *
 81			 (props->max_brightness / 15));
 82
 83		if (brightness < 0)
 84			brightness = 0;
 85		else if (brightness > props->max_brightness)
 86			brightness = props->max_brightness;
 87
 88		props->brightness = brightness;
 89		backlight_update_status(pmac_backlight);
 90	}
 91	mutex_unlock(&pmac_backlight_mutex);
 92}
 93
 94/* This function is called in interrupt context */
 95void pmac_backlight_key(int direction)
 96{
 97	if (atomic_read(&kernel_backlight_disabled))
 98		return;
 99
100	/* we can receive multiple interrupts here, but the scheduled work
101	 * will run only once, with the last value
102	 */
103	pmac_backlight_key_queued = direction;
104	schedule_work(&pmac_backlight_key_work);
105}
106
107static int __pmac_backlight_set_legacy_brightness(int brightness)
108{
109	int error = -ENXIO;
110
111	mutex_lock(&pmac_backlight_mutex);
112	if (pmac_backlight) {
113		struct backlight_properties *props;
114
115		props = &pmac_backlight->props;
116		props->brightness = brightness *
117			(props->max_brightness + 1) /
118			(OLD_BACKLIGHT_MAX + 1);
119
120		if (props->brightness > props->max_brightness)
121			props->brightness = props->max_brightness;
122		else if (props->brightness < 0)
123			props->brightness = 0;
124
125		backlight_update_status(pmac_backlight);
126
127		error = 0;
128	}
129	mutex_unlock(&pmac_backlight_mutex);
130
131	return error;
132}
133
134static void pmac_backlight_set_legacy_worker(struct work_struct *work)
135{
136	if (atomic_read(&kernel_backlight_disabled))
137		return;
138
139	__pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);
140}
141
142/* This function is called in interrupt context */
143void pmac_backlight_set_legacy_brightness_pmu(int brightness) {
144	if (atomic_read(&kernel_backlight_disabled))
145		return;
146
147	pmac_backlight_set_legacy_queued = brightness;
148	schedule_work(&pmac_backlight_set_legacy_work);
149}
150
151int pmac_backlight_set_legacy_brightness(int brightness)
152{
153	return __pmac_backlight_set_legacy_brightness(brightness);
154}
155
156int pmac_backlight_get_legacy_brightness(void)
157{
158	int result = -ENXIO;
159
160	mutex_lock(&pmac_backlight_mutex);
161	if (pmac_backlight) {
162		struct backlight_properties *props;
163
164		props = &pmac_backlight->props;
165
166		result = props->brightness *
167			(OLD_BACKLIGHT_MAX + 1) /
168			(props->max_brightness + 1);
169	}
170	mutex_unlock(&pmac_backlight_mutex);
171
172	return result;
173}
174
175void pmac_backlight_disable(void)
176{
177	atomic_inc(&kernel_backlight_disabled);
178}
179
180void pmac_backlight_enable(void)
181{
182	atomic_dec(&kernel_backlight_disabled);
183}
184
185EXPORT_SYMBOL_GPL(pmac_backlight);
186EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
187EXPORT_SYMBOL_GPL(pmac_has_backlight_type);
~/ Read-only file preview.