drm/nouveau: remove (most) hardcoded object handle usage
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nouveau_backlight.c
CommitLineData
6ee73861
BS
1/*
2 * Copyright (C) 2009 Red Hat <mjg@redhat.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26/*
27 * Authors:
28 * Matthew Garrett <mjg@redhat.com>
29 *
30 * Register locations derived from NVClock by Roderick Colenbrander
31 */
32
33#include <linux/backlight.h>
34
51a3d342 35#include "nouveau_drm.h"
6ee73861 36#include "nouveau_reg.h"
10b461e4 37#include "nouveau_encoder.h"
6ee73861 38
73076481
BS
39static int
40nv40_get_intensity(struct backlight_device *bd)
6ee73861 41{
51a3d342 42 struct nouveau_drm *drm = bl_get_data(bd);
967e7bde 43 struct nvif_device *device = &drm->device;
db2bec18 44 int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
51a3d342 45 NV40_PMC_BACKLIGHT_MASK) >> 16;
6ee73861
BS
46
47 return val;
48}
49
73076481
BS
50static int
51nv40_set_intensity(struct backlight_device *bd)
6ee73861 52{
51a3d342 53 struct nouveau_drm *drm = bl_get_data(bd);
967e7bde 54 struct nvif_device *device = &drm->device;
6ee73861 55 int val = bd->props.brightness;
db2bec18 56 int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
6ee73861 57
db2bec18 58 nvif_wr32(device, NV40_PMC_BACKLIGHT,
6ee73861
BS
59 (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
60
61 return 0;
62}
63
acc2472e 64static const struct backlight_ops nv40_bl_ops = {
6ee73861
BS
65 .options = BL_CORE_SUSPENDRESUME,
66 .get_brightness = nv40_get_intensity,
67 .update_status = nv40_set_intensity,
68};
69
73076481
BS
70static int
71nv40_backlight_init(struct drm_connector *connector)
6ee73861 72{
77145f1c 73 struct nouveau_drm *drm = nouveau_drm(connector->dev);
967e7bde 74 struct nvif_device *device = &drm->device;
7eae3efa 75 struct backlight_properties props;
6ee73861
BS
76 struct backlight_device *bd;
77
db2bec18 78 if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
6ee73861
BS
79 return 0;
80
a19a6ee6 81 memset(&props, 0, sizeof(struct backlight_properties));
bb7ca747 82 props.type = BACKLIGHT_RAW;
a19a6ee6 83 props.max_brightness = 31;
5bdebb18 84 bd = backlight_device_register("nv_backlight", connector->kdev, drm,
a19a6ee6 85 &nv40_bl_ops, &props);
b795016c
MS
86 if (IS_ERR(bd))
87 return PTR_ERR(bd);
51a3d342 88 drm->backlight = bd;
6ee73861
BS
89 bd->props.brightness = nv40_get_intensity(bd);
90 backlight_update_status(bd);
91
92 return 0;
93}
94
73076481
BS
95static int
96nv50_get_intensity(struct backlight_device *bd)
97{
10b461e4 98 struct nouveau_encoder *nv_encoder = bl_get_data(bd);
77145f1c 99 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
967e7bde 100 struct nvif_device *device = &drm->device;
10b461e4 101 int or = nv_encoder->or;
09461459
BS
102 u32 div = 1025;
103 u32 val;
73076481 104
db2bec18 105 val = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
5024c54b 106 val &= NV50_PDISP_SOR_PWM_CTL_VAL;
09461459 107 return ((val * 100) + (div / 2)) / div;
73076481
BS
108}
109
110static int
111nv50_set_intensity(struct backlight_device *bd)
112{
10b461e4 113 struct nouveau_encoder *nv_encoder = bl_get_data(bd);
77145f1c 114 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
967e7bde 115 struct nvif_device *device = &drm->device;
10b461e4 116 int or = nv_encoder->or;
09461459
BS
117 u32 div = 1025;
118 u32 val = (bd->props.brightness * div) / 100;
73076481 119
db2bec18 120 nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
51a3d342 121 NV50_PDISP_SOR_PWM_CTL_NEW | val);
73076481
BS
122 return 0;
123}
124
125static const struct backlight_ops nv50_bl_ops = {
126 .options = BL_CORE_SUSPENDRESUME,
127 .get_brightness = nv50_get_intensity,
128 .update_status = nv50_set_intensity,
129};
130
5024c54b
BS
131static int
132nva3_get_intensity(struct backlight_device *bd)
133{
134 struct nouveau_encoder *nv_encoder = bl_get_data(bd);
77145f1c 135 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
967e7bde 136 struct nvif_device *device = &drm->device;
5024c54b
BS
137 int or = nv_encoder->or;
138 u32 div, val;
139
db2bec18
BS
140 div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
141 val = nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(or));
5024c54b
BS
142 val &= NVA3_PDISP_SOR_PWM_CTL_VAL;
143 if (div && div >= val)
144 return ((val * 100) + (div / 2)) / div;
145
146 return 100;
147}
148
149static int
150nva3_set_intensity(struct backlight_device *bd)
151{
152 struct nouveau_encoder *nv_encoder = bl_get_data(bd);
77145f1c 153 struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
967e7bde 154 struct nvif_device *device = &drm->device;
5024c54b
BS
155 int or = nv_encoder->or;
156 u32 div, val;
157
db2bec18 158 div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
5024c54b
BS
159 val = (bd->props.brightness * div) / 100;
160 if (div) {
db2bec18 161 nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
51a3d342
BS
162 NV50_PDISP_SOR_PWM_CTL_NEW |
163 NVA3_PDISP_SOR_PWM_CTL_UNK);
5024c54b
BS
164 return 0;
165 }
166
167 return -EINVAL;
168}
169
170static const struct backlight_ops nva3_bl_ops = {
171 .options = BL_CORE_SUSPENDRESUME,
172 .get_brightness = nva3_get_intensity,
173 .update_status = nva3_set_intensity,
174};
175
73076481
BS
176static int
177nv50_backlight_init(struct drm_connector *connector)
6ee73861 178{
77145f1c 179 struct nouveau_drm *drm = nouveau_drm(connector->dev);
967e7bde 180 struct nvif_device *device = &drm->device;
10b461e4 181 struct nouveau_encoder *nv_encoder;
7eae3efa 182 struct backlight_properties props;
6ee73861 183 struct backlight_device *bd;
5024c54b 184 const struct backlight_ops *ops;
10b461e4 185
cb75d97e 186 nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
10b461e4 187 if (!nv_encoder) {
cb75d97e 188 nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
10b461e4
BS
189 if (!nv_encoder)
190 return -ENODEV;
191 }
192
db2bec18 193 if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or)))
6ee73861
BS
194 return 0;
195
967e7bde
BS
196 if (device->info.chipset <= 0xa0 ||
197 device->info.chipset == 0xaa ||
198 device->info.chipset == 0xac)
5024c54b
BS
199 ops = &nv50_bl_ops;
200 else
201 ops = &nva3_bl_ops;
202
a19a6ee6 203 memset(&props, 0, sizeof(struct backlight_properties));
bb7ca747 204 props.type = BACKLIGHT_RAW;
09461459 205 props.max_brightness = 100;
5bdebb18 206 bd = backlight_device_register("nv_backlight", connector->kdev,
5024c54b 207 nv_encoder, ops, &props);
6ee73861
BS
208 if (IS_ERR(bd))
209 return PTR_ERR(bd);
210
51a3d342 211 drm->backlight = bd;
5024c54b 212 bd->props.brightness = bd->ops->get_brightness(bd);
6ee73861
BS
213 backlight_update_status(bd);
214 return 0;
215}
216
73076481 217int
10b461e4 218nouveau_backlight_init(struct drm_device *dev)
6ee73861 219{
77145f1c 220 struct nouveau_drm *drm = nouveau_drm(dev);
967e7bde 221 struct nvif_device *device = &drm->device;
10b461e4 222 struct drm_connector *connector;
6ee73861 223
10b461e4
BS
224 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
225 if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
226 connector->connector_type != DRM_MODE_CONNECTOR_eDP)
227 continue;
228
967e7bde
BS
229 switch (device->info.family) {
230 case NV_DEVICE_INFO_V0_CURIE:
10b461e4 231 return nv40_backlight_init(connector);
967e7bde
BS
232 case NV_DEVICE_INFO_V0_TESLA:
233 case NV_DEVICE_INFO_V0_FERMI:
234 case NV_DEVICE_INFO_V0_KEPLER:
10b461e4
BS
235 return nv50_backlight_init(connector);
236 default:
237 break;
238 }
6ee73861
BS
239 }
240
10b461e4 241
6ee73861
BS
242 return 0;
243}
244
73076481 245void
10b461e4 246nouveau_backlight_exit(struct drm_device *dev)
6ee73861 247{
77145f1c 248 struct nouveau_drm *drm = nouveau_drm(dev);
6ee73861 249
51a3d342
BS
250 if (drm->backlight) {
251 backlight_device_unregister(drm->backlight);
252 drm->backlight = NULL;
6ee73861
BS
253 }
254}
This page took 0.39934 seconds and 5 git commands to generate.