Example #1
0
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);
}
Example #2
0
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);
        }
    });
}
Example #3
0
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;
}
Example #4
0
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 != &current_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();
}