Subversion Repositories Kolibri OS

Rev

Rev 1268 | Rev 1404 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1123 serge 1
/*
2
 * Copyright (c) 2006-2008 Intel Corporation
3
 * Copyright (c) 2007 Dave Airlie 
4
 *
5
 * DRM core CRTC related functions
6
 *
7
 * Permission to use, copy, modify, distribute, and sell this software and its
8
 * documentation for any purpose is hereby granted without fee, provided that
9
 * the above copyright notice appear in all copies and that both that copyright
10
 * notice and this permission notice appear in supporting documentation, and
11
 * that the name of the copyright holders not be used in advertising or
12
 * publicity pertaining to distribution of the software without specific,
13
 * written prior permission.  The copyright holders make no representations
14
 * about the suitability of this software for any purpose.  It is provided "as
15
 * is" without express or implied warranty.
16
 *
17
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23
 * OF THIS SOFTWARE.
24
 *
25
 * Authors:
26
 *      Keith Packard
27
 *	Eric Anholt 
28
 *      Dave Airlie 
29
 *      Jesse Barnes 
30
 */
31
 
32
#include "drmP.h"
33
#include "drm_crtc.h"
34
#include "drm_crtc_helper.h"
1221 serge 35
#include "drm_fb_helper.h"
1123 serge 36
 
37
static void drm_mode_validate_flag(struct drm_connector *connector,
38
				   int flags)
39
{
40
	struct drm_display_mode *mode, *t;
41
 
42
	if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
43
		return;
44
 
45
	list_for_each_entry_safe(mode, t, &connector->modes, head) {
46
		if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
47
				!(flags & DRM_MODE_FLAG_INTERLACE))
48
			mode->status = MODE_NO_INTERLACE;
49
		if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
50
				!(flags & DRM_MODE_FLAG_DBLSCAN))
51
			mode->status = MODE_NO_DBLESCAN;
52
	}
53
 
54
	return;
55
}
56
 
57
/**
58
 * drm_helper_probe_connector_modes - get complete set of display modes
59
 * @dev: DRM device
60
 * @maxX: max width for modes
61
 * @maxY: max height for modes
62
 *
63
 * LOCKING:
64
 * Caller must hold mode config lock.
65
 *
66
 * Based on @dev's mode_config layout, scan all the connectors and try to detect
67
 * modes on them.  Modes will first be added to the connector's probed_modes
68
 * list, then culled (based on validity and the @maxX, @maxY parameters) and
69
 * put into the normal modes list.
70
 *
71
 * Intended to be used either at bootup time or when major configuration
72
 * changes have occurred.
73
 *
74
 * FIXME: take into account monitor limits
75
 *
76
 * RETURNS:
77
 * Number of modes found on @connector.
78
 */
79
int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
80
					    uint32_t maxX, uint32_t maxY)
81
{
82
	struct drm_device *dev = connector->dev;
83
	struct drm_display_mode *mode, *t;
84
	struct drm_connector_helper_funcs *connector_funcs =
85
		connector->helper_private;
86
	int count = 0;
87
	int mode_flags = 0;
88
 
1179 serge 89
	DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
1123 serge 90
	/* set all modes to the unverified state */
91
	list_for_each_entry_safe(mode, t, &connector->modes, head)
92
		mode->status = MODE_UNVERIFIED;
93
 
1221 serge 94
	if (connector->force) {
95
		if (connector->force == DRM_FORCE_ON)
96
			connector->status = connector_status_connected;
97
		else
98
			connector->status = connector_status_disconnected;
99
		if (connector->funcs->force)
100
			connector->funcs->force(connector);
101
	} else
1123 serge 102
	connector->status = connector->funcs->detect(connector);
103
 
104
	if (connector->status == connector_status_disconnected) {
1179 serge 105
		DRM_DEBUG_KMS("%s is disconnected\n",
1123 serge 106
			  drm_get_connector_name(connector));
1179 serge 107
		goto prune;
1123 serge 108
	}
109
 
110
	count = (*connector_funcs->get_modes)(connector);
1179 serge 111
	if (!count) {
1321 serge 112
		count = drm_add_modes_noedid(connector, 1024, 768);
1123 serge 113
	if (!count)
114
		return 0;
1179 serge 115
	}
1123 serge 116
 
117
	drm_mode_connector_list_update(connector);
118
 
119
	if (maxX && maxY)
120
		drm_mode_validate_size(dev, &connector->modes, maxX,
121
				       maxY, 0);
122
 
123
	if (connector->interlace_allowed)
124
		mode_flags |= DRM_MODE_FLAG_INTERLACE;
125
	if (connector->doublescan_allowed)
126
		mode_flags |= DRM_MODE_FLAG_DBLSCAN;
127
	drm_mode_validate_flag(connector, mode_flags);
128
 
129
	list_for_each_entry_safe(mode, t, &connector->modes, head) {
130
		if (mode->status == MODE_OK)
131
			mode->status = connector_funcs->mode_valid(connector,
132
								   mode);
133
	}
134
 
1179 serge 135
prune:
1123 serge 136
	drm_mode_prune_invalid(dev, &connector->modes, true);
137
 
138
	if (list_empty(&connector->modes))
139
		return 0;
140
 
141
	drm_mode_sort(&connector->modes);
142
 
1179 serge 143
	DRM_DEBUG_KMS("Probed modes for %s\n",
144
				drm_get_connector_name(connector));
1123 serge 145
	list_for_each_entry_safe(mode, t, &connector->modes, head) {
146
		mode->vrefresh = drm_mode_vrefresh(mode);
147
 
148
		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
149
		drm_mode_debug_printmodeline(mode);
150
	}
151
 
152
	return count;
153
}
154
EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
155
 
156
int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
157
				      uint32_t maxY)
158
{
159
	struct drm_connector *connector;
160
	int count = 0;
161
 
162
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
163
		count += drm_helper_probe_single_connector_modes(connector,
164
								 maxX, maxY);
165
	}
166
 
167
	return count;
168
}
169
EXPORT_SYMBOL(drm_helper_probe_connector_modes);
170
 
171
/**
172
 * drm_helper_encoder_in_use - check if a given encoder is in use
173
 * @encoder: encoder to check
174
 *
175
 * LOCKING:
176
 * Caller must hold mode config lock.
177
 *
178
 * Walk @encoders's DRM device's mode_config and see if it's in use.
179
 *
180
 * RETURNS:
181
 * True if @encoder is part of the mode_config, false otherwise.
182
 */
183
bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
184
{
185
	struct drm_connector *connector;
186
	struct drm_device *dev = encoder->dev;
187
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
188
		if (connector->encoder == encoder)
189
			return true;
190
	return false;
191
}
192
EXPORT_SYMBOL(drm_helper_encoder_in_use);
193
 
194
/**
195
 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
196
 * @crtc: CRTC to check
197
 *
198
 * LOCKING:
199
 * Caller must hold mode config lock.
200
 *
201
 * Walk @crtc's DRM device's mode_config and see if it's in use.
202
 *
203
 * RETURNS:
204
 * True if @crtc is part of the mode_config, false otherwise.
205
 */
206
bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
207
{
208
	struct drm_encoder *encoder;
209
	struct drm_device *dev = crtc->dev;
210
	/* FIXME: Locking around list access? */
211
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
212
		if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
213
			return true;
214
	return false;
215
}
216
EXPORT_SYMBOL(drm_helper_crtc_in_use);
217
 
218
/**
219
 * drm_disable_unused_functions - disable unused objects
220
 * @dev: DRM device
221
 *
222
 * LOCKING:
223
 * Caller must hold mode config lock.
224
 *
225
 * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
226
 * by calling its dpms function, which should power it off.
227
 */
228
void drm_helper_disable_unused_functions(struct drm_device *dev)
229
{
230
	struct drm_encoder *encoder;
1179 serge 231
	struct drm_connector *connector;
1123 serge 232
	struct drm_encoder_helper_funcs *encoder_funcs;
233
	struct drm_crtc *crtc;
234
 
1179 serge 235
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
236
		if (!connector->encoder)
237
			continue;
238
		if (connector->status == connector_status_disconnected)
239
			connector->encoder = NULL;
240
	}
241
 
1123 serge 242
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
243
		encoder_funcs = encoder->helper_private;
1179 serge 244
		if (!drm_helper_encoder_in_use(encoder)) {
245
			if (encoder_funcs->disable)
246
				(*encoder_funcs->disable)(encoder);
247
			else