linux/drivers/video/fbdev/nvidia/nv_backlight.c
<<
>>
Prefs
   1/*
   2 * Backlight code for nVidia based graphic cards
   3 *
   4 * Copyright 2004 Antonino Daplas <adaplas@pol.net>
   5 * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/backlight.h>
  13#include <linux/fb.h>
  14#include <linux/pci.h>
  15
  16#ifdef CONFIG_PMAC_BACKLIGHT
  17#include <asm/backlight.h>
  18#endif
  19
  20#include "nv_local.h"
  21#include "nv_type.h"
  22#include "nv_proto.h"
  23
  24/* We do not have any information about which values are allowed, thus
  25 * we used safe values.
  26 */
  27#define MIN_LEVEL 0x158
  28#define MAX_LEVEL 0x534
  29#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
  30
  31static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
  32                int level)
  33{
  34        struct fb_info *info = pci_get_drvdata(par->pci_dev);
  35        int nlevel;
  36
  37        /* Get and convert the value */
  38        /* No locking of bl_curve since we read a single value */
  39        nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
  40
  41        if (nlevel < 0)
  42                nlevel = 0;
  43        else if (nlevel < MIN_LEVEL)
  44                nlevel = MIN_LEVEL;
  45        else if (nlevel > MAX_LEVEL)
  46                nlevel = MAX_LEVEL;
  47
  48        return nlevel;
  49}
  50
  51static int nvidia_bl_update_status(struct backlight_device *bd)
  52{
  53        struct nvidia_par *par = bl_get_data(bd);
  54        u32 tmp_pcrt, tmp_pmc, fpcontrol;
  55        int level;
  56
  57        if (!par->FlatPanel)
  58                return 0;
  59
  60        if (bd->props.power != FB_BLANK_UNBLANK ||
  61            bd->props.fb_blank != FB_BLANK_UNBLANK)
  62                level = 0;
  63        else
  64                level = bd->props.brightness;
  65
  66        tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
  67        tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
  68        fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
  69
  70        if (level > 0) {
  71                tmp_pcrt |= 0x1;
  72                tmp_pmc |= (1 << 31); /* backlight bit */
  73                tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
  74                fpcontrol |= par->fpSyncs;
  75        } else
  76                fpcontrol |= 0x20000022;
  77
  78        NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
  79        NV_WR32(par->PMC, 0x10F0, tmp_pmc);
  80        NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
  81
  82        return 0;
  83}
  84
  85static const struct backlight_ops nvidia_bl_ops = {
  86        .update_status  = nvidia_bl_update_status,
  87};
  88
  89void nvidia_bl_init(struct nvidia_par *par)
  90{
  91        struct backlight_properties props;
  92        struct fb_info *info = pci_get_drvdata(par->pci_dev);
  93        struct backlight_device *bd;
  94        char name[12];
  95
  96        if (!par->FlatPanel)
  97                return;
  98
  99#ifdef CONFIG_PMAC_BACKLIGHT
 100        if (!machine_is(powermac) ||
 101            !pmac_has_backlight_type("mnca"))
 102                return;
 103#endif
 104
 105        snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 106
 107        memset(&props, 0, sizeof(struct backlight_properties));
 108        props.type = BACKLIGHT_RAW;
 109        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 110        bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
 111                                       &props);
 112        if (IS_ERR(bd)) {
 113                info->bl_dev = NULL;
 114                printk(KERN_WARNING "nvidia: Backlight registration failed\n");
 115                goto error;
 116        }
 117
 118        info->bl_dev = bd;
 119        fb_bl_default_curve(info, 0,
 120                0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
 121                0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
 122
 123        bd->props.brightness = bd->props.max_brightness;
 124        bd->props.power = FB_BLANK_UNBLANK;
 125        backlight_update_status(bd);
 126
 127        printk("nvidia: Backlight initialized (%s)\n", name);
 128
 129        return;
 130
 131error:
 132        return;
 133}
 134
 135void nvidia_bl_exit(struct nvidia_par *par)
 136{
 137        struct fb_info *info = pci_get_drvdata(par->pci_dev);
 138        struct backlight_device *bd = info->bl_dev;
 139
 140        backlight_device_unregister(bd);
 141        printk("nvidia: Backlight unloaded\n");
 142}
 143