1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Backlight code for nVidia based graphic cards |
4 | * |
5 | * Copyright 2004 Antonino Daplas <adaplas@pol.net> |
6 | * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> |
7 | */ |
8 | |
9 | #include <linux/backlight.h> |
10 | #include <linux/fb.h> |
11 | #include <linux/pci.h> |
12 | |
13 | #ifdef CONFIG_PMAC_BACKLIGHT |
14 | #include <asm/backlight.h> |
15 | #endif |
16 | |
17 | #include "nv_local.h" |
18 | #include "nv_type.h" |
19 | #include "nv_proto.h" |
20 | |
21 | /* We do not have any information about which values are allowed, thus |
22 | * we used safe values. |
23 | */ |
24 | #define MIN_LEVEL 0x158 |
25 | #define MAX_LEVEL 0x534 |
26 | #define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) |
27 | |
28 | static int nvidia_bl_get_level_brightness(struct nvidia_par *par, |
29 | int level) |
30 | { |
31 | struct fb_info *info = pci_get_drvdata(pdev: par->pci_dev); |
32 | int nlevel; |
33 | |
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; |
37 | |
38 | if (nlevel < 0) |
39 | nlevel = 0; |
40 | else if (nlevel < MIN_LEVEL) |
41 | nlevel = MIN_LEVEL; |
42 | else if (nlevel > MAX_LEVEL) |
43 | nlevel = MAX_LEVEL; |
44 | |
45 | return nlevel; |
46 | } |
47 | |
48 | static int nvidia_bl_update_status(struct backlight_device *bd) |
49 | { |
50 | struct nvidia_par *par = bl_get_data(bl_dev: bd); |
51 | u32 tmp_pcrt, tmp_pmc, fpcontrol; |
52 | int level = backlight_get_brightness(bd); |
53 | |
54 | if (!par->FlatPanel) |
55 | return 0; |
56 | |
57 | tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; |
58 | tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; |
59 | fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; |
60 | |
61 | if (level > 0) { |
62 | tmp_pcrt |= 0x1; |
63 | tmp_pmc |= (1 << 31); /* backlight bit */ |
64 | tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16; |
65 | fpcontrol |= par->fpSyncs; |
66 | } else |
67 | fpcontrol |= 0x20000022; |
68 | |
69 | NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt); |
70 | NV_WR32(par->PMC, 0x10F0, tmp_pmc); |
71 | NV_WR32(par->PRAMDAC, 0x848, fpcontrol); |
72 | |
73 | return 0; |
74 | } |
75 | |
76 | static const struct backlight_ops nvidia_bl_ops = { |
77 | .update_status = nvidia_bl_update_status, |
78 | }; |
79 | |
80 | void nvidia_bl_init(struct nvidia_par *par) |
81 | { |
82 | struct backlight_properties props; |
83 | struct fb_info *info = pci_get_drvdata(pdev: par->pci_dev); |
84 | struct backlight_device *bd; |
85 | char name[12]; |
86 | |
87 | if (!par->FlatPanel) |
88 | return; |
89 | |
90 | #ifdef CONFIG_PMAC_BACKLIGHT |
91 | if (!machine_is(powermac) || |
92 | !pmac_has_backlight_type("mnca" )) |
93 | return; |
94 | #endif |
95 | |
96 | snprintf(buf: name, size: sizeof(name), fmt: "nvidiabl%d" , info->node); |
97 | |
98 | memset(&props, 0, sizeof(struct backlight_properties)); |
99 | props.type = BACKLIGHT_RAW; |
100 | props.max_brightness = FB_BACKLIGHT_LEVELS - 1; |
101 | bd = backlight_device_register(name, dev: info->device, devdata: par, ops: &nvidia_bl_ops, |
102 | props: &props); |
103 | if (IS_ERR(ptr: bd)) { |
104 | info->bl_dev = NULL; |
105 | printk(KERN_WARNING "nvidia: Backlight registration failed\n" ); |
106 | goto error; |
107 | } |
108 | |
109 | info->bl_dev = bd; |
110 | fb_bl_default_curve(fb_info: info, off: 0, |
111 | min: 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, |
112 | max: 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); |
113 | |
114 | bd->props.brightness = bd->props.max_brightness; |
115 | bd->props.power = FB_BLANK_UNBLANK; |
116 | backlight_update_status(bd); |
117 | |
118 | printk("nvidia: Backlight initialized (%s)\n" , name); |
119 | |
120 | error: |
121 | return; |
122 | } |
123 | |
124 | void nvidia_bl_exit(struct nvidia_par *par) |
125 | { |
126 | struct fb_info *info = pci_get_drvdata(pdev: par->pci_dev); |
127 | struct backlight_device *bd = info->bl_dev; |
128 | |
129 | backlight_device_unregister(bd); |
130 | printk("nvidia: Backlight unloaded\n" ); |
131 | } |
132 | |