1 // SPDX-License-Identifier: GPL-2.0-only
3 * Backlight code for nVidia based graphic cards
5 * Copyright 2004 Antonino Daplas <adaplas@pol.net>
6 * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
9 #include <linux/backlight.h>
11 #include <linux/pci.h>
13 #ifdef CONFIG_PMAC_BACKLIGHT
14 #include <asm/backlight.h>
21 /* We do not have any information about which values are allowed, thus
22 * we used safe values.
24 #define MIN_LEVEL 0x158
25 #define MAX_LEVEL 0x534
26 #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
28 static int nvidia_bl_get_level_brightness(struct nvidia_par
*par
,
31 struct fb_info
*info
= pci_get_drvdata(par
->pci_dev
);
34 /* Get and convert the value */
35 /* No locking of bl_curve since we read a single value */
36 nlevel
= MIN_LEVEL
+ info
->bl_curve
[level
] * LEVEL_STEP
;
40 else if (nlevel
< MIN_LEVEL
)
42 else if (nlevel
> MAX_LEVEL
)
48 static int nvidia_bl_update_status(struct backlight_device
*bd
)
50 struct nvidia_par
*par
= bl_get_data(bd
);
51 u32 tmp_pcrt
, tmp_pmc
, fpcontrol
;
57 if (bd
->props
.power
!= FB_BLANK_UNBLANK
||
58 bd
->props
.fb_blank
!= FB_BLANK_UNBLANK
)
61 level
= bd
->props
.brightness
;
63 tmp_pmc
= NV_RD32(par
->PMC
, 0x10F0) & 0x0000FFFF;
64 tmp_pcrt
= NV_RD32(par
->PCRTC0
, 0x081C) & 0xFFFFFFFC;
65 fpcontrol
= NV_RD32(par
->PRAMDAC
, 0x0848) & 0xCFFFFFCC;
69 tmp_pmc
|= (1 << 31); /* backlight bit */
70 tmp_pmc
|= nvidia_bl_get_level_brightness(par
, level
) << 16;
71 fpcontrol
|= par
->fpSyncs
;
73 fpcontrol
|= 0x20000022;
75 NV_WR32(par
->PCRTC0
, 0x081C, tmp_pcrt
);
76 NV_WR32(par
->PMC
, 0x10F0, tmp_pmc
);
77 NV_WR32(par
->PRAMDAC
, 0x848, fpcontrol
);
82 static const struct backlight_ops nvidia_bl_ops
= {
83 .update_status
= nvidia_bl_update_status
,
86 void nvidia_bl_init(struct nvidia_par
*par
)
88 struct backlight_properties props
;
89 struct fb_info
*info
= pci_get_drvdata(par
->pci_dev
);
90 struct backlight_device
*bd
;
96 #ifdef CONFIG_PMAC_BACKLIGHT
97 if (!machine_is(powermac
) ||
98 !pmac_has_backlight_type("mnca"))
102 snprintf(name
, sizeof(name
), "nvidiabl%d", info
->node
);
104 memset(&props
, 0, sizeof(struct backlight_properties
));
105 props
.type
= BACKLIGHT_RAW
;
106 props
.max_brightness
= FB_BACKLIGHT_LEVELS
- 1;
107 bd
= backlight_device_register(name
, info
->dev
, par
, &nvidia_bl_ops
,
111 printk(KERN_WARNING
"nvidia: Backlight registration failed\n");
116 fb_bl_default_curve(info
, 0,
117 0x158 * FB_BACKLIGHT_MAX
/ MAX_LEVEL
,
118 0x534 * FB_BACKLIGHT_MAX
/ MAX_LEVEL
);
120 bd
->props
.brightness
= bd
->props
.max_brightness
;
121 bd
->props
.power
= FB_BLANK_UNBLANK
;
122 backlight_update_status(bd
);
124 printk("nvidia: Backlight initialized (%s)\n", name
);
130 void nvidia_bl_exit(struct nvidia_par
*par
)
132 struct fb_info
*info
= pci_get_drvdata(par
->pci_dev
);
133 struct backlight_device
*bd
= info
->bl_dev
;
135 backlight_device_unregister(bd
);
136 printk("nvidia: Backlight unloaded\n");