Path: blob/master/drivers/gpu/drm/nouveau/nouveau_backlight.c
15112 views
/*1* Copyright (C) 2009 Red Hat <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice (including the12* next paragraph) shall be included in all copies or substantial13* portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,16* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF17* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.18* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE19* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION20* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION21* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.22*23*/2425/*26* Authors:27* Matthew Garrett <[email protected]>28*29* Register locations derived from NVClock by Roderick Colenbrander30*/3132#include <linux/backlight.h>33#include <linux/acpi.h>3435#include "drmP.h"36#include "nouveau_drv.h"37#include "nouveau_drm.h"38#include "nouveau_reg.h"3940static int nv40_get_intensity(struct backlight_device *bd)41{42struct drm_device *dev = bl_get_data(bd);43int val = (nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)44>> 16;4546return val;47}4849static int nv40_set_intensity(struct backlight_device *bd)50{51struct drm_device *dev = bl_get_data(bd);52int val = bd->props.brightness;53int reg = nv_rd32(dev, NV40_PMC_BACKLIGHT);5455nv_wr32(dev, NV40_PMC_BACKLIGHT,56(val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));5758return 0;59}6061static const struct backlight_ops nv40_bl_ops = {62.options = BL_CORE_SUSPENDRESUME,63.get_brightness = nv40_get_intensity,64.update_status = nv40_set_intensity,65};6667static int nv50_get_intensity(struct backlight_device *bd)68{69struct drm_device *dev = bl_get_data(bd);7071return nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT);72}7374static int nv50_set_intensity(struct backlight_device *bd)75{76struct drm_device *dev = bl_get_data(bd);77int val = bd->props.brightness;7879nv_wr32(dev, NV50_PDISPLAY_SOR_BACKLIGHT,80val | NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE);81return 0;82}8384static const struct backlight_ops nv50_bl_ops = {85.options = BL_CORE_SUSPENDRESUME,86.get_brightness = nv50_get_intensity,87.update_status = nv50_set_intensity,88};8990static int nouveau_nv40_backlight_init(struct drm_connector *connector)91{92struct drm_device *dev = connector->dev;93struct drm_nouveau_private *dev_priv = dev->dev_private;94struct backlight_properties props;95struct backlight_device *bd;9697if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))98return 0;99100memset(&props, 0, sizeof(struct backlight_properties));101props.type = BACKLIGHT_RAW;102props.max_brightness = 31;103bd = backlight_device_register("nv_backlight", &connector->kdev, dev,104&nv40_bl_ops, &props);105if (IS_ERR(bd))106return PTR_ERR(bd);107108dev_priv->backlight = bd;109bd->props.brightness = nv40_get_intensity(bd);110backlight_update_status(bd);111112return 0;113}114115static int nouveau_nv50_backlight_init(struct drm_connector *connector)116{117struct drm_device *dev = connector->dev;118struct drm_nouveau_private *dev_priv = dev->dev_private;119struct backlight_properties props;120struct backlight_device *bd;121122if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))123return 0;124125memset(&props, 0, sizeof(struct backlight_properties));126props.type = BACKLIGHT_RAW;127props.max_brightness = 1025;128bd = backlight_device_register("nv_backlight", &connector->kdev, dev,129&nv50_bl_ops, &props);130if (IS_ERR(bd))131return PTR_ERR(bd);132133dev_priv->backlight = bd;134bd->props.brightness = nv50_get_intensity(bd);135backlight_update_status(bd);136return 0;137}138139int nouveau_backlight_init(struct drm_connector *connector)140{141struct drm_device *dev = connector->dev;142struct drm_nouveau_private *dev_priv = dev->dev_private;143144#ifdef CONFIG_ACPI145if (acpi_video_backlight_support()) {146NV_INFO(dev, "ACPI backlight interface available, "147"not registering our own\n");148return 0;149}150#endif151152switch (dev_priv->card_type) {153case NV_40:154return nouveau_nv40_backlight_init(connector);155case NV_50:156return nouveau_nv50_backlight_init(connector);157default:158break;159}160161return 0;162}163164void nouveau_backlight_exit(struct drm_connector *connector)165{166struct drm_device *dev = connector->dev;167struct drm_nouveau_private *dev_priv = dev->dev_private;168169if (dev_priv->backlight) {170backlight_device_unregister(dev_priv->backlight);171dev_priv->backlight = NULL;172}173}174175176