1 /*
2  * Copyright (c) 2017 Eric Holland
3  * Use of this source code is governed by a MIT-style
4  * license that can be found in the LICENSE file or at
5  * https://opensource.org/licenses/MIT
6  */
7 
8 #include <lk/reg.h>
9 #include <lk/err.h>
10 #include <lk/debug.h>
11 #include <lk/trace.h>
12 
13 #include <arch.h>
14 #include <platform.h>
15 #include <arch/ops.h>
16 #include <kernel/vm.h>
17 #include <dev/display.h>
18 
19 #include <platform/bcm28xx.h>
20 #include <platform/mailbox.h>
21 
22 
23 static volatile uint32_t *mailbox_regs = (uint32_t *)ARM0_MAILBOX_BASE;
24 static fb_mbox_t fb_desc __ALIGNED(16);
25 
vc_bus_to_kvaddr(uint32_t bus_addr)26 static inline void *vc_bus_to_kvaddr(uint32_t bus_addr) {
27     return (paddr_to_kvaddr(bus_addr & 0x3fffffff));
28 }
29 
kvaddr_to_vc_bus(addr_t kvaddr)30 static inline uint32_t kvaddr_to_vc_bus(addr_t kvaddr) {
31     return (uint32_t)((kvaddr & 0x3fffffff)+BCM_SDRAM_BUS_ADDR_BASE);
32 }
33 
34 #define MAILBOX_WAIT_TIMEOUT_US 500000
35 #define MAILBOX_MAX_READ_ATTEMPTS 20
36 
mailbox_write(const enum mailbox_channel ch,uint32_t value)37 static status_t mailbox_write(const enum mailbox_channel ch, uint32_t value) {
38     value = value | ch;
39 
40     lk_time_t now = current_time();
41 
42     // Wait for there to be space in the FIFO.
43     while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_FULL) {
44         if ( (now + MAILBOX_WAIT_TIMEOUT_US) < current_time()) {
45             return ERR_TIMED_OUT;
46         }
47     }
48 
49     // Write the value to the mailbox.
50     mailbox_regs[MAILBOX_WRITE] = value;
51 
52     return NO_ERROR;
53 }
54 
mailbox_read(enum mailbox_channel ch,uint32_t * result)55 static status_t mailbox_read(enum mailbox_channel ch, uint32_t *result) {
56     uint32_t local_result = 0;
57     uint32_t attempts = 0;
58 
59     lk_time_t deadline;
60 
61     do {
62         deadline = current_time() + MAILBOX_WAIT_TIMEOUT_US;
63         while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_EMPTY) {
64             if (current_time() > deadline)
65                 return ERR_TIMED_OUT;
66         }
67 
68         local_result = mailbox_regs[MAILBOX_READ];
69 
70         attempts++;
71 
72     } while ((((local_result)&0xF) != ch) && (attempts < MAILBOX_MAX_READ_ATTEMPTS));
73 
74     *result = (local_result);
75 
76     return attempts < MAX_MAILBOX_READ_ATTEMPTS ? NO_ERROR : ERR_IO;
77 }
78 
79 
mailbox_get_framebuffer(fb_mbox_t * fb)80 static status_t mailbox_get_framebuffer(fb_mbox_t *fb) {
81     status_t ret = NO_ERROR;
82 
83     arch_clean_cache_range((addr_t)fb,sizeof(fb_mbox_t));
84 
85     ret = mailbox_write(ch_framebuffer, kvaddr_to_vc_bus((addr_t)fb));
86     if (ret != NO_ERROR)
87         return ret;
88 
89     uint32_t ack = 0x0;
90     ret = mailbox_read(ch_framebuffer, &ack);
91     if (ret != NO_ERROR)
92         return ret;
93 
94     arch_invalidate_cache_range((addr_t)fb,sizeof(fb_mbox_t));
95 
96     return ret;
97 }
98 
init_framebuffer(void)99 status_t init_framebuffer(void) {
100 
101     fb_desc.phys_width = 800;
102     fb_desc.phys_height = 480;
103     fb_desc.virt_width = 800;
104     fb_desc.virt_height = 480;
105     fb_desc.pitch = 0;
106     fb_desc.depth = 32;
107     fb_desc.virt_x_offs = 0;
108     fb_desc.virt_y_offs = 0;
109     fb_desc.fb_p = 0;
110     fb_desc.fb_size = 0;
111 
112     status_t ret = mailbox_get_framebuffer(&fb_desc);
113 
114     return ret;
115 }
116 
dispflush(void)117 void dispflush(void) {
118 
119     //arch_clean_cache_range(fb_desc,sizeof(fb_mbox_t));
120 
121 }
122 
123 /* LK display (lib/gfx.h) calls this function */
display_get_framebuffer(struct display_framebuffer * fb)124 status_t display_get_framebuffer(struct display_framebuffer *fb) {
125     // VideoCore returns 32-bit bus address, which needs to be converted to kernel virtual
126     fb->image.pixels = paddr_to_kvaddr(fb_desc.fb_p & 0x3fffffff);
127 
128     fb->format = DISPLAY_FORMAT_ARGB_8888;
129     fb->image.format = IMAGE_FORMAT_ARGB_8888;
130     fb->image.rowbytes = fb_desc.phys_width * fb_desc.depth/8;
131 
132     fb->image.width = fb_desc.phys_width;
133     fb->image.height = fb_desc.phys_height;
134     fb->image.stride = fb_desc.phys_width;
135     fb->flush = NULL;
136 
137     return NO_ERROR;
138 }
139 
display_get_info(struct display_info * info)140 status_t display_get_info(struct display_info *info) {
141     info->format = DISPLAY_FORMAT_ARGB_8888;
142     info->width = fb_desc.phys_width;
143     info->height = fb_desc.phys_height;
144 
145     return NO_ERROR;
146 }
147 
display_present(struct display_image * image,uint starty,uint endy)148 status_t display_present(struct display_image *image, uint starty, uint endy) {
149     return NO_ERROR;
150 }
151 
152 
153 
154