Beispiel #1
0
static void pl110_invalidate_display(void * opaque)
{
    pl110_state *s = (pl110_state *)opaque;
    s->invalidate = 1;
    if (pl110_enabled(s)) {
        qemu_console_resize(s->ds, s->cols, s->rows);
    }
}
Beispiel #2
0
static void pl110_display_invalidate(struct vmm_vdisplay *vdis)
{
	struct pl110_state *s = vmm_vdisplay_priv(vdis);

	if (pl110_enabled(s)) {
		vmm_vdisplay_surface_gfx_clear(vdis);
	}
}
Beispiel #3
0
static void pl110_resize(pl110_state *s, int width, int height)
{
    if (width != s->cols || height != s->rows) {
        if (pl110_enabled(s)) {
            qemu_console_resize(s->ds, width, height);
        }
    }
    s->cols = width;
    s->rows = height;
}
Beispiel #4
0
static int pl110_display_pixeldata(struct vmm_vdisplay *vdis,
				   struct vmm_pixelformat *pf,
				   u32 *rows, u32 *cols,
				   physical_addr_t *pa)
{
	u32 flags;
	physical_addr_t gpa, hpa;
	physical_size_t gsz, hsz;
	int rc, bits_per_pixel, bytes_per_pixel;
	struct pl110_state *s = vmm_vdisplay_priv(vdis);

	if (!pl110_enabled(s)) {
		return VMM_ENOTAVAIL;
	}

	switch (s->bpp) {
	case BPP_16:
	case BPP_16_565:
		bits_per_pixel = 16;
		bytes_per_pixel = 2;
		break;
	case BPP_32:
		bits_per_pixel = 32;
		bytes_per_pixel = 4;
		break;
	default:
		return VMM_EINVALID;
	};

	gpa = s->upbase;
	gsz = (s->cols * s->rows) * bytes_per_pixel;
	rc = vmm_guest_physical_map(s->guest, gpa, gsz, &hpa, &hsz, &flags);
	if (rc) {
		return rc;
	}

	if (!(flags & VMM_REGION_REAL) ||
	    !(flags & VMM_REGION_MEMORY) ||
	    !(flags & VMM_REGION_ISRAM)) {
		return VMM_EINVALID;
	}

	vmm_pixelformat_init_default(pf, bits_per_pixel);
	*rows = s->rows;
	*cols = s->cols;
	*pa = hpa;

	return VMM_OK;
}
Beispiel #5
0
static void pl110_update_display(void *opaque)
{
    pl110_state *s = (pl110_state *)opaque;
    drawfn* fntable;
    drawfn fn;
    int dest_width;
    int src_width;
    int bpp_offset;
    int first;
    int last;

    if (!pl110_enabled(s))
        return;

    switch (ds_get_bits_per_pixel(s->ds)) {
    case 0:
        return;
    case 8:
        fntable = pl110_draw_fn_8;
        dest_width = 1;
        break;
    case 15:
        fntable = pl110_draw_fn_15;
        dest_width = 2;
        break;
    case 16:
        fntable = pl110_draw_fn_16;
        dest_width = 2;
        break;
    case 24:
        fntable = pl110_draw_fn_24;
        dest_width = 3;
        break;
    case 32:
        fntable = pl110_draw_fn_32;
        dest_width = 4;
        break;
    default:
        fprintf(stderr, "pl110: Bad color depth\n");
        exit(1);
    }
    if (s->cr & PL110_CR_BGR)
        bpp_offset = 0;
    else
        bpp_offset = 18;

    if (s->cr & PL110_CR_BEBO)
        fn = fntable[s->bpp + 6 + bpp_offset];
    else if (s->cr & PL110_CR_BEPO)
        fn = fntable[s->bpp + 12 + bpp_offset];
    else
        fn = fntable[s->bpp + bpp_offset];

    src_width = s->cols;
    switch (s->bpp) {
    case BPP_1:
        src_width >>= 3;
        break;
    case BPP_2:
        src_width >>= 2;
        break;
    case BPP_4:
        src_width >>= 1;
        break;
    case BPP_8:
        break;
    case BPP_16:
        src_width <<= 1;
        break;
    case BPP_32:
        src_width <<= 2;
        break;
    }
    dest_width *= s->cols;
    first = 0;
    framebuffer_update_display(s->ds,
                               s->upbase, s->cols, s->rows,
                               src_width, dest_width, 0,
                               s->invalidate,
                               fn, s->pallette,
                               &first, &last);
    if (first >= 0) {
        dpy_update(s->ds, 0, first, s->cols, last - first + 1);
    }
    s->invalidate = 0;
}
Beispiel #6
0
static void pl110_display_update(struct vmm_vdisplay *vdis,
				 struct vmm_surface *sf)
{
	drawfn fn;
	drawfn *fntable;
	u32 *palette;
	physical_addr_t gphys;
	int cols, rows, first, last;
	int dest_width, src_width, bpp_offset;
	struct pl110_state *s = vmm_vdisplay_priv(vdis);

	if (!pl110_enabled(s)) {
		return;
	}

	switch (vmm_surface_bits_per_pixel(sf)) {
	case 0:
		return;
	case 8:
		fntable = pl110_draw_fn_8;
		dest_width = 1;
		palette = s->palette8;
		break;
	case 15:
		fntable = pl110_draw_fn_15;
		dest_width = 2;
		palette = s->palette15;
		break;
	case 16:
		fntable = pl110_draw_fn_16;
		dest_width = 2;
		palette = s->palette16;
		break;
	case 24:
		fntable = pl110_draw_fn_24;
		dest_width = 3;
		palette = s->palette32;
		break;
	case 32:
		fntable = pl110_draw_fn_32;
		dest_width = 4;
		palette = s->palette32;
		break;
	default:
		vmm_printf("%s: Bad color depth\n", __func__);
		return;
	};

	vmm_spin_lock(&s->lock);

	if (s->cr & PL110_CR_BGR) {
		bpp_offset = 0;
	} else {
		bpp_offset = 24;
	}

	if ((s->version != PL111) && (s->bpp == BPP_16)) {
		/* The PL110's native 16 bit mode is 5551; however
		 * most boards with a PL110 implement an external
		 * mux which allows bits to be reshuffled to give
		 * 565 format. The mux is typically controlled by
		 * an external system register.
		 * This is controlled by a GPIO input pin
		 * so boards can wire it up to their register.
		 *
		 * The PL111 straightforwardly implements both
		 * 5551 and 565 under control of the bpp field
		 * in the LCDControl register.
		 */
		switch (s->mux_ctrl) {
		case 3: /* 565 BGR */
			bpp_offset = (BPP_16_565 - BPP_16);
			break;
		case 1: /* 5551 */
			break;
		case 0: /* 888; also if we have loaded vmstate from an old version */
		case 2: /* 565 RGB */
		default:
			/* treat as 565 but honour BGR bit */
			bpp_offset += (BPP_16_565 - BPP_16);
			break;
		};
	}

	if (s->cr & PL110_CR_BEBO) {
		fn = fntable[s->bpp + 8 + bpp_offset];
	} else if (s->cr & PL110_CR_BEPO) {
		fn = fntable[s->bpp + 16 + bpp_offset];
	} else {
		fn = fntable[s->bpp + bpp_offset];
	}

	src_width = s->cols;
	switch (s->bpp) {
	case BPP_1:
		src_width >>= 3;
		break;
	case BPP_2:
		src_width >>= 2;
		break;
	case BPP_4:
		src_width >>= 1;
		break;
	case BPP_8:
		break;
	case BPP_16:
	case BPP_16_565:
	case BPP_12:
		src_width <<= 1;
		break;
	case BPP_32:
		src_width <<= 2;
		break;
	};

	dest_width *= s->cols;

	gphys = s->upbase;
	cols = s->cols;
	rows = s->rows;

	vmm_spin_unlock(&s->lock);

	first = 0;
	vmm_surface_update(sf, s->guest, gphys, cols, rows,
			   src_width, dest_width, 0, fn, palette,
			   &first, &last);
	if (first >= 0) {
		vmm_vdisplay_surface_gfx_update(vdis, 0, first, cols,
						last - first + 1);
	}
}