Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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