Path: blob/master/arch/powerpc/platforms/powermac/backlight.c
51173 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/of.h>14#include <linux/pmu.h>15#include <linux/atomic.h>16#include <linux/export.h>17#include <asm/backlight.h>1819#define OLD_BACKLIGHT_MAX 152021static void pmac_backlight_key_worker(struct work_struct *work);22static void pmac_backlight_set_legacy_worker(struct work_struct *work);2324static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker);25static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker);2627/* Although these variables are used in interrupt context, it makes no sense to28* protect them. No user is able to produce enough key events per second and29* notice the errors that might happen.30*/31static int pmac_backlight_key_queued;32static int pmac_backlight_set_legacy_queued;3334/* The via-pmu code allows the backlight to be grabbed, in which case the35* in-kernel control of the brightness needs to be disabled. This should36* only be used by really old PowerBooks.37*/38static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);3940/* Protect the pmac_backlight variable below.41You should hold this lock when using the pmac_backlight pointer to42prevent its potential removal. */43DEFINE_MUTEX(pmac_backlight_mutex);4445/* Main backlight storage46*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 one51* internal display, it doesn't matter. Other backlight drivers can be used52* independently.53*54*/55struct backlight_device *pmac_backlight;5657int pmac_has_backlight_type(const char *type)58{59struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");60int i = of_property_match_string(bk_node, "backlight-control", type);6162of_node_put(bk_node);63return i >= 0;64}6566static void pmac_backlight_key_worker(struct work_struct *work)67{68if (atomic_read(&kernel_backlight_disabled))69return;7071mutex_lock(&pmac_backlight_mutex);72if (pmac_backlight) {73struct backlight_properties *props;74int brightness;7576props = &pmac_backlight->props;7778brightness = props->brightness +79((pmac_backlight_key_queued?-1:1) *80(props->max_brightness / 15));8182if (brightness < 0)83brightness = 0;84else if (brightness > props->max_brightness)85brightness = props->max_brightness;8687props->brightness = brightness;88backlight_update_status(pmac_backlight);89}90mutex_unlock(&pmac_backlight_mutex);91}9293/* This function is called in interrupt context */94void pmac_backlight_key(int direction)95{96if (atomic_read(&kernel_backlight_disabled))97return;9899/* we can receive multiple interrupts here, but the scheduled work100* will run only once, with the last value101*/102pmac_backlight_key_queued = direction;103schedule_work(&pmac_backlight_key_work);104}105106static int __pmac_backlight_set_legacy_brightness(int brightness)107{108int error = -ENXIO;109110mutex_lock(&pmac_backlight_mutex);111if (pmac_backlight) {112struct backlight_properties *props;113114props = &pmac_backlight->props;115props->brightness = brightness *116(props->max_brightness + 1) /117(OLD_BACKLIGHT_MAX + 1);118119if (props->brightness > props->max_brightness)120props->brightness = props->max_brightness;121else if (props->brightness < 0)122props->brightness = 0;123124backlight_update_status(pmac_backlight);125126error = 0;127}128mutex_unlock(&pmac_backlight_mutex);129130return error;131}132133static void pmac_backlight_set_legacy_worker(struct work_struct *work)134{135if (atomic_read(&kernel_backlight_disabled))136return;137138__pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);139}140141/* This function is called in interrupt context */142void pmac_backlight_set_legacy_brightness_pmu(int brightness) {143if (atomic_read(&kernel_backlight_disabled))144return;145146pmac_backlight_set_legacy_queued = brightness;147schedule_work(&pmac_backlight_set_legacy_work);148}149150int pmac_backlight_set_legacy_brightness(int brightness)151{152return __pmac_backlight_set_legacy_brightness(brightness);153}154155int pmac_backlight_get_legacy_brightness(void)156{157int result = -ENXIO;158159mutex_lock(&pmac_backlight_mutex);160if (pmac_backlight) {161struct backlight_properties *props;162163props = &pmac_backlight->props;164165result = props->brightness *166(OLD_BACKLIGHT_MAX + 1) /167(props->max_brightness + 1);168}169mutex_unlock(&pmac_backlight_mutex);170171return result;172}173174void pmac_backlight_disable(void)175{176atomic_inc(&kernel_backlight_disabled);177}178179void pmac_backlight_enable(void)180{181atomic_dec(&kernel_backlight_disabled);182}183184EXPORT_SYMBOL_GPL(pmac_backlight);185EXPORT_SYMBOL_GPL(pmac_backlight_mutex);186EXPORT_SYMBOL_GPL(pmac_has_backlight_type);187188189