Subversion Repositories Kolibri OS

Rev

Rev 3746 | Rev 4293 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3746 Rev 4104
1
/*
1
/*
2
 * Copyright © 2006-2010 Intel Corporation
2
 * Copyright © 2006-2010 Intel Corporation
3
 * Copyright (c) 2006 Dave Airlie 
3
 * Copyright (c) 2006 Dave Airlie 
4
 *
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * copy of this software and associated documentation files (the "Software"),
6
 * copy of this software and associated documentation files (the "Software"),
7
 * to deal in the Software without restriction, including without limitation
7
 * to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following conditions:
10
 * Software is furnished to do so, subject to the following conditions:
11
 *
11
 *
12
 * The above copyright notice and this permission notice (including the next
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
14
 * Software.
15
 *
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
22
 * DEALINGS IN THE SOFTWARE.
23
 *
23
 *
24
 * Authors:
24
 * Authors:
25
 *	Eric Anholt 
25
 *	Eric Anholt 
26
 *      Dave Airlie 
26
 *      Dave Airlie 
27
 *      Jesse Barnes 
27
 *      Jesse Barnes 
28
 *      Chris Wilson 
28
 *      Chris Wilson 
29
 */
29
 */
30
 
30
 
31
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32
 
32
 
33
#include 
33
#include 
34
#include "intel_drv.h"
34
#include "intel_drv.h"
35
 
35
 
36
#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
36
#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
37
 
37
 
38
void
38
void
39
intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
39
intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
40
		       struct drm_display_mode *adjusted_mode)
40
		       struct drm_display_mode *adjusted_mode)
41
{
41
{
42
	adjusted_mode->hdisplay = fixed_mode->hdisplay;
-
 
43
	adjusted_mode->hsync_start = fixed_mode->hsync_start;
-
 
44
	adjusted_mode->hsync_end = fixed_mode->hsync_end;
-
 
45
	adjusted_mode->htotal = fixed_mode->htotal;
-
 
46
 
-
 
47
	adjusted_mode->vdisplay = fixed_mode->vdisplay;
-
 
48
	adjusted_mode->vsync_start = fixed_mode->vsync_start;
-
 
49
	adjusted_mode->vsync_end = fixed_mode->vsync_end;
42
	drm_mode_copy(adjusted_mode, fixed_mode);
50
	adjusted_mode->vtotal = fixed_mode->vtotal;
-
 
51
 
43
 
52
	adjusted_mode->clock = fixed_mode->clock;
44
	drm_mode_set_crtcinfo(adjusted_mode, 0);
53
}
45
}
54
 
46
 
55
/* adjusted_mode has been preset to be the panel's fixed mode */
47
/* adjusted_mode has been preset to be the panel's fixed mode */
56
void
48
void
57
intel_pch_panel_fitting(struct drm_device *dev,
49
intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
-
 
50
			struct intel_crtc_config *pipe_config,
58
			int fitting_mode,
51
			int fitting_mode)
59
			const struct drm_display_mode *mode,
-
 
60
			struct drm_display_mode *adjusted_mode)
-
 
61
{
52
{
62
	struct drm_i915_private *dev_priv = dev->dev_private;
53
	struct drm_display_mode *mode, *adjusted_mode;
63
	int x, y, width, height;
54
	int x, y, width, height;
-
 
55
 
-
 
56
	mode = &pipe_config->requested_mode;
-
 
57
	adjusted_mode = &pipe_config->adjusted_mode;
64
 
58
 
65
	x = y = width = height = 0;
59
	x = y = width = height = 0;
66
 
60
 
67
	/* Native modes don't need fitting */
61
	/* Native modes don't need fitting */
68
	if (adjusted_mode->hdisplay == mode->hdisplay &&
62
	if (adjusted_mode->hdisplay == mode->hdisplay &&
69
	    adjusted_mode->vdisplay == mode->vdisplay)
63
	    adjusted_mode->vdisplay == mode->vdisplay)
70
		goto done;
64
		goto done;
71
 
65
 
72
	switch (fitting_mode) {
66
	switch (fitting_mode) {
73
	case DRM_MODE_SCALE_CENTER:
67
	case DRM_MODE_SCALE_CENTER:
74
		width = mode->hdisplay;
68
		width = mode->hdisplay;
75
		height = mode->vdisplay;
69
		height = mode->vdisplay;
76
		x = (adjusted_mode->hdisplay - width + 1)/2;
70
		x = (adjusted_mode->hdisplay - width + 1)/2;
77
		y = (adjusted_mode->vdisplay - height + 1)/2;
71
		y = (adjusted_mode->vdisplay - height + 1)/2;
78
		break;
72
		break;
79
 
73
 
80
	case DRM_MODE_SCALE_ASPECT:
74
	case DRM_MODE_SCALE_ASPECT:
81
		/* Scale but preserve the aspect ratio */
75
		/* Scale but preserve the aspect ratio */
82
		{
76
		{
83
			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
77
			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
84
			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
78
			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
85
			if (scaled_width > scaled_height) { /* pillar */
79
			if (scaled_width > scaled_height) { /* pillar */
86
				width = scaled_height / mode->vdisplay;
80
				width = scaled_height / mode->vdisplay;
87
				if (width & 1)
81
				if (width & 1)
88
				    	width++;
82
				    	width++;
89
				x = (adjusted_mode->hdisplay - width + 1) / 2;
83
				x = (adjusted_mode->hdisplay - width + 1) / 2;
90
				y = 0;
84
				y = 0;
91
				height = adjusted_mode->vdisplay;
85
				height = adjusted_mode->vdisplay;
92
			} else if (scaled_width < scaled_height) { /* letter */
86
			} else if (scaled_width < scaled_height) { /* letter */
93
				height = scaled_width / mode->hdisplay;
87
				height = scaled_width / mode->hdisplay;
94
				if (height & 1)
88
				if (height & 1)
95
				    height++;
89
				    height++;
96
				y = (adjusted_mode->vdisplay - height + 1) / 2;
90
				y = (adjusted_mode->vdisplay - height + 1) / 2;
97
				x = 0;
91
				x = 0;
98
				width = adjusted_mode->hdisplay;
92
				width = adjusted_mode->hdisplay;
99
			} else {
93
			} else {
100
				x = y = 0;
94
				x = y = 0;
101
				width = adjusted_mode->hdisplay;
95
				width = adjusted_mode->hdisplay;
102
				height = adjusted_mode->vdisplay;
96
				height = adjusted_mode->vdisplay;
103
			}
97
			}
104
		}
98
		}
105
		break;
99
		break;
106
 
-
 
107
	default:
100
 
108
	case DRM_MODE_SCALE_FULLSCREEN:
101
	case DRM_MODE_SCALE_FULLSCREEN:
109
		x = y = 0;
102
		x = y = 0;
110
		width = adjusted_mode->hdisplay;
103
		width = adjusted_mode->hdisplay;
111
		height = adjusted_mode->vdisplay;
104
		height = adjusted_mode->vdisplay;
112
		break;
105
		break;
-
 
106
 
-
 
107
	default:
-
 
108
		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
-
 
109
		return;
113
	}
110
	}
114
 
111
 
115
done:
112
done:
116
	dev_priv->pch_pf_pos = (x << 16) | y;
113
	pipe_config->pch_pfit.pos = (x << 16) | y;
117
	dev_priv->pch_pf_size = (width << 16) | height;
114
	pipe_config->pch_pfit.size = (width << 16) | height;
-
 
115
	pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
-
 
116
}
-
 
117
 
-
 
118
static void
-
 
119
centre_horizontally(struct drm_display_mode *mode,
-
 
120
		    int width)
-
 
121
{
-
 
122
	u32 border, sync_pos, blank_width, sync_width;
-
 
123
 
-
 
124
	/* keep the hsync and hblank widths constant */
-
 
125
	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
-
 
126
	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
-
 
127
	sync_pos = (blank_width - sync_width + 1) / 2;
-
 
128
 
-
 
129
	border = (mode->hdisplay - width + 1) / 2;
-
 
130
	border += border & 1; /* make the border even */
-
 
131
 
-
 
132
	mode->crtc_hdisplay = width;
-
 
133
	mode->crtc_hblank_start = width + border;
-
 
134
	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
-
 
135
 
-
 
136
	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
-
 
137
	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
-
 
138
}
-
 
139
 
-
 
140
static void
-
 
141
centre_vertically(struct drm_display_mode *mode,
-
 
142
		  int height)
-
 
143
{
-
 
144
	u32 border, sync_pos, blank_width, sync_width;
-
 
145
 
-
 
146
	/* keep the vsync and vblank widths constant */
-
 
147
	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
-
 
148
	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
-
 
149
	sync_pos = (blank_width - sync_width + 1) / 2;
-
 
150
 
-
 
151
	border = (mode->vdisplay - height + 1) / 2;
-
 
152
 
-
 
153
	mode->crtc_vdisplay = height;
-
 
154
	mode->crtc_vblank_start = height + border;
-
 
155
	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
-
 
156
 
-
 
157
	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
-
 
158
	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
-
 
159
}
-
 
160
 
-
 
161
static inline u32 panel_fitter_scaling(u32 source, u32 target)
-
 
162
{
-
 
163
	/*
-
 
164
	 * Floating point operation is not supported. So the FACTOR
-
 
165
	 * is defined, which can avoid the floating point computation
-
 
166
	 * when calculating the panel ratio.
-
 
167
	 */
-
 
168
#define ACCURACY 12
-
 
169
#define FACTOR (1 << ACCURACY)
-
 
170
	u32 ratio = source * FACTOR / target;
-
 
171
	return (FACTOR * ratio + FACTOR/2) / FACTOR;
-
 
172
}
-
 
173
 
-
 
174
void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
-
 
175
			      struct intel_crtc_config *pipe_config,
-
 
176
			      int fitting_mode)
-
 
177
{
-
 
178
	struct drm_device *dev = intel_crtc->base.dev;
-
 
179
	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
-
 
180
	struct drm_display_mode *mode, *adjusted_mode;
-
 
181
 
-
 
182
	mode = &pipe_config->requested_mode;
-
 
183
	adjusted_mode = &pipe_config->adjusted_mode;
-
 
184
 
-
 
185
	/* Native modes don't need fitting */
-
 
186
	if (adjusted_mode->hdisplay == mode->hdisplay &&
-
 
187
	    adjusted_mode->vdisplay == mode->vdisplay)
-
 
188
		goto out;
-
 
189
 
-
 
190
	switch (fitting_mode) {
-
 
191
	case DRM_MODE_SCALE_CENTER:
-
 
192
		/*
-
 
193
		 * For centered modes, we have to calculate border widths &
-
 
194
		 * heights and modify the values programmed into the CRTC.
-
 
195
		 */
-
 
196
		centre_horizontally(adjusted_mode, mode->hdisplay);
-
 
197
		centre_vertically(adjusted_mode, mode->vdisplay);
-
 
198
		border = LVDS_BORDER_ENABLE;
-
 
199
		break;
-
 
200
	case DRM_MODE_SCALE_ASPECT:
-
 
201
		/* Scale but preserve the aspect ratio */
-
 
202
		if (INTEL_INFO(dev)->gen >= 4) {
-
 
203
			u32 scaled_width = adjusted_mode->hdisplay *
-
 
204
				mode->vdisplay;
-
 
205
			u32 scaled_height = mode->hdisplay *
-
 
206
				adjusted_mode->vdisplay;
-
 
207
 
-
 
208
			/* 965+ is easy, it does everything in hw */
-
 
209
			if (scaled_width > scaled_height)
-
 
210
				pfit_control |= PFIT_ENABLE |
-
 
211
					PFIT_SCALING_PILLAR;
-
 
212
			else if (scaled_width < scaled_height)
-
 
213
				pfit_control |= PFIT_ENABLE |
-
 
214
					PFIT_SCALING_LETTER;
-
 
215
			else if (adjusted_mode->hdisplay != mode->hdisplay)
-
 
216
				pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
-
 
217
		} else {
-
 
218
			u32 scaled_width = adjusted_mode->hdisplay *
-
 
219
				mode->vdisplay;
-
 
220
			u32 scaled_height = mode->hdisplay *
-
 
221
				adjusted_mode->vdisplay;
-
 
222
			/*
-
 
223
			 * For earlier chips we have to calculate the scaling
-
 
224
			 * ratio by hand and program it into the
-
 
225
			 * PFIT_PGM_RATIO register
-
 
226
			 */
-
 
227
			if (scaled_width > scaled_height) { /* pillar */
-
 
228
				centre_horizontally(adjusted_mode,
-
 
229
						    scaled_height /
-
 
230
						    mode->vdisplay);
-
 
231
 
-
 
232
				border = LVDS_BORDER_ENABLE;
-
 
233
				if (mode->vdisplay != adjusted_mode->vdisplay) {
-
 
234
					u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
-
 
235
					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
-
 
236
							    bits << PFIT_VERT_SCALE_SHIFT);
-
 
237
					pfit_control |= (PFIT_ENABLE |
-
 
238
							 VERT_INTERP_BILINEAR |
-
 
239
							 HORIZ_INTERP_BILINEAR);
-
 
240
				}
-
 
241
			} else if (scaled_width < scaled_height) { /* letter */
-
 
242
				centre_vertically(adjusted_mode,
-
 
243
						  scaled_width /
-
 
244
						  mode->hdisplay);
-
 
245
 
-
 
246
				border = LVDS_BORDER_ENABLE;
-
 
247
				if (mode->hdisplay != adjusted_mode->hdisplay) {
-
 
248
					u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
-
 
249
					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
-
 
250
							    bits << PFIT_VERT_SCALE_SHIFT);
-
 
251
					pfit_control |= (PFIT_ENABLE |
-
 
252
							 VERT_INTERP_BILINEAR |
-
 
253
							 HORIZ_INTERP_BILINEAR);
-
 
254
				}
-
 
255
			} else {
-
 
256
				/* Aspects match, Let hw scale both directions */
-
 
257
				pfit_control |= (PFIT_ENABLE |
-
 
258
						 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
-
 
259
						 VERT_INTERP_BILINEAR |
-
 
260
						 HORIZ_INTERP_BILINEAR);
-
 
261
			}
-
 
262
		}
-
 
263
		break;
-
 
264
	case DRM_MODE_SCALE_FULLSCREEN:
-
 
265
		/*
-
 
266
		 * Full scaling, even if it changes the aspect ratio.
-
 
267
		 * Fortunately this is all done for us in hw.
-
 
268
		 */
-
 
269
		if (mode->vdisplay != adjusted_mode->vdisplay ||
-
 
270
		    mode->hdisplay != adjusted_mode->hdisplay) {
-
 
271
			pfit_control |= PFIT_ENABLE;
-
 
272
			if (INTEL_INFO(dev)->gen >= 4)
-
 
273
				pfit_control |= PFIT_SCALING_AUTO;
-
 
274
			else
-
 
275
				pfit_control |= (VERT_AUTO_SCALE |
-
 
276
						 VERT_INTERP_BILINEAR |
-
 
277
						 HORIZ_AUTO_SCALE |
-
 
278
						 HORIZ_INTERP_BILINEAR);
-
 
279
		}
-
 
280
		break;
-
 
281
	default:
-
 
282
		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
-
 
283
		return;
-
 
284
	}
-
 
285
 
-
 
286
	/* 965+ wants fuzzy fitting */
-
 
287
	/* FIXME: handle multiple panels by failing gracefully */
-
 
288
	if (INTEL_INFO(dev)->gen >= 4)
-
 
289
		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
-
 
290
				 PFIT_FILTER_FUZZY);
-
 
291
 
-
 
292
out:
-
 
293
	if ((pfit_control & PFIT_ENABLE) == 0) {
-
 
294
		pfit_control = 0;
-
 
295
		pfit_pgm_ratios = 0;
-
 
296
	}
-
 
297
 
-
 
298
	/* Make sure pre-965 set dither correctly for 18bpp panels. */
-
 
299
	if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
-
 
300
		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-
 
301
 
-
 
302
	pipe_config->gmch_pfit.control = pfit_control;
-
 
303
	pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
-
 
304
	pipe_config->gmch_pfit.lvds_border_bits = border;
118
}
305
}
119
 
306
 
120
static int is_backlight_combination_mode(struct drm_device *dev)
307
static int is_backlight_combination_mode(struct drm_device *dev)
121
{
308
{
122
	struct drm_i915_private *dev_priv = dev->dev_private;
309
	struct drm_i915_private *dev_priv = dev->dev_private;
123
 
310
 
124
	if (INTEL_INFO(dev)->gen >= 4)
311
	if (INTEL_INFO(dev)->gen >= 4)
125
		return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
312
		return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
126
 
313
 
127
	if (IS_GEN2(dev))
314
	if (IS_GEN2(dev))
128
		return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
315
		return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
129
 
316
 
130
	return 0;
317
	return 0;
131
}
318
}
-
 
319
 
-
 
320
/* XXX: query mode clock or hardware clock and program max PWM appropriately
-
 
321
 * when it's 0.
132
 
322
 */
133
static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
323
static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
134
{
324
{
135
	struct drm_i915_private *dev_priv = dev->dev_private;
325
	struct drm_i915_private *dev_priv = dev->dev_private;
136
	u32 val;
326
	u32 val;
-
 
327
 
-
 
328
//   WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock));
137
 
329
 
138
	/* Restore the CTL value if it lost, e.g. GPU reset */
330
	/* Restore the CTL value if it lost, e.g. GPU reset */
139
 
331
 
140
	if (HAS_PCH_SPLIT(dev_priv->dev)) {
332
	if (HAS_PCH_SPLIT(dev_priv->dev)) {
141
		val = I915_READ(BLC_PWM_PCH_CTL2);
333
		val = I915_READ(BLC_PWM_PCH_CTL2);
142
		if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) {
334
		if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) {
143
			dev_priv->regfile.saveBLC_PWM_CTL2 = val;
335
			dev_priv->regfile.saveBLC_PWM_CTL2 = val;
144
		} else if (val == 0) {
336
		} else if (val == 0) {
145
			val = dev_priv->regfile.saveBLC_PWM_CTL2;
337
			val = dev_priv->regfile.saveBLC_PWM_CTL2;
146
			I915_WRITE(BLC_PWM_PCH_CTL2, val);
338
			I915_WRITE(BLC_PWM_PCH_CTL2, val);
147
		}
339
		}
148
	} else {
340
	} else {
149
		val = I915_READ(BLC_PWM_CTL);
341
		val = I915_READ(BLC_PWM_CTL);
150
		if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
342
		if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
151
			dev_priv->regfile.saveBLC_PWM_CTL = val;
343
			dev_priv->regfile.saveBLC_PWM_CTL = val;
152
			if (INTEL_INFO(dev)->gen >= 4)
344
			if (INTEL_INFO(dev)->gen >= 4)
153
				dev_priv->regfile.saveBLC_PWM_CTL2 =
345
				dev_priv->regfile.saveBLC_PWM_CTL2 =
154
					I915_READ(BLC_PWM_CTL2);
346
					I915_READ(BLC_PWM_CTL2);
155
		} else if (val == 0) {
347
		} else if (val == 0) {
156
			val = dev_priv->regfile.saveBLC_PWM_CTL;
348
			val = dev_priv->regfile.saveBLC_PWM_CTL;
157
			I915_WRITE(BLC_PWM_CTL, val);
349
			I915_WRITE(BLC_PWM_CTL, val);
158
			if (INTEL_INFO(dev)->gen >= 4)
350
			if (INTEL_INFO(dev)->gen >= 4)
159
			I915_WRITE(BLC_PWM_CTL2,
351
			I915_WRITE(BLC_PWM_CTL2,
160
					   dev_priv->regfile.saveBLC_PWM_CTL2);
352
					   dev_priv->regfile.saveBLC_PWM_CTL2);
161
		}
353
		}
162
	}
354
	}
163
 
355
 
164
	return val;
356
	return val;
165
}
357
}
166
 
358
 
167
static u32 _intel_panel_get_max_backlight(struct drm_device *dev)
359
static u32 intel_panel_get_max_backlight(struct drm_device *dev)
168
{
360
{
169
	u32 max;
361
	u32 max;
170
 
362
 
171
	max = i915_read_blc_pwm_ctl(dev);
363
	max = i915_read_blc_pwm_ctl(dev);
172
 
364
 
173
	if (HAS_PCH_SPLIT(dev)) {
365
	if (HAS_PCH_SPLIT(dev)) {
174
		max >>= 16;
366
		max >>= 16;
175
	} else {
367
	} else {
176
		if (INTEL_INFO(dev)->gen < 4)
368
		if (INTEL_INFO(dev)->gen < 4)
177
			max >>= 17;
369
			max >>= 17;
178
		else
370
		else
179
			max >>= 16;
371
			max >>= 16;
180
 
372
 
181
		if (is_backlight_combination_mode(dev))
373
		if (is_backlight_combination_mode(dev))
182
			max *= 0xff;
374
			max *= 0xff;
183
	}
375
	}
184
 
-
 
185
	return max;
-
 
186
}
-
 
187
 
-
 
188
u32 intel_panel_get_max_backlight(struct drm_device *dev)
-
 
189
{
-
 
190
	u32 max;
-
 
191
 
-
 
192
	max = _intel_panel_get_max_backlight(dev);
-
 
193
	if (max == 0) {
-
 
194
		/* XXX add code here to query mode clock or hardware clock
-
 
195
		 * and program max PWM appropriately.
-
 
196
		 */
-
 
197
		pr_warn_once("fixme: max PWM is zero\n");
-
 
198
		return 1;
-
 
199
	}
-
 
200
 
376
 
-
 
377
	DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
201
	DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
378
 
202
	return max;
379
	return max;
203
}
380
}
204
 
381
 
205
static int i915_panel_invert_brightness;
382
static int i915_panel_invert_brightness;
206
MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
383
MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
207
	"(-1 force normal, 0 machine defaults, 1 force inversion), please "
384
	"(-1 force normal, 0 machine defaults, 1 force inversion), please "
208
	"report PCI device ID, subsystem vendor and subsystem device ID "
385
	"report PCI device ID, subsystem vendor and subsystem device ID "
209
	"to dri-devel@lists.freedesktop.org, if your machine needs it. "
386
	"to dri-devel@lists.freedesktop.org, if your machine needs it. "
210
	"It will then be included in an upcoming module version.");
387
	"It will then be included in an upcoming module version.");
211
module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
388
module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
212
static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val)
389
static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val)
213
{
390
{
214
	struct drm_i915_private *dev_priv = dev->dev_private;
391
	struct drm_i915_private *dev_priv = dev->dev_private;
215
 
392
 
216
	if (i915_panel_invert_brightness < 0)
393
	if (i915_panel_invert_brightness < 0)
217
		return val;
394
		return val;
218
 
395
 
219
	if (i915_panel_invert_brightness > 0 ||
396
	if (i915_panel_invert_brightness > 0 ||
220
	    dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS)
397
	    dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
221
		return intel_panel_get_max_backlight(dev) - val;
398
		u32 max = intel_panel_get_max_backlight(dev);
-
 
399
		if (max)
-
 
400
			return max - val;
-
 
401
	}
222
 
402
 
223
	return val;
403
	return val;
224
}
404
}
225
 
405
 
226
static u32 intel_panel_get_backlight(struct drm_device *dev)
406
static u32 intel_panel_get_backlight(struct drm_device *dev)
227
{
407
{
228
	struct drm_i915_private *dev_priv = dev->dev_private;
408
	struct drm_i915_private *dev_priv = dev->dev_private;
229
	u32 val;
409
	u32 val;
-
 
410
	unsigned long flags;
-
 
411
 
-
 
412
	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
230
 
413
 
231
	if (HAS_PCH_SPLIT(dev)) {
414
	if (HAS_PCH_SPLIT(dev)) {
232
		val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
415
		val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
233
	} else {
416
	} else {
234
		val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
417
		val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
235
		if (INTEL_INFO(dev)->gen < 4)
418
		if (INTEL_INFO(dev)->gen < 4)
236
			val >>= 1;
419
			val >>= 1;
237
 
420
 
238
		if (is_backlight_combination_mode(dev)) {
421
		if (is_backlight_combination_mode(dev)) {
239
			u8 lbpc;
422
			u8 lbpc;
240
 
423
 
241
			pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
424
			pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
242
			val *= lbpc;
425
			val *= lbpc;
243
		}
426
		}
244
	}
427
	}
245
 
428
 
246
	val = intel_panel_compute_brightness(dev, val);
429
	val = intel_panel_compute_brightness(dev, val);
-
 
430
 
-
 
431
	spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
 
432
 
247
	DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
433
	DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
248
	return val;
434
	return val;
249
}
435
}
250
 
436
 
251
static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
437
static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
252
{
438
{
253
	struct drm_i915_private *dev_priv = dev->dev_private;
439
	struct drm_i915_private *dev_priv = dev->dev_private;
254
	u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
440
	u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
255
	I915_WRITE(BLC_PWM_CPU_CTL, val | level);
441
	I915_WRITE(BLC_PWM_CPU_CTL, val | level);
256
}
442
}
257
 
443
 
258
static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
444
static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
259
{
445
{
260
	struct drm_i915_private *dev_priv = dev->dev_private;
446
	struct drm_i915_private *dev_priv = dev->dev_private;
261
	u32 tmp;
447
	u32 tmp;
262
 
448
 
263
	DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
449
	DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
264
	level = intel_panel_compute_brightness(dev, level);
450
	level = intel_panel_compute_brightness(dev, level);
265
 
451
 
266
	if (HAS_PCH_SPLIT(dev))
452
	if (HAS_PCH_SPLIT(dev))
267
		return intel_pch_panel_set_backlight(dev, level);
453
		return intel_pch_panel_set_backlight(dev, level);
268
 
454
 
269
	if (is_backlight_combination_mode(dev)) {
455
	if (is_backlight_combination_mode(dev)) {
270
		u32 max = intel_panel_get_max_backlight(dev);
456
		u32 max = intel_panel_get_max_backlight(dev);
271
		u8 lbpc;
457
		u8 lbpc;
-
 
458
 
-
 
459
		/* we're screwed, but keep behaviour backwards compatible */
-
 
460
		if (!max)
-
 
461
			max = 1;
272
 
462
 
273
		lbpc = level * 0xfe / max + 1;
463
		lbpc = level * 0xfe / max + 1;
274
		level /= lbpc;
464
		level /= lbpc;
275
		pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
465
		pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
276
	}
466
	}
277
 
467
 
278
	tmp = I915_READ(BLC_PWM_CTL);
468
	tmp = I915_READ(BLC_PWM_CTL);
279
	if (INTEL_INFO(dev)->gen < 4)
469
	if (INTEL_INFO(dev)->gen < 4)
280
		level <<= 1;
470
		level <<= 1;
281
		tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
471
		tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
282
	I915_WRITE(BLC_PWM_CTL, tmp | level);
472
	I915_WRITE(BLC_PWM_CTL, tmp | level);
283
}
473
}
-
 
474
 
284
 
475
/* set backlight brightness to level in range [0..max] */
285
void intel_panel_set_backlight(struct drm_device *dev, u32 level)
476
void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
286
{
477
{
287
	struct drm_i915_private *dev_priv = dev->dev_private;
478
	struct drm_i915_private *dev_priv = dev->dev_private;
288
 
479
 
289
	dev_priv->backlight.level = level;
480
	dev_priv->backlight.level = level;
290
//   if (dev_priv->backlight.device)
481
//   if (dev_priv->backlight.device)
291
//       dev_priv->backlight.device->props.brightness = level;
482
//       dev_priv->backlight.device->props.brightness = level;
292
 
483
 
293
//   if (dev_priv->backlight.enabled)
484
//   if (dev_priv->backlight.enabled)
294
//       intel_panel_actually_set_backlight(dev, level);
485
//       intel_panel_actually_set_backlight(dev, level);
295
}
486
}
296
 
487
 
297
void intel_panel_disable_backlight(struct drm_device *dev)
488
void intel_panel_disable_backlight(struct drm_device *dev)
298
{
489
{
299
	struct drm_i915_private *dev_priv = dev->dev_private;
490
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
491
	unsigned long flags;
-
 
492
 
-
 
493
	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
300
 
494
 
301
	dev_priv->backlight.enabled = false;
495
	dev_priv->backlight.enabled = false;
302
	intel_panel_actually_set_backlight(dev, 0);
496
	intel_panel_actually_set_backlight(dev, 0);
303
 
497
 
304
	if (INTEL_INFO(dev)->gen >= 4) {
498
	if (INTEL_INFO(dev)->gen >= 4) {
305
		uint32_t reg, tmp;
499
		uint32_t reg, tmp;
306
 
500
 
307
		reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
501
		reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
308
 
502
 
309
		I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
503
		I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
310
 
504
 
311
		if (HAS_PCH_SPLIT(dev)) {
505
		if (HAS_PCH_SPLIT(dev)) {
312
			tmp = I915_READ(BLC_PWM_PCH_CTL1);
506
			tmp = I915_READ(BLC_PWM_PCH_CTL1);
313
			tmp &= ~BLM_PCH_PWM_ENABLE;
507
			tmp &= ~BLM_PCH_PWM_ENABLE;
314
			I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
508
			I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
315
		}
509
		}
316
	}
510
	}
-
 
511
 
-
 
512
	spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
317
}
513
}
318
 
514
 
319
void intel_panel_enable_backlight(struct drm_device *dev,
515
void intel_panel_enable_backlight(struct drm_device *dev,
320
				  enum pipe pipe)
516
				  enum pipe pipe)
321
{
517
{
322
	struct drm_i915_private *dev_priv = dev->dev_private;
518
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
519
	enum transcoder cpu_transcoder =
-
 
520
		intel_pipe_to_cpu_transcoder(dev_priv, pipe);
-
 
521
	unsigned long flags;
-
 
522
 
-
 
523
	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
323
 
524
 
324
	if (dev_priv->backlight.level == 0) {
525
	if (dev_priv->backlight.level == 0) {
325
		dev_priv->backlight.level = intel_panel_get_max_backlight(dev);
526
		dev_priv->backlight.level = intel_panel_get_max_backlight(dev);
326
//       if (dev_priv->backlight.device)
527
//       if (dev_priv->backlight.device)
327
//           dev_priv->backlight.device->props.brightness =
528
//           dev_priv->backlight.device->props.brightness =
328
//               dev_priv->backlight.level;
529
//               dev_priv->backlight.level;
329
	}
530
	}
330
 
531
 
331
	if (INTEL_INFO(dev)->gen >= 4) {
532
	if (INTEL_INFO(dev)->gen >= 4) {
332
		uint32_t reg, tmp;
533
		uint32_t reg, tmp;
333
 
534
 
334
		reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
535
		reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2;
335
 
536
 
336
 
537
 
337
		tmp = I915_READ(reg);
538
		tmp = I915_READ(reg);
338
 
539
 
339
		/* Note that this can also get called through dpms changes. And
540
		/* Note that this can also get called through dpms changes. And
340
		 * we don't track the backlight dpms state, hence check whether
541
		 * we don't track the backlight dpms state, hence check whether
341
		 * we have to do anything first. */
542
		 * we have to do anything first. */
342
		if (tmp & BLM_PWM_ENABLE)
543
		if (tmp & BLM_PWM_ENABLE)
343
			goto set_level;
544
			goto set_level;
344
 
545
 
345
		if (INTEL_INFO(dev)->num_pipes == 3)
546
		if (INTEL_INFO(dev)->num_pipes == 3)
346
			tmp &= ~BLM_PIPE_SELECT_IVB;
547
			tmp &= ~BLM_PIPE_SELECT_IVB;
347
		else
548
		else
348
			tmp &= ~BLM_PIPE_SELECT;
549
			tmp &= ~BLM_PIPE_SELECT;
-
 
550
 
-
 
551
		if (cpu_transcoder == TRANSCODER_EDP)
-
 
552
			tmp |= BLM_TRANSCODER_EDP;
349
 
553
		else
350
		tmp |= BLM_PIPE(pipe);
554
			tmp |= BLM_PIPE(cpu_transcoder);
351
		tmp &= ~BLM_PWM_ENABLE;
555
		tmp &= ~BLM_PWM_ENABLE;
352
 
556
 
353
		I915_WRITE(reg, tmp);
557
		I915_WRITE(reg, tmp);
354
		POSTING_READ(reg);
558
		POSTING_READ(reg);
355
		I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
559
		I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
356
 
560
 
-
 
561
		if (HAS_PCH_SPLIT(dev) &&
357
		if (HAS_PCH_SPLIT(dev)) {
562
		    !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
358
			tmp = I915_READ(BLC_PWM_PCH_CTL1);
563
			tmp = I915_READ(BLC_PWM_PCH_CTL1);
359
			tmp |= BLM_PCH_PWM_ENABLE;
564
			tmp |= BLM_PCH_PWM_ENABLE;
360
			tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
565
			tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
361
			I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
566
			I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
362
		}
567
		}
363
	}
568
	}
364
 
569
 
365
set_level:
570
set_level:
366
	/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
571
	/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
367
	 * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
572
	 * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
368
	 * registers are set.
573
	 * registers are set.
369
	 */
574
	 */
370
	dev_priv->backlight.enabled = true;
575
	dev_priv->backlight.enabled = true;
371
	intel_panel_actually_set_backlight(dev, dev_priv->backlight.level);
576
	intel_panel_actually_set_backlight(dev, dev_priv->backlight.level);
-
 
577
 
-
 
578
	spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
372
}
579
}
373
 
580
 
374
static void intel_panel_init_backlight(struct drm_device *dev)
581
static void intel_panel_init_backlight(struct drm_device *dev)
375
{
582
{
376
	struct drm_i915_private *dev_priv = dev->dev_private;
583
	struct drm_i915_private *dev_priv = dev->dev_private;
377
 
584
 
378
	dev_priv->backlight.level = intel_panel_get_backlight(dev);
585
	dev_priv->backlight.level = intel_panel_get_backlight(dev);
379
	dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
586
	dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
380
}
587
}
381
 
588
 
382
enum drm_connector_status
589
enum drm_connector_status
383
intel_panel_detect(struct drm_device *dev)
590
intel_panel_detect(struct drm_device *dev)
384
{
591
{
385
	struct drm_i915_private *dev_priv = dev->dev_private;
592
	struct drm_i915_private *dev_priv = dev->dev_private;
386
 
593
 
387
	/* Assume that the BIOS does not lie through the OpRegion... */
594
	/* Assume that the BIOS does not lie through the OpRegion... */
388
	if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) {
595
	if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) {
389
		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
596
		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
390
			connector_status_connected :
597
			connector_status_connected :
391
			connector_status_disconnected;
598
			connector_status_disconnected;
392
	}
599
	}
393
 
600
 
394
	switch (i915_panel_ignore_lid) {
601
	switch (i915_panel_ignore_lid) {
395
	case -2:
602
	case -2:
396
		return connector_status_connected;
603
		return connector_status_connected;
397
	case -1:
604
	case -1:
398
		return connector_status_disconnected;
605
		return connector_status_disconnected;
399
	default:
606
	default:
400
	return connector_status_unknown;
607
	return connector_status_unknown;
401
	}
608
	}
402
}
609
}
403
 
610
 
404
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
611
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
405
static int intel_panel_update_status(struct backlight_device *bd)
612
static int intel_panel_update_status(struct backlight_device *bd)
406
{
613
{
407
	struct drm_device *dev = bl_get_data(bd);
614
	struct drm_device *dev = bl_get_data(bd);
408
	intel_panel_set_backlight(dev, bd->props.brightness);
615
	intel_panel_set_backlight(dev, bd->props.brightness,
-
 
616
				  bd->props.max_brightness);
409
	return 0;
617
	return 0;
410
}
618
}
411
 
619
 
412
static int intel_panel_get_brightness(struct backlight_device *bd)
620
static int intel_panel_get_brightness(struct backlight_device *bd)
413
{
621
{
414
	struct drm_device *dev = bl_get_data(bd);
622
	struct drm_device *dev = bl_get_data(bd);
415
	return intel_panel_get_backlight(dev);
623
	return intel_panel_get_backlight(dev);
416
}
624
}
417
 
625
 
418
static const struct backlight_ops intel_panel_bl_ops = {
626
static const struct backlight_ops intel_panel_bl_ops = {
419
	.update_status = intel_panel_update_status,
627
	.update_status = intel_panel_update_status,
420
	.get_brightness = intel_panel_get_brightness,
628
	.get_brightness = intel_panel_get_brightness,
421
};
629
};
422
 
630
 
423
int intel_panel_setup_backlight(struct drm_connector *connector)
631
int intel_panel_setup_backlight(struct drm_connector *connector)
424
{
632
{
425
	struct drm_device *dev = connector->dev;
633
	struct drm_device *dev = connector->dev;
426
	struct drm_i915_private *dev_priv = dev->dev_private;
634
	struct drm_i915_private *dev_priv = dev->dev_private;
427
	struct backlight_properties props;
635
	struct backlight_properties props;
-
 
636
	unsigned long flags;
428
 
637
 
429
	intel_panel_init_backlight(dev);
638
	intel_panel_init_backlight(dev);
430
 
639
 
431
	if (WARN_ON(dev_priv->backlight.device))
640
	if (WARN_ON(dev_priv->backlight.device))
432
		return -ENODEV;
641
		return -ENODEV;
433
 
642
 
434
	memset(&props, 0, sizeof(props));
643
	memset(&props, 0, sizeof(props));
435
	props.type = BACKLIGHT_RAW;
644
	props.type = BACKLIGHT_RAW;
436
	props.brightness = dev_priv->backlight.level;
645
	props.brightness = dev_priv->backlight.level;
-
 
646
 
-
 
647
	spin_lock_irqsave(&dev_priv->backlight.lock, flags);
437
	props.max_brightness = _intel_panel_get_max_backlight(dev);
648
	props.max_brightness = intel_panel_get_max_backlight(dev);
-
 
649
	spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
 
650
 
438
	if (props.max_brightness == 0) {
651
	if (props.max_brightness == 0) {
439
		DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
652
		DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
440
		return -ENODEV;
653
		return -ENODEV;
441
	}
654
	}
442
	dev_priv->backlight.device =
655
	dev_priv->backlight.device =
443
		backlight_device_register("intel_backlight",
656
		backlight_device_register("intel_backlight",
444
					  &connector->kdev, dev,
657
					  &connector->kdev, dev,
445
					  &intel_panel_bl_ops, &props);
658
					  &intel_panel_bl_ops, &props);
446
 
659
 
447
	if (IS_ERR(dev_priv->backlight.device)) {
660
	if (IS_ERR(dev_priv->backlight.device)) {
448
		DRM_ERROR("Failed to register backlight: %ld\n",
661
		DRM_ERROR("Failed to register backlight: %ld\n",
449
			  PTR_ERR(dev_priv->backlight.device));
662
			  PTR_ERR(dev_priv->backlight.device));
450
		dev_priv->backlight.device = NULL;
663
		dev_priv->backlight.device = NULL;
451
		return -ENODEV;
664
		return -ENODEV;
452
	}
665
	}
453
	return 0;
666
	return 0;
454
}
667
}
455
 
668
 
456
void intel_panel_destroy_backlight(struct drm_device *dev)
669
void intel_panel_destroy_backlight(struct drm_device *dev)
457
{
670
{
458
	struct drm_i915_private *dev_priv = dev->dev_private;
671
	struct drm_i915_private *dev_priv = dev->dev_private;
459
	if (dev_priv->backlight.device) {
672
	if (dev_priv->backlight.device) {
460
		backlight_device_unregister(dev_priv->backlight.device);
673
		backlight_device_unregister(dev_priv->backlight.device);
461
		dev_priv->backlight.device = NULL;
674
		dev_priv->backlight.device = NULL;
462
	}
675
	}
463
}
676
}
464
#else
677
#else
465
int intel_panel_setup_backlight(struct drm_connector *connector)
678
int intel_panel_setup_backlight(struct drm_connector *connector)
466
{
679
{
467
	intel_panel_init_backlight(connector->dev);
680
	intel_panel_init_backlight(connector->dev);
468
	return 0;
681
	return 0;
469
}
682
}
470
 
683
 
471
void intel_panel_destroy_backlight(struct drm_device *dev)
684
void intel_panel_destroy_backlight(struct drm_device *dev)
472
{
685
{
473
	return;
686
	return;
474
}
687
}
475
#endif
688
#endif
476
 
689
 
477
int intel_panel_init(struct intel_panel *panel,
690
int intel_panel_init(struct intel_panel *panel,
478
		     struct drm_display_mode *fixed_mode)
691
		     struct drm_display_mode *fixed_mode)
479
{
692
{
480
	panel->fixed_mode = fixed_mode;
693
	panel->fixed_mode = fixed_mode;
481
 
694
 
482
	return 0;
695
	return 0;
483
}
696
}
484
 
697
 
485
void intel_panel_fini(struct intel_panel *panel)
698
void intel_panel_fini(struct intel_panel *panel)
486
{
699
{
487
	struct intel_connector *intel_connector =
700
	struct intel_connector *intel_connector =
488
		container_of(panel, struct intel_connector, panel);
701
		container_of(panel, struct intel_connector, panel);
489
 
702
 
490
	if (panel->fixed_mode)
703
	if (panel->fixed_mode)
491
		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
704
		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
492
}
705
}