Path: blob/master/arch/powerpc/platforms/powermac/backlight.c
26481 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Miscellaneous procedures for dealing with the PowerMac hardware.3* Contains support for the backlight.4*5* Copyright (C) 2000 Benjamin Herrenschmidt6* Copyright (C) 2006 Michael Hanselmann <[email protected]>7*8*/910#include <linux/kernel.h>11#include <linux/backlight.h>12#include <linux/adb.h>13#include <linux/pmu.h>14#include <linux/atomic.h>15#include <linux/export.h>16#include <asm/backlight.h>1718#define OLD_BACKLIGHT_MAX 151920static void pmac_backlight_key_worker(struct work_struct *work);21static void pmac_backlight_set_legacy_worker(struct work_struct *work);2223static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker);24static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker);2526/* Although these variables are used in interrupt context, it makes no sense to27* protect them. No user is able to produce enough key events per second and28* notice the errors that might happen.29*/30static int pmac_backlight_key_queued;31static int pmac_backlight_set_legacy_queued;3233/* The via-pmu code allows the backlight to be grabbed, in which case the34* in-kernel control of the brightness needs to be disabled. This should35* only be used by really old PowerBooks.36*/37static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);3839/* Protect the pmac_backlight variable below.40You should hold this lock when using the pmac_backlight pointer to41prevent its potential removal. */42DEFINE_MUTEX(pmac_backlight_mutex);4344/* Main backlight storage45*46* Backlight drivers in this variable are required to have the "ops"47* attribute set and to have an update_status function.48*49* We can only store one backlight here, but since Apple laptops have only one50* internal display, it doesn't matter. Other backlight drivers can be used51* independently.52*53*/54struct backlight_device *pmac_backlight;5556int pmac_has_backlight_type(const char *type)57{58struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");59int i = of_property_match_string(bk_node, "backlight-control", type);6061of_node_put(bk_node);62return i >= 0;63}6465static void pmac_backlight_key_worker(struct work_struct *work)66{67if (atomic_read(&kernel_backlight_disabled))68return;6970mutex_lock(&pmac_backlight_mutex);71if (pmac_backlight) {72struct backlight_properties *props;73int brightness;7475props = &pmac_backlight->props;7677brightness = props->brightness +78((pmac_backlight_key_queued?-1:1) *79(props->max_brightness / 15));8081if (brightness < 0)82brightness = 0;83else if (brightness > props->max_brightness)84brightness = props->max_brightness;8586props->brightness = brightness;87backlight_update_status(pmac_backlight);88}89mutex_unlock(&pmac_backlight_mutex);90}9192/* This function is called in interrupt context */93void pmac_backlight_key(int direction)94{95if (atomic_read(&kernel_backlight_disabled))96return;9798/* we can receive multiple interrupts here, but the scheduled work99* will run only once, with the last value100*/101pmac_backlight_key_queued = direction;102schedule_work(&pmac_backlight_key_work);103}104105static int __pmac_backlight_set_legacy_brightness(int brightness)106{107int error = -ENXIO;108109mutex_lock(&pmac_backlight_mutex);110if (pmac_backlight) {111struct backlight_properties *props;112113props = &pmac_backlight->props;114props->brightness = brightness *115(props->max_brightness + 1) /116(OLD_BACKLIGHT_MAX + 1);117118if (props->brightness > props->max_brightness)119props->brightness = props->max_brightness;120else if (props->brightness < 0)121props->brightness = 0;122123backlight_update_status(pmac_backlight);124125error = 0;126}127mutex_unlock(&pmac_backlight_mutex);128129return error;130}131132static void pmac_backlight_set_legacy_worker(struct work_struct *work)133{134if (atomic_read(&kernel_backlight_disabled))135return;136137__pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);138}139140/* This function is called in interrupt context */141void pmac_backlight_set_legacy_brightness_pmu(int brightness) {142if (atomic_read(&kernel_backlight_disabled))143return;144145pmac_backlight_set_legacy_queued = brightness;146schedule_work(&pmac_backlight_set_legacy_work);147}148149int pmac_backlight_set_legacy_brightness(int brightness)150{151return __pmac_backlight_set_legacy_brightness(brightness);152}153154int pmac_backlight_get_legacy_brightness(void)155{156int result = -ENXIO;157158mutex_lock(&pmac_backlight_mutex);159if (pmac_backlight) {160struct backlight_properties *props;161162props = &pmac_backlight->props;163164result = props->brightness *165(OLD_BACKLIGHT_MAX + 1) /166(props->max_brightness + 1);167}168mutex_unlock(&pmac_backlight_mutex);169170return result;171}172173void pmac_backlight_disable(void)174{175atomic_inc(&kernel_backlight_disabled);176}177178void pmac_backlight_enable(void)179{180atomic_dec(&kernel_backlight_disabled);181}182183EXPORT_SYMBOL_GPL(pmac_backlight);184EXPORT_SYMBOL_GPL(pmac_backlight_mutex);185EXPORT_SYMBOL_GPL(pmac_has_backlight_type);186187188