linux/drivers/video/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 int nvidia_bl_get_brightness(struct backlight_device *bd)
  86{
  87        return bd->props.brightness;
  88}
  89
  90static const struct backlight_ops nvidia_bl_ops = {
  91        .get_brightness = nvidia_bl_get_brightness,
  92        .update_status  = nvidia_bl_update_status,
  93};
  94
  95void nvidia_bl_init(struct nvidia_par *par)
  96{
  97        struct backlight_properties props;
  98        struct fb_info *info = pci_get_drvdata(par->pci_dev);
  99        struct backlight_device *bd;
 100        char name[12];
 101
 102        if (!par->FlatPanel)
 103                return;
 104
 105#ifdef CONFIG_PMAC_BACKLIGHT
 106        if (!machine_is(powermac) ||
 107            !pmac_has_backlight_type("mnca"))
 108                return;
 109#endif
 110
 111        snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 112
 113        memset(&props, 0, sizeof(struct backlight_properties));
 114        props.type = BACKLIGHT_RAW;
 115        props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 116        bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
 117                                       &props);
 118        if (IS_ERR(bd)) {
 119                info->bl_dev = NULL;
 120                printk(KERN_WARNING "nvidia: Backlight registration failed\n");
 121                goto error;
 122        }
 123
 124        info->bl_dev = bd;
 125        fb_bl_default_curve(info, 0,
 126                0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
 127                0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
 128
 129        bd->props.brightness = bd->props.max_brightness;
 130        bd->props.power = FB_BLANK_UNBLANK;
 131        backlight_update_status(bd);
 132
 133        printk("nvidia: Backlight initialized (%s)\n", name);
 134
 135        return;
 136
 137error:
 138        return;
 139}
 140
 141void nvidia_bl_exit(struct nvidia_par *par)
 142{
 143        struct fb_info *info = pci_get_drvdata(par->pci_dev);
 144        struct backlight_device *bd = info->bl_dev;
 145
 146        backlight_device_unregister(bd);
 147        printk("nvidia: Backlight unloaded\n");
 148}
 149