2 * Copyright © 2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * Author: Paulo Zanoni <paulo.r.zanoni@intel.com>
27 #include <sys/types.h>
35 #include "intel_chipset.h"
37 /* We know that if we don't enable audio runtime PM, snd_hda_intel will never
38 * release its power well refcount, and we'll never reach the LPSP sate. OTOH
39 * there's no guarantee that it will release the power well if we enable runtime
40 * PM, but at least we can try. We don't have any assertions since the user may
41 * not even have snd_hda_intel loaded, which is not a problem. */
42 static void disable_audio_runtime_pm(void)
46 fd = open("/sys/module/snd_hda_intel/parameters/power_save", O_WRONLY);
51 fd = open("/sys/bus/pci/devices/0000:00:03.0/power/control", O_WRONLY);
53 write(fd, "auto\n", 5);
56 /* Give some time for it to react. */
60 static bool supports_lpsp(uint32_t devid)
62 return IS_HASWELL(devid) || IS_BROADWELL(devid);
65 static bool lpsp_is_enabled(int drm_fd)
69 val = INREG(HSW_PWR_WELL_CTL2);
70 return !(val & HSW_PWR_WELL_STATE_ENABLED);
73 static void disable_all_screens(int drm_fd, drmModeResPtr drm_resources)
77 for (i = 0; i < drm_resources->count_crtcs; i++) {
78 rc = drmModeSetCrtc(drm_fd, drm_resources->crtcs[i], -1, 0, 0,
84 /* The LPSP mode is all about an enabled pipe, but we expect to also be in the
85 * low power mode when no pipes are enabled, so do this check anyway. */
86 static void screens_disabled_subtest(int drm_fd, drmModeResPtr drm_res)
88 disable_all_screens(drm_fd, drm_res);
89 igt_assert(lpsp_is_enabled(drm_fd));
92 static uint32_t create_fb(int drm_fd, int width, int height)
98 buffer_id = igt_create_fb(drm_fd, width, height,
101 cr = igt_get_cairo_ctx(drm_fd, &fb);
102 igt_paint_test_pattern(cr, width, height);
108 static void edp_subtest(int drm_fd, drmModeResPtr drm_res,
109 drmModeConnectorPtr *drm_connectors, uint32_t devid,
110 bool use_panel_fitter)
113 uint32_t connector_id = 0, crtc_id = 0, buffer_id = 0;
114 drmModeModeInfoPtr mode = NULL;
115 drmModeModeInfo std_1024_mode = {
131 .name = "Custom 1024x768",
134 disable_all_screens(drm_fd, drm_res);
136 for (i = 0; i < drm_res->count_connectors; i++) {
137 drmModeConnectorPtr c = drm_connectors[i];
139 if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
141 if (c->connection != DRM_MODE_CONNECTED)
144 if (!use_panel_fitter && c->count_modes) {
145 connector_id = c->connector_id;
149 if (use_panel_fitter) {
150 connector_id = c->connector_id;
152 /* This is one of the modes Xorg creates for panels, so
153 * it should work just fine. Notice that Gens that
154 * support LPSP are too new for panels with native
155 * 1024x768 resolution, so this should force the panel
157 igt_assert(c->count_modes &&
158 c->modes[0].hdisplay > 1024);
159 igt_assert(c->count_modes &&
160 c->modes[0].vdisplay > 768);
161 mode = &std_1024_mode;
165 igt_require(connector_id);
167 crtc_id = drm_res->crtcs[0];
168 buffer_id = create_fb(drm_fd, mode->hdisplay, mode->vdisplay);
171 igt_assert(buffer_id);
172 igt_assert(connector_id);
175 rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id, 1,
179 if (use_panel_fitter) {
180 if (IS_HASWELL(devid))
181 igt_assert(!lpsp_is_enabled(drm_fd));
183 igt_assert(lpsp_is_enabled(drm_fd));
185 igt_assert(lpsp_is_enabled(drm_fd));
189 static void non_edp_subtest(int drm_fd, drmModeResPtr drm_res,
190 drmModeConnectorPtr *drm_connectors)
193 uint32_t connector_id = 0, crtc_id = 0, buffer_id = 0;
194 drmModeModeInfoPtr mode = NULL;
196 disable_all_screens(drm_fd, drm_res);
198 for (i = 0; i < drm_res->count_connectors; i++) {
199 drmModeConnectorPtr c = drm_connectors[i];
201 if (c->connector_type == DRM_MODE_CONNECTOR_eDP)
203 if (c->connection != DRM_MODE_CONNECTED)
206 if (c->count_modes) {
207 connector_id = c->connector_id;
212 igt_require(connector_id);
214 crtc_id = drm_res->crtcs[0];
215 buffer_id = create_fb(drm_fd, mode->hdisplay, mode->vdisplay);
218 igt_assert(buffer_id);
219 igt_assert(connector_id);
222 rc = drmModeSetCrtc(drm_fd, crtc_id, buffer_id, 0, 0, &connector_id, 1,
226 igt_assert(!lpsp_is_enabled(drm_fd));
229 #define MAX_CONNECTORS 32
233 drmModeResPtr drm_res;
234 drmModeConnectorPtr drm_connectors[MAX_CONNECTORS];
241 drm_fd = drm_open_any();
242 igt_require(drm_fd >= 0);
244 devid = intel_get_drm_devid(drm_fd);
246 drm_res = drmModeGetResources(drm_fd);
247 igt_assert(drm_res->count_connectors <= MAX_CONNECTORS);
249 for (i = 0; i < drm_res->count_connectors; i++)
250 drm_connectors[i] = drmModeGetConnector(drm_fd,
251 drm_res->connectors[i]);
253 disable_audio_runtime_pm();
255 igt_require(supports_lpsp(devid));
257 intel_register_access_init(intel_get_pci_device(), 0);
259 igt_set_vt_graphics_mode();
262 igt_subtest("screens-disabled")
263 screens_disabled_subtest(drm_fd, drm_res);
264 igt_subtest("edp-native")
265 edp_subtest(drm_fd, drm_res, drm_connectors, devid, false);
266 igt_subtest("edp-panel-fitter")
267 edp_subtest(drm_fd, drm_res, drm_connectors, devid, true);
268 igt_subtest("non-edp")
269 non_edp_subtest(drm_fd, drm_res, drm_connectors);
274 intel_register_access_fini();
275 for (i = 0; i < drm_res->count_connectors; i++)
276 drmModeFreeConnector(drm_connectors[i]);
277 drmModeFreeResources(drm_res);