aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_encoder.c
diff options
context:
space:
mode:
authorInki Dae <inki.dae@samsung.com>2011-12-05 21:06:54 -0500
committerInki Dae <inki.dae@samsung.com>2011-12-21 01:14:17 -0500
commitec05da959acc5da8d51207060d9af672ae837321 (patch)
tree72fbc6c3d5b155877741a38441b308564d083427 /drivers/gpu/drm/exynos/exynos_drm_encoder.c
parenta794d57da8031a45fed4e4cb71a999694ba02f7e (diff)
drm/exynos: updated crtc and encoder dpms framework.
With DPMS ON and OFF requests, crtc dpms would be in charge of just only device power such as fimd or hdmi and encoder dpms in charge of device setting(mode setting and register updating) and also lcd panel and digital TV power. Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_encoder.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c109
1 files changed, 83 insertions, 26 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 153061415ba..4ff4a217c1d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -42,49 +42,68 @@
42 * @drm_encoder: encoder object. 42 * @drm_encoder: encoder object.
43 * @manager: specific encoder has its own manager to control a hardware 43 * @manager: specific encoder has its own manager to control a hardware
44 * appropriately and we can access a hardware drawing on this manager. 44 * appropriately and we can access a hardware drawing on this manager.
45 * @dpms: store the encoder dpms value.
45 */ 46 */
46struct exynos_drm_encoder { 47struct exynos_drm_encoder {
47 struct drm_encoder drm_encoder; 48 struct drm_encoder drm_encoder;
48 struct exynos_drm_manager *manager; 49 struct exynos_drm_manager *manager;
50 int dpms;
49}; 51};
50 52
51static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) 53static void exynos_drm_display_power(struct drm_encoder *encoder, int mode)
52{ 54{
53 struct drm_device *dev = encoder->dev; 55 struct drm_device *dev = encoder->dev;
54 struct drm_connector *connector; 56 struct drm_connector *connector;
55 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); 57 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
58
59 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
60 if (connector->encoder == encoder) {
61 struct exynos_drm_display_ops *display_ops =
62 manager->display_ops;
63
64 DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
65 connector->base.id, mode);
66 if (display_ops && display_ops->power_on)
67 display_ops->power_on(manager->dev, mode);
68 }
69 }
70}
71
72static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
73{
74 struct drm_device *dev = encoder->dev;
75 struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
56 struct exynos_drm_manager_ops *manager_ops = manager->ops; 76 struct exynos_drm_manager_ops *manager_ops = manager->ops;
77 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
57 78
58 DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); 79 DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
59 80
81 if (exynos_encoder->dpms == mode) {
82 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
83 return;
84 }
85
86 mutex_lock(&dev->struct_mutex);
87
60 switch (mode) { 88 switch (mode) {
61 case DRM_MODE_DPMS_ON: 89 case DRM_MODE_DPMS_ON:
62 if (manager_ops && manager_ops->commit) 90 if (manager_ops && manager_ops->apply)
63 manager_ops->commit(manager->dev); 91 manager_ops->apply(manager->dev);
92 exynos_drm_display_power(encoder, mode);
93 exynos_encoder->dpms = mode;
64 break; 94 break;
65 case DRM_MODE_DPMS_STANDBY: 95 case DRM_MODE_DPMS_STANDBY:
66 case DRM_MODE_DPMS_SUSPEND: 96 case DRM_MODE_DPMS_SUSPEND:
67 case DRM_MODE_DPMS_OFF: 97 case DRM_MODE_DPMS_OFF:
68 /* TODO */ 98 exynos_drm_display_power(encoder, mode);
69 if (manager_ops && manager_ops->disable) 99 exynos_encoder->dpms = mode;
70 manager_ops->disable(manager->dev);
71 break; 100 break;
72 default: 101 default:
73 DRM_ERROR("unspecified mode %d\n", mode); 102 DRM_ERROR("unspecified mode %d\n", mode);
74 break; 103 break;
75 } 104 }
76 105
77 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 106 mutex_unlock(&dev->struct_mutex);
78 if (connector->encoder == encoder) {
79 struct exynos_drm_display_ops *display_ops =
80 manager->display_ops;
81
82 DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
83 connector->base.id, mode);
84 if (display_ops && display_ops->power_on)
85 display_ops->power_on(manager->dev, mode);
86 }
87 }
88} 107}
89 108
90static bool 109static bool
@@ -169,7 +188,6 @@ static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
169 exynos_encoder->manager->pipe = -1; 188 exynos_encoder->manager->pipe = -1;
170 189
171 drm_encoder_cleanup(encoder); 190 drm_encoder_cleanup(encoder);
172 encoder->dev->mode_config.num_encoder--;
173 kfree(exynos_encoder); 191 kfree(exynos_encoder);
174} 192}
175 193
@@ -199,6 +217,7 @@ exynos_drm_encoder_create(struct drm_device *dev,
199 return NULL; 217 return NULL;
200 } 218 }
201 219
220 exynos_encoder->dpms = DRM_MODE_DPMS_OFF;
202 exynos_encoder->manager = manager; 221 exynos_encoder->manager = manager;
203 encoder = &exynos_encoder->drm_encoder; 222 encoder = &exynos_encoder->drm_encoder;
204 encoder->possible_crtcs = possible_crtcs; 223 encoder->possible_crtcs = possible_crtcs;
@@ -294,6 +313,52 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
294 overlay_ops->commit(manager->dev); 313 overlay_ops->commit(manager->dev);
295} 314}
296 315
316void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data)
317{
318 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
319 int mode = *(int *)data;
320
321 DRM_DEBUG_KMS("%s\n", __FILE__);
322
323 exynos_drm_encoder_dpms(encoder, mode);
324
325 exynos_encoder->dpms = mode;
326}
327
328void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
329{
330 struct drm_device *dev = encoder->dev;
331 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
332 struct exynos_drm_manager *manager = exynos_encoder->manager;
333 struct exynos_drm_manager_ops *manager_ops = manager->ops;
334 struct drm_connector *connector;
335 int mode = *(int *)data;
336
337 DRM_DEBUG_KMS("%s\n", __FILE__);
338
339 if (manager_ops && manager_ops->dpms)
340 manager_ops->dpms(manager->dev, mode);
341
342 /*
343 * set current dpms mode to the connector connected to
344 * current encoder. connector->dpms would be checked
345 * at drm_helper_connector_dpms()
346 */
347 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
348 if (connector->encoder == encoder)
349 connector->dpms = mode;
350
351 /*
352 * if this condition is ok then it means that the crtc is already
353 * detached from encoder and last function for detaching is properly
354 * done, so clear pipe from manager to prevent repeated call.
355 */
356 if (mode > DRM_MODE_DPMS_ON) {
357 if (!encoder->crtc)
358 manager->pipe = -1;
359 }
360}
361
297void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) 362void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
298{ 363{
299 struct exynos_drm_manager *manager = 364 struct exynos_drm_manager *manager =
@@ -315,14 +380,6 @@ void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
315 380
316 if (overlay_ops && overlay_ops->disable) 381 if (overlay_ops && overlay_ops->disable)
317 overlay_ops->disable(manager->dev); 382 overlay_ops->disable(manager->dev);
318
319 /*
320 * crtc is already detached from encoder and last
321 * function for detaching is properly done, so
322 * clear pipe from manager to prevent repeated call
323 */
324 if (!encoder->crtc)
325 manager->pipe = -1;
326} 383}
327 384
328MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); 385MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");