浏览代码

add raspi4 hdmi driver

bigmagic 4 年之前
父节点
当前提交
c97f33d11d

+ 4 - 2
bsp/raspberry-pi/raspi4-32/driver/board.c

@@ -19,8 +19,10 @@
 
 struct mem_desc platform_mem_desc[] = {
     {0x0, 0x6400000, 0x0, NORMAL_MEM},
-    {0xFE000000, 0xFE400000, 0xFE000000, DEVICE_MEM},//uart gpio
-    {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM} //gic
+    {0x8000000, 0x8100000, 0x8000000, DEVICE_MEM},    //mbox msg
+    {0x0EA00000, 0x0EE00000, 0x0EA00000, DEVICE_MEM}, //framebuffer
+    {0xFE000000, 0xFE400000, 0xFE000000, DEVICE_MEM}, //peripheral
+    {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM}  //gic
 };
 
 const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);

+ 307 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.c

@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-26     bigmagic       first version
+ */
+
+#include <stdint.h>
+#include <rtthread.h>
+#include "mbox.h"
+#include "drv_hdmi.h"
+
+#define LCD_WIDTH     (800)
+#define LCD_HEIGHT    (480)
+#define LCD_DEPTH     (32)
+#define LCD_BPP       (32)
+
+#define TAG_ALLOCATE_BUFFER         0x00040001
+#define TAG_SET_PHYS_WIDTH_HEIGHT   0x00048003
+#define TAG_SET_VIRT_WIDTH_HEIGHT   0x00048004
+#define TAG_SET_DEPTH               0x00048005
+#define TAG_SET_PIXEL_ORDER         0x00048006
+#define TAG_GET_PITCH               0x00040008
+#define TAG_SET_VIRT_OFFSET         0x00048009
+#define TAG_END                     0x00000000
+
+
+enum {
+    MBOX_TAG_FB_GET_GPIOVIRT        = 0x00040010,
+    MBOX_TAG_FB_ALLOCATE_BUFFER     = 0x00040001,
+    MBOX_TAG_FB_RELEASE_BUFFER      = 0x00048001,
+    MBOX_TAG_FB_BLANK_SCREEN        = 0x00040002,
+    MBOX_TAG_FB_GET_PHYS_WH         = 0x00040003,
+    MBOX_TAG_FB_TEST_PHYS_WH        = 0x00044003,
+    MBOX_TAG_FB_SET_PHYS_WH         = 0x00048003,
+    MBOX_TAG_FB_GET_VIRT_WH         = 0x00040004,
+    MBOX_TAG_FB_TEST_VIRT_WH        = 0x00044004,
+    MBOX_TAG_FB_SET_VIRT_WH         = 0x00048004,
+    MBOX_TAG_FB_GET_DEPTH           = 0x00040005,
+    MBOX_TAG_FB_TEST_DEPTH          = 0x00044005,
+    MBOX_TAG_FB_SET_DEPTH           = 0x00048005,
+    MBOX_TAG_FB_GET_PIXEL_ORDER     = 0x00040006,
+    MBOX_TAG_FB_TEST_PIXEL_ORDER    = 0x00044006,
+    MBOX_TAG_FB_SET_PIXEL_ORDER     = 0x00048006,
+    MBOX_TAG_FB_GET_ALPHA_MODE      = 0x00040007,
+    MBOX_TAG_FB_TEST_ALPHA_MODE     = 0x00044007,
+    MBOX_TAG_FB_SET_ALPHA_MODE      = 0x00048007,
+    MBOX_TAG_FB_GET_PITCH           = 0x00040008,
+    MBOX_TAG_FB_GET_VIRT_OFFSET     = 0x00040009,
+    MBOX_TAG_FB_TEST_VIRT_OFFSET    = 0x00044009,
+    MBOX_TAG_FB_SET_VIRT_OFFSET     = 0x00048009,
+    MBOX_TAG_FB_GET_OVERSCAN        = 0x0004000a,
+    MBOX_TAG_FB_TEST_OVERSCAN       = 0x0004400a,
+    MBOX_TAG_FB_SET_OVERSCAN        = 0x0004800a,
+    MBOX_TAG_FB_GET_PALETTE         = 0x0004000b,
+    MBOX_TAG_FB_TEST_PALETTE        = 0x0004400b,
+    MBOX_TAG_FB_SET_PALETTE         = 0x0004800b,
+};
+
+#define LCD_DEVICE(dev)    (struct rt_hdmi_fb_device*)(dev)
+
+static struct rt_hdmi_fb_device _hdmi;
+
+typedef rt_uint16_t color_t;
+
+rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    return RT_EOK;
+}
+
+rt_err_t hdmi_fb_close(rt_device_t dev)
+{
+    return RT_EOK;
+}
+
+rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
+{
+    return 0;
+}
+
+rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    return size;
+}
+
+rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
+{
+    struct rt_hdmi_fb_device *lcd = LCD_DEVICE(dev);
+    switch (cmd)
+    {
+    case RTGRAPHIC_CTRL_RECT_UPDATE:
+        {
+            struct rt_device_rect_info *info = (struct rt_device_rect_info*)args;
+            info = info;
+        }
+        break;
+
+    case RTGRAPHIC_CTRL_GET_INFO:
+        {
+           struct rt_device_graphic_info* info = (struct rt_device_graphic_info*)args;
+
+            RT_ASSERT(info != RT_NULL);
+            info->pixel_format  = RTGRAPHIC_PIXEL_FORMAT_RGB888;
+            info->bits_per_pixel= LCD_DEPTH;
+            info->width         = lcd->width;
+            info->height        = lcd->height;
+            info->framebuffer   = lcd->fb;
+        }
+        break;
+    }
+    return RT_EOK;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops hdmi_fb_ops = 
+{
+    RT_NULL,
+    hdmi_fb_open,
+    hdmi_fb_close,
+    hdmi_fb_read,
+    hdmi_fb_write,
+    hdmi_fb_control,
+};
+#endif
+
+rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
+{
+    struct rt_device *device;
+    RT_ASSERT(hdmi_fb != RT_NULL);
+
+    device = &hdmi_fb->parent;
+
+    /* set device type */
+    device->type = RT_Device_Class_Graphic;
+    /* initialize device interface */
+#ifdef RT_USING_DEVICE_OPS
+    device->ops = &hdmi_fb_ops;
+#else
+    device->init = RT_NULL;
+    device->open = hdmi_fb_open;
+    device->close = hdmi_fb_close;
+    device->read = hdmi_fb_read;
+    device->write = hdmi_fb_write;
+    device->control = hdmi_fb_control;
+#endif
+
+    /* register to device manager */
+    rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
+
+    return RT_EOK;
+}
+
+rt_uint32_t bcm271x_mbox_fb_get_gpiovirt(void)
+{
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_GET_GPIOVIRT;
+    mbox[3] = 4;                        // buffer size
+    mbox[4] = 0;                        // len
+
+    mbox[5] = 0;                        // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+    return (mbox[5] & 0x3fffffff);
+}
+
+rt_uint32_t bcm271x_mbox_fb_get_pitch(void)
+{
+    mbox[0] = 8*4;                  // length of the message
+    mbox[1] = MBOX_REQUEST;         // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_GET_PITCH;
+    mbox[3] = 4;                    // buffer size
+    mbox[4] = 0;                    // len
+
+    mbox[5] = 0;                    // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+    return mbox[5];
+}
+
+void bcm271x_mbox_fb_set_porder(int rgb)
+{
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_SET_PIXEL_ORDER;
+    mbox[3] = 4;                        // buffer size
+    mbox[4] = 4;                        // len
+
+    mbox[5] = rgb;                      // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+}
+
+void bcm271x_mbox_fb_setoffset(int xoffset, int yoffset)
+{
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_SET_VIRT_OFFSET;
+    mbox[3] = 8;                        // buffer size
+    mbox[4] = 8;                        // len
+
+    mbox[5] = xoffset;                  // id
+    mbox[6] = yoffset;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+}
+
+
+void bcm271x_mbox_fb_setalpha(int alpha)
+{
+
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_SET_ALPHA_MODE;
+    mbox[3] = 4;                        // buffer size
+    mbox[4] = 4;                        // len
+
+    mbox[5] = alpha;                    // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+}
+
+void *bcm271x_mbox_fb_alloc(int width, int height, int bpp, int nrender)
+{
+    mbox[0] = 4 * 35;
+    mbox[1] = MBOX_REQUEST;
+
+    mbox[2] = TAG_ALLOCATE_BUFFER;//get framebuffer, gets alignment on request
+    mbox[3] = 8;                  //size
+    mbox[4] = 4;                  //len
+    mbox[5] = 4096;               //The design of MBOX driver forces us to give the virtual address 0x3C100000
+    mbox[6] = 0;                  //FrameBufferInfo.size
+
+    mbox[7] = TAG_SET_PHYS_WIDTH_HEIGHT;
+    mbox[8] = 8;
+    mbox[9] = 8;
+    mbox[10] = width;
+    mbox[11] = height;
+
+    mbox[12] = TAG_SET_VIRT_WIDTH_HEIGHT;
+    mbox[13] = 8;
+    mbox[14] = 8;
+    mbox[15] = width;
+    mbox[16] = height * nrender;
+
+    mbox[17] = TAG_SET_DEPTH;
+    mbox[18] = 4;
+    mbox[19] = 4;
+    mbox[20] = bpp;
+
+    mbox[21] = TAG_SET_PIXEL_ORDER;
+    mbox[22] = 4;
+    mbox[23] = 0;
+    mbox[24] = 0;                    //RGB, not BGR preferably
+
+    mbox[25] = TAG_GET_PITCH;
+    mbox[26] = 4;
+    mbox[27] = 0;
+    mbox[28] = 0;
+
+    mbox[29] = TAG_SET_VIRT_OFFSET;
+    mbox[30] = 8;
+    mbox[31] = 8;
+    mbox[32] = 0;
+    mbox[33] = 0;
+
+    mbox[34] = TAG_END;
+
+    mbox_call(8, MMU_DISABLE);
+    return (void *)((rt_uint32_t)(mbox[5] & 0x3fffffff));
+}
+
+int hdmi_fb_init(void)
+{
+    _hdmi.fb = (rt_uint8_t *)bcm271x_mbox_fb_alloc(LCD_WIDTH, LCD_HEIGHT, LCD_BPP, 1);
+    bcm271x_mbox_fb_setoffset(0, 0);
+    bcm271x_mbox_fb_set_porder(0);
+    _hdmi.width = LCD_WIDTH;
+    _hdmi.height = LCD_HEIGHT;
+    _hdmi.depth = LCD_DEPTH;
+    _hdmi.pitch = 0;
+    _hdmi.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
+
+    //rt_kprintf("_hdmi.fb is %p\n", _hdmi.fb);
+    rt_hdmi_fb_device_init(&_hdmi, "lcd");
+
+    return 0;
+}
+
+INIT_DEVICE_EXPORT(hdmi_fb_init);

+ 27 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-26     bigmagic       first version
+ */
+#ifndef __DRV_HDMI_H__
+#define __DRV_HDMI_H__
+
+#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b)))
+
+struct rt_hdmi_fb_device
+{
+    struct rt_device parent;
+
+    rt_uint32_t width;
+    rt_uint32_t height;
+    rt_uint32_t depth;
+    rt_uint32_t pitch;
+    rt_uint32_t pixel_format;
+
+    rt_uint8_t *fb;
+};
+#endif/* __DRV_HDMI_H__ */

+ 46 - 0
bsp/raspberry-pi/raspi4-32/driver/mbox.c

@@ -49,6 +49,52 @@ int mbox_call(unsigned char ch, int mmu_enable)
     return 0;
 }
 
+int bcm271x_notify_reboot(void)
+{
+    mbox[0] = 7*4;                          // length of the message
+    mbox[1] = MBOX_REQUEST;                 // this is a request message
+    mbox[2] = MBOX_TAG_NOTIFY_REBOOT;       // (the tag id)
+    mbox[3] = 0x00000004;                   // length + 4
+    mbox[4] = 0x00000000;                   // size of the data
+    mbox[5] = 0x00000000;                   // request
+
+    mbox[6] = MBOX_TAG_LAST; 
+    mbox_call(8, MMU_DISABLE);
+    return 0;
+}
+
+int bcm271x_notify_xhci_reset(void)
+{
+    mbox[0] = 7*4;                          // length of the message
+    mbox[1] = MBOX_REQUEST;                 // this is a request message
+    mbox[2] = MBOX_TAG_NOTIFY_XHCI_RESET;   // (the tag id)
+    mbox[3] = 0x00000004;                   // length + 4
+    mbox[4] = 0x00000004;                   // size of the data
+    mbox[5] = 0x00100000;                   // request
+    mbox[6] = MBOX_TAG_LAST; 
+    mbox_call(8, MMU_DISABLE);
+    return 0;
+}
+
+int bcm271x_gpu_enable(void)
+{
+    mbox[0] = 12*4;                          // length of the message
+    mbox[1] = MBOX_REQUEST;                  // this is a request message
+    
+    mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
+    mbox[3] = 0x00000008;                   // (the tag id)
+    mbox[4] = 0x00000008;                   // (the tag id)
+    mbox[5] = 5;                            // V3D
+    mbox[6] = 250 * 1000 * 1000;
+    mbox[7] = MBOX_TAG_ENABLE_QPU;                   // (the tag id)
+    mbox[8] = 0x00000004;                   // (size of the buffer)
+    mbox[9] = 0x00000004;                   // (size of the data)
+    mbox[10] = 0x00000001;
+    mbox[11] = MBOX_TAG_LAST;               // end tag
+    mbox_call(8, MMU_DISABLE);
+    return mbox[1];
+}
+
 int bcm271x_mbox_hardware_get_model(void)
 {
     mbox[0] = 8*4;                          // length of the message

+ 43 - 10
bsp/raspberry-pi/raspi4-32/driver/mbox.h

@@ -35,7 +35,7 @@ extern volatile unsigned int* mbox;
 /* tags */
 #define MBOX_TAG_SETPOWER       0x28001
 #define MBOX_TAG_SETCLKRATE     0x38002
-#define MBOX_GET_MAC_ADDRESS	0x10003
+#define MBOX_GET_MAC_ADDRESS    0x10003
 #define MBOX_TAG_LAST           0
 
 #define MMIO_BASE       0xFE000000
@@ -50,14 +50,14 @@ extern volatile unsigned int* mbox;
 #define MBOX_FULL       0x80000000
 #define MBOX_EMPTY      0x40000000
 
-#define DEVICE_ID_SD_CARD	0
-#define DEVICE_ID_USB_HCD	3
-#define POWER_STATE_OFF		(0 << 0)
-#define POWER_STATE_ON		(1 << 0)
-#define POWER_STATE_WAIT	(1 << 1)
-#define POWER_STATE_NO_DEVICE	(1 << 1)	// in response
-#define MMU_ENABLE 1
-#define MMU_DISABLE 0
+#define DEVICE_ID_SD_CARD        (0)
+#define DEVICE_ID_USB_HCD        (3)
+#define POWER_STATE_OFF          (0 << 0)
+#define POWER_STATE_ON           (1 << 0)
+#define POWER_STATE_WAIT         (1 << 1)
+#define POWER_STATE_NO_DEVICE    (1 << 1)    // in response
+#define MMU_ENABLE               (1)
+#define MMU_DISABLE              (0)
 
 /*
  * raspi hardware info
@@ -102,9 +102,42 @@ enum {
     MBOX_TAG_TEMP_GET_MAX   = 0x0003000A,
 };
 
-#define MBOX_ADDR 0xc00000
+/*
+ * raspi Memory
+ */
+enum {
+    MBOX_TAG_ALLOCATE_MEMORY = 0x0003000C, // Memory: Allocates Contiguous Memory On The GPU (Response: Handle)
+    MBOX_TAG_LOCK_MEMORY     = 0x0003000D, // Memory: Unlock Buffer (Response: Status)
+    MBOX_TAG_UNLOCK_MEMORY   = 0x0003000E, // Memory: Unlock Buffer (Response: Status)
+    MBOX_TAG_RELEASE_MEMORY  = 0x0003000F, // Memory: Free The Memory Buffer (Response: Status)
+    MBOX_TAG_EXECUTE_CODE    = 0x00030010, // Memory: Calls The Function At Given (Bus) Address And With Arguments Given
+};
+
+/*
+ * raspi GPU
+ */
+enum {
+    MBOX_TAG_EXECUTE_QPU = 0x00030011, // QPU: Calls The QPU Function At Given (Bus) Address And With Arguments Given (Response: Number Of QPUs, Control, No Flush, Timeout In ms)
+    MBOX_TAG_ENABLE_QPU  = 0x00030012, // QPU: Enables The QPU (Response: Enable State)
+};
+
+/*
+ * raspi HDMI
+ */
+#define MBOX_TAG_GET_EDID_BLOCK        0x00030020 // HDMI: Read Specificed EDID Block From Attached HDMI/DVI Device (Response: Block Number, Status, EDID Block (128 Bytes))
+
+/*
+ * raspi NOTIFY
+ */
+#define MBOX_TAG_NOTIFY_REBOOT         0x00030048
+#define MBOX_TAG_NOTIFY_XHCI_RESET     0x00030058
+
+#define MBOX_ADDR 0x08000000
 
 int mbox_call(unsigned char ch, int mmu_enable);
+int bcm271x_notify_reboot(void);
+int bcm271x_notify_xhci_reset(void);
+int bcm271x_gpu_enable(void);
 int bcm271x_mbox_hardware_get_model(void);
 int bcm271x_mbox_hardware_get_revison(void);
 int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac);