예제 #1
0
static int ipu_crtc_mode_set(struct drm_crtc *crtc,
			       struct drm_display_mode *orig_mode,
			       struct drm_display_mode *mode,
			       int x, int y,
			       struct drm_framebuffer *old_fb)
{
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct drm_framebuffer *fb = ipu_crtc->base.fb;
	int ret;
	struct ipu_di_signal_cfg sig_cfg = {};
	u32 out_pixel_fmt;
	struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch);
	int bpp;
	u32 v4l2_fmt;

	dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
			mode->hdisplay);
	dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
			mode->vdisplay);

	ipu_ch_param_zero(cpmem);

	switch (fb->pixel_format) {
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_ARGB8888:
		v4l2_fmt = V4L2_PIX_FMT_RGB32;
		bpp = 32;
		break;
	case DRM_FORMAT_RGB565:
		v4l2_fmt = V4L2_PIX_FMT_RGB565;
		bpp = 16;
		break;
	case DRM_FORMAT_RGB888:
		v4l2_fmt = V4L2_PIX_FMT_RGB24;
		bpp = 24;
		break;
	default:
		dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n",
				fb->pixel_format);
		return -EINVAL;
	}

	out_pixel_fmt = ipu_crtc->interface_pix_fmt;

	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		sig_cfg.interlaced = 1;
	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
		sig_cfg.Hsync_pol = 1;
	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
		sig_cfg.Vsync_pol = 1;

	sig_cfg.enable_pol = 1;
	sig_cfg.clk_pol = 0;
	sig_cfg.width = mode->hdisplay;
	sig_cfg.height = mode->vdisplay;
	sig_cfg.pixel_fmt = out_pixel_fmt;
	sig_cfg.h_start_width = mode->htotal - mode->hsync_end;
	sig_cfg.h_sync_width = mode->hsync_end - mode->hsync_start;
	sig_cfg.h_end_width = mode->hsync_start - mode->hdisplay;

	sig_cfg.v_start_width = mode->vtotal - mode->vsync_end;
	sig_cfg.v_sync_width = mode->vsync_end - mode->vsync_start;
	sig_cfg.v_end_width = mode->vsync_start - mode->vdisplay;
	sig_cfg.pixelclock = mode->clock * 1000;
	sig_cfg.clkflags = ipu_crtc->di_clkflags;

	sig_cfg.v_to_h_sync = 0;

	if (ipu_crtc->dp) {
		ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB,
				IPUV3_COLORSPACE_RGB);
		if (ret) {
			dev_err(ipu_crtc->dev,
				"initializing display processor failed with %d\n",
				ret);
			return ret;
		}
		ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1);
	}

	ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced,
			out_pixel_fmt, mode->hdisplay);
	if (ret) {
		dev_err(ipu_crtc->dev,
				"initializing display controller failed with %d\n",
				ret);
		return ret;
	}

	ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
	if (ret) {
		dev_err(ipu_crtc->dev,
				"initializing panel failed with %d\n", ret);
		return ret;
	}

	ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay);
	ipu_cpmem_set_fmt(cpmem, v4l2_fmt);
	ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch);

	ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay);
	if (ret) {
		dev_err(ipu_crtc->dev,
				"initializing dmfc channel failed with %d\n",
				ret);
		return ret;
	}

	ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc,
			calc_bandwidth(mode, calc_vref(mode)), 64);
	if (ret) {
		dev_err(ipu_crtc->dev,
				"allocating dmfc bandwidth failed with %d\n",
				ret);
		return ret;
	}

	ipu_drm_set_base(crtc, x, y);

	return 0;
}
예제 #2
0
/* TODO: this should be optimized so we don't allocate network and call open()/close() all the time */
static void
collect (DiskIOMonitor *monitor)
{
    gchar *contents = NULL;
    gsize len;
    GError *error;
    gchar **lines = NULL;
    guint n;
    gint64 now;
    Sample *sample = NULL;
    Sample *last = NULL;
    GVariantBuilder builder;

    error = NULL;
    if (!g_file_get_contents ("/proc/diskstats",
                              &contents,
                              &len,
                              &error))
    {
        g_warning ("Error loading contents /proc/vmstat: %s (%s, %d)",
                   error->message, g_quark_to_string (error->domain), error->code);
        g_error_free (error);
        goto out;
    }

    now = g_get_real_time ();

    sample = &(monitor->samples[monitor->samples_next]);
    sample->timestamp = now;
    sample->bytes_read = 0;
    sample->bytes_written = 0;
    sample->num_ops = 0;

    if (monitor->samples_prev != -1)
        last = &(monitor->samples[monitor->samples_prev]);

    lines = g_strsplit (contents, "\n", -1);
    for (n = 0; lines != NULL && lines[n] != NULL; n++)
    {
        const gchar *line = lines[n];
        guint num_parsed;
        gint dev_major, dev_minor;
        gchar dev_name[64]; /* TODO: big enough? */
        guint64 num_reads,  num_reads_merged,  num_sectors_read,    num_msec_reading;
        guint64 num_writes, num_writes_merged, num_sectors_written, num_msec_writing;
        guint64 num_io_in_progress, num_msec_doing_io, weighted_num_msec_doing_io;

        if (strlen (line) == 0)
            continue;

        /* From http://www.kernel.org/doc/Documentation/iostats.txt
         *
         * Field  1 -- # of reads completed
         *     This is the total number of reads completed successfully.
         * Field  2 -- # of reads merged, field 6 -- # of writes merged
         *     Reads and writes which are adjacent to each other may be merged for
         *     efficiency.  Thus two 4K reads may become one 8K read before it is
         *     ultimately handed to the disk, and so it will be counted (and queued)
         *     as only one I/O.  This field lets you know how often this was done.
         * Field  3 -- # of sectors read
         *     This is the total number of sectors read successfully.
         * Field  4 -- # of milliseconds spent reading
         *     This is the total number of milliseconds spent by all reads (as
         *     measured from __make_request() to end_that_request_last()).
         * Field  5 -- # of writes completed
         *     This is the total number of writes completed successfully.
         * Field  7 -- # of sectors written
         *     This is the total number of sectors written successfully.
         * Field  8 -- # of milliseconds spent writing
         *     This is the total number of milliseconds spent by all writes (as
         *     measured from __make_request() to end_that_request_last()).
         * Field  9 -- # of I/Os currently in progress
         *     The only field that should go to zero. Incremented as requests are
         *     given to appropriate struct request_queue and decremented as they finish.
         * Field 10 -- # of milliseconds spent doing I/Os
         *     This field increases so long as field 9 is nonzero.
         * Field 11 -- weighted # of milliseconds spent doing I/Os
         *     This field is incremented at each I/O start, I/O completion, I/O
         *     merge, or read of these stats by the number of I/Os in progress
         *     (field 9) times the number of milliseconds spent doing I/O since the
         *     last update of this field.  This can provide an easy measure of both
         *     I/O completion time and the backlog that may be accumulating.
         */

        num_parsed = sscanf (line,
                             "%d %d %s"
                             " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT
                             " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT
                             " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT,
                             &dev_major, &dev_minor, dev_name,
                             &num_reads,  &num_reads_merged, &num_sectors_read, &num_msec_reading,
                             &num_writes, &num_writes_merged, &num_sectors_written, &num_msec_writing,
                             &num_io_in_progress, &num_msec_doing_io, &weighted_num_msec_doing_io);
        if (num_parsed != 14)
        {
            g_warning ("Error parsing line %d of file /proc/diskstats (num_parsed=%d): `%s'", n, num_parsed, line);
            continue;
        }

        /* skip mapped devices and partitions... otherwise we'll count their
         * I/O more than once
         *
         * TODO: the way we identify dm devices and partitions is not
         * very elegant... we should consult sysfs via libgudev1
         * instead.
         */
        if (dev_major == 253)
            continue;

        if (g_str_has_prefix (dev_name, "sd") && g_ascii_isdigit (dev_name[strlen (dev_name) - 1]))
            continue;

        sample->bytes_read += num_sectors_read * 512;
        sample->bytes_written += num_sectors_written * 512;
        sample->num_ops += num_reads_merged + num_writes_merged;
    }

    if (last != NULL)
    {
        sample->bytes_read_per_sec = calc_bandwidth (monitor, sample, last, sample->bytes_read, last->bytes_read);
        sample->bytes_written_per_sec = calc_bandwidth (monitor, sample, last, sample->bytes_written, last->bytes_written);
        sample->io_operations_per_sec = calc_bandwidth (monitor, sample, last, sample->num_ops, last->num_ops);
    }

out:
    g_strfreev (lines);
    g_free (contents);
    if (sample != NULL)
    {
        g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
        g_variant_builder_add (&builder, "d", sample->bytes_read_per_sec);
        g_variant_builder_add (&builder, "d", sample->bytes_written_per_sec);
        g_variant_builder_add (&builder, "d", sample->io_operations_per_sec);
        cockpit_resource_monitor_emit_new_sample (COCKPIT_RESOURCE_MONITOR(monitor),
                now, g_variant_builder_end (&builder));
    }

    monitor->samples_prev = monitor->samples_next;
    monitor->samples_next += 1;
    if (monitor->samples_next == monitor->samples_max)
        monitor->samples_next = 0;
}