135 lines
4.2 KiB
C
135 lines
4.2 KiB
C
/**
|
|
* Framebuffer initialization of Asagiri
|
|
* Copyright (C) 2023 Asagiri contributors
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <bits/alltypes.h>
|
|
#include <device.h>
|
|
#include <fb.h>
|
|
#include <fdt.h>
|
|
#include <hal.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
/* The buffer must be 16-byte aligned as only the upper 28 bits of the address
|
|
* can be passed via the mailbox */
|
|
volatile unsigned int __attribute__((aligned(16))) mbox[36];
|
|
|
|
unsigned int width, height, pitch, bpp, rgb;
|
|
unsigned char *fb;
|
|
|
|
void pixel_draw(int x, int y, int r, int g, int b) {
|
|
fb[(pitch * y) + (x * bpp) + 0] = r;
|
|
fb[(pitch * y) + (x * bpp) + 1] = g;
|
|
fb[(pitch * y) + (x * bpp) + 2] = b;
|
|
}
|
|
|
|
unsigned int mbox_call(unsigned char ch) {
|
|
unsigned int m = ((unsigned int)((long)&mbox) & ~0xF)
|
|
| (ch & 0xF); /* 28-bit address (MSB), 4-bit value (LSB) */
|
|
|
|
while (1)
|
|
if (!(mmio_read(MBOX_STATUS) & MBOX_FULL))
|
|
break;
|
|
|
|
mmio_write(MBOX_WRITE, m);
|
|
|
|
while (1) {
|
|
while (1)
|
|
if (!(mmio_read(MBOX_STATUS) & MBOX_EMPTY))
|
|
break; /* Wait for a reply */
|
|
|
|
if (m == mmio_read(MBOX_READ)) { /* Look for a message on MBOX_READ */
|
|
if (mbox[1] == MBOX_RESPONSE)
|
|
return 1; /* Success! */
|
|
else
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void fb_init() {
|
|
fdt_prop mailbox_path = fdt_get_prop(fdt_get_addr("/__symbols__/mailbox"));
|
|
fdt_prop mailbox_reg = fdt_get_prop(fdt_get_addr(strcat((char *)mailbox_path.data, "/reg")));
|
|
MBOX_BASE = SWAP_UINT32(*mailbox_reg.data) - MMIO_BASE;
|
|
|
|
MBOX_READ = (MBOX_BASE + 0x0);
|
|
MBOX_POLL = (MBOX_BASE + 0x10);
|
|
MBOX_SENDER = (MBOX_BASE + 0x14);
|
|
MBOX_STATUS = (MBOX_BASE + 0x18);
|
|
MBOX_CONFIG = (MBOX_BASE + 0x1C);
|
|
MBOX_WRITE = (MBOX_BASE + 0x20);
|
|
|
|
mbox[0] = 35 * 4; /* Length of message in bytes */
|
|
mbox[1] = MBOX_REQUEST;
|
|
|
|
mbox[2] = MBOX_TAG_SETPHYWH;
|
|
mbox[3] = 8; /* Value size in bytes */
|
|
mbox[4] = 0;
|
|
mbox[5] = 640; /* Width, hardcoded for now */
|
|
mbox[6] = 480; /* Height, hardcoded for now */
|
|
|
|
mbox[7] = MBOX_TAG_SETVIRTWH;
|
|
mbox[8] = 8;
|
|
mbox[9] = 8;
|
|
mbox[10] = 640;
|
|
mbox[11] = 480;
|
|
|
|
mbox[12] = MBOX_TAG_SETVIRTOFF;
|
|
mbox[13] = 8;
|
|
mbox[14] = 8;
|
|
mbox[15] = 0; /* X coordinate */
|
|
mbox[16] = 0; /* Y coordinate */
|
|
|
|
mbox[17] = MBOX_TAG_SETDEPTH;
|
|
mbox[18] = 4;
|
|
mbox[19] = 4;
|
|
mbox[20] = 32; /* Bits per pixel */
|
|
|
|
mbox[21] = MBOX_TAG_SETPXLORDR;
|
|
mbox[22] = 4;
|
|
mbox[23] = 4;
|
|
mbox[24] = 1; /* RGB */
|
|
|
|
mbox[25] = MBOX_TAG_GETFB;
|
|
mbox[26] = 8;
|
|
mbox[27] = 8;
|
|
mbox[28] = 4096; /* FrameBufferInfo.pointer */
|
|
mbox[29] = 0; /* FrameBufferInfo.size */
|
|
|
|
mbox[30] = MBOX_TAG_GETPITCH;
|
|
mbox[31] = 4;
|
|
mbox[32] = 4;
|
|
mbox[33] = 0; /* Bytes per line */
|
|
|
|
mbox[34] = MBOX_TAG_LAST;
|
|
|
|
/* Check if mailbox says we're good and that the depth is what we asked for
|
|
* and that it gave us a pointer */
|
|
if (mbox_call(MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) {
|
|
mbox[28] &= 0x3FFFFFFF; /* Convert GPU address to ARM address */
|
|
width = mbox[10]; /* Actual physical width */
|
|
height = mbox[11]; /* Actual physical height */
|
|
pitch = mbox[33]; /* Number of bytes per line */
|
|
rgb = mbox[24]; /* Pixel order */
|
|
fb = (unsigned char *)((long)mbox[28]);
|
|
bpp = pitch / width;
|
|
printf("Initialized framebuffer.\n");
|
|
}
|
|
memset(fb, 0x00, pitch * height);
|
|
}
|