static void restore_power_modes() { if(control_sleep_modes == 0) return; dbgmsg("Restoring power modes\n"); if(saved_sapc_idle_en_c0 != -1) set_power_mode(0, "standalone_power_collapse", "idle_enabled", saved_sapc_idle_en_c0 ); if(saved_sapc_idle_en_c1 != -1) set_power_mode(1, "standalone_power_collapse", "idle_enabled", saved_sapc_idle_en_c1 ); if(saved_pc_idle_en_c0 != -1) set_power_mode(0, "power_collapse", "idle_enabled", saved_pc_idle_en_c0); if(saved_pc_idle_en_c1 != -1) set_power_mode(1, "power_collapse", "idle_enabled", saved_pc_idle_en_c1); }
void mgm::Display::clear_connected_unused_outputs() { current_display_configuration.for_each_output([&](DisplayConfigurationOutput const& conf_output) { /* * An output may be unused either because it's explicitly not used * (DisplayConfigurationOutput::used) or because its power mode is * not mir_power_mode_on. */ if (conf_output.connected && (!conf_output.used || (conf_output.power_mode != mir_power_mode_on))) { uint32_t const connector_id = current_display_configuration.get_kms_connector_id(conf_output.id); auto kms_output = output_container.get_kms_output_for(connector_id); kms_output->clear_crtc(); kms_output->set_power_mode(conf_output.power_mode); } }); }
static int act_on_decision(unsigned int status) { int ret = 0; if (status == core1_status) { msg("No action required to change core status(%d).", status); return 0; } pthread_mutex_lock(&hotplug_mutex); if (decision_engine_stalled()) { msg("MP decision to set core status to %d ignored\n", status); pthread_mutex_unlock(&hotplug_mutex); return -ENODEV; } if (thermal_condition) { msg("MP decision in thermal condition, " "request to set core status to %d ignored\n", status); pthread_mutex_unlock(&hotplug_mutex); return -ENODEV; } switch (status) { case CORE_UP: if(control_sleep_modes==1) { int err=0; // 1) Remember the individual core independent power collapse setting for both cores save_power_modes(); // 2) Disable individual core independent power collapse dbgmsg("Setting power modes before CORE_UP\n"); err += set_power_mode(0, "standalone_power_collapse", "idle_enabled", 0); err += set_power_mode(1, "standalone_power_collapse", "idle_enabled", 0); err += set_power_mode(0, "power_collapse", "idle_enabled", 0); err += set_power_mode(1, "power_collapse", "idle_enabled", 0); if(err) { dbgmsg("Error setting a sleep mode - %d\n", err); } //print_power_modes(); } // 3) Power up the 2nd core core1_status = CORE_UP; ret = cpu_up(1, 1); break; case CORE_DOWN: // 1) Power down the 2nd core core1_status = CORE_DOWN; ret = cpu_up(1, 0); // 2) Restore the original individual core independent power collapse setting for both cores if(control_sleep_modes==1) { dbgmsg("Restoring power modes after CORE_DOWN\n"); restore_power_modes(); //print_power_modes(); } break; default: break; } if (ret) { msg("Error(%d) changing core status to %s\n", ret, status ? "online" : "offline"); } pthread_mutex_unlock(&hotplug_mutex); return ret; }
void mgm::Display::configure(mg::DisplayConfiguration const& conf) { if (!conf.valid()) { BOOST_THROW_EXCEPTION( std::logic_error("Invalid or inconsistent display configuration")); } { std::lock_guard<std::mutex> lg{configuration_mutex}; auto const& kms_conf = dynamic_cast<RealKMSDisplayConfiguration const&>(conf); // Treat the current_display_configuration as incompatible with itself, // before it's fully constructed, to force proper initialization. bool const comp{(&conf != ¤t_display_configuration) && compatible(kms_conf, current_display_configuration)}; std::vector<std::unique_ptr<DisplayBuffer>> display_buffers_new; if (!comp) { /* * Notice for a little while here we will have duplicate * DisplayBuffers attached to each output, and the display_buffers_new * will take over the outputs before the old display_buffers are * destroyed. So to avoid page flipping confusion in-between, make * sure we wait for all pending page flips to finish before the * display_buffers_new are created and take control of the outputs. */ for (auto& db : display_buffers) db->wait_for_page_flip(); /* Reset the state of all outputs */ kms_conf.for_each_output([&](DisplayConfigurationOutput const& conf_output) { uint32_t const connector_id = current_display_configuration.get_kms_connector_id(conf_output.id); auto kms_output = output_container.get_kms_output_for(connector_id); kms_output->clear_cursor(); kms_output->reset(); }); } /* Set up used outputs */ OverlappingOutputGrouping grouping{conf}; auto group_idx = 0; grouping.for_each_group([&](OverlappingOutputGroup const& group) { auto bounding_rect = group.bounding_rectangle(); std::vector<std::shared_ptr<KMSOutput>> kms_outputs; MirOrientation orientation = mir_orientation_normal; group.for_each_output([&](DisplayConfigurationOutput const& conf_output) { uint32_t const connector_id = kms_conf.get_kms_connector_id(conf_output.id); auto kms_output = output_container.get_kms_output_for(connector_id); auto const mode_index = kms_conf.get_kms_mode_index(conf_output.id, conf_output.current_mode_index); kms_output->configure(conf_output.top_left - bounding_rect.top_left, mode_index); if (!comp) { kms_output->set_power_mode(conf_output.power_mode); kms_outputs.push_back(kms_output); } /* * Presently OverlappingOutputGroup guarantees all grouped * outputs have the same orientation. */ orientation = conf_output.orientation; }); if (comp) { display_buffers[group_idx++]->set_orientation(orientation, bounding_rect); } else { uint32_t width = bounding_rect.size.width.as_uint32_t(); uint32_t height = bounding_rect.size.height.as_uint32_t(); if (orientation == mir_orientation_left || orientation == mir_orientation_right) { std::swap(width, height); } auto surface = gbm->create_scanout_surface(width, height); std::unique_ptr<DisplayBuffer> db{ new DisplayBuffer{bypass_option, drm, gbm, listener, kms_outputs, std::move(surface), bounding_rect, orientation, *gl_config, shared_egl.context()}}; display_buffers_new.push_back(std::move(db)); } }); if (!comp) display_buffers = std::move(display_buffers_new); /* Store applied configuration */ current_display_configuration = kms_conf; if (!comp) /* Clear connected but unused outputs */ clear_connected_unused_outputs(); } if (auto c = cursor.lock()) c->resume(); }