Created
June 23, 2015 13:11
-
-
Save notro/25f289e8382bc444e9e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi | |
index 8caa234..69533af 100644 | |
--- a/arch/arm/boot/dts/bcm2708_common.dtsi | |
+++ b/arch/arm/boot/dts/bcm2708_common.dtsi | |
@@ -162,6 +162,11 @@ | |
<1 9>; | |
}; | |
+ firmware: firmware { | |
+ compatible = "raspberrypi,bcm2835-firmware"; | |
+ mboxes = <&mailbox>; | |
+ }; | |
+ | |
leds: leds { | |
compatible = "gpio-leds"; | |
}; | |
diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig | |
index a3067bf..0fbe1b5 100644 | |
--- a/arch/arm/configs/bcm2709_defconfig | |
+++ b/arch/arm/configs/bcm2709_defconfig | |
@@ -1066,6 +1066,7 @@ CONFIG_IIO_BUFFER=y | |
CONFIG_IIO_BUFFER_CB=y | |
CONFIG_IIO_KFIFO_BUF=m | |
CONFIG_DHT11=m | |
+CONFIG_RASPBERRYPI_FIRMWARE=y | |
CONFIG_EXT4_FS=y | |
CONFIG_EXT4_FS_POSIX_ACL=y | |
CONFIG_EXT4_FS_SECURITY=y | |
diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig | |
index 6a41231..4271c78 100644 | |
--- a/arch/arm/configs/bcmrpi_defconfig | |
+++ b/arch/arm/configs/bcmrpi_defconfig | |
@@ -1059,6 +1059,7 @@ CONFIG_IIO_BUFFER=y | |
CONFIG_IIO_BUFFER_CB=y | |
CONFIG_IIO_KFIFO_BUF=m | |
CONFIG_DHT11=m | |
+CONFIG_RASPBERRYPI_FIRMWARE=y | |
CONFIG_EXT4_FS=y | |
CONFIG_EXT4_FS_POSIX_ACL=y | |
CONFIG_EXT4_FS_SECURITY=y | |
diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c | |
index 937c2d3..a321342 100644 | |
--- a/arch/arm/mach-bcm2708/bcm2708.c | |
+++ b/arch/arm/mach-bcm2708/bcm2708.c | |
@@ -415,6 +415,16 @@ static struct platform_device bcm2708_vcio_device = { | |
}, | |
}; | |
+static u64 rpifw_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); | |
+ | |
+static struct platform_device bcm2708_rpifw_device = { | |
+ .name = "raspberrypi-firmware", | |
+ .dev = { | |
+ .dma_mask = &rpifw_dmamask, | |
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), | |
+ }, | |
+}; | |
+ | |
static struct resource bcm2708_vchiq_resources[] = { | |
{ | |
.start = ARMCTRL_0_BELL_BASE, | |
@@ -871,6 +881,7 @@ void __init bcm2708_init(void) | |
bcm_register_device_dt(&bcm2708_dmaengine_device); | |
bcm_register_device_dt(&bcm2708_vcio_device); | |
+ bcm_register_device_dt(&bcm2708_rpifw_device); | |
bcm_register_device_dt(&bcm2708_vchiq_device); | |
#ifdef CONFIG_BCM2708_GPIO | |
bcm_register_device_dt(&bcm2708_gpio_device); | |
diff --git a/arch/arm/mach-bcm2709/bcm2709.c b/arch/arm/mach-bcm2709/bcm2709.c | |
index fe71c50..88fb3ce5 100644 | |
--- a/arch/arm/mach-bcm2709/bcm2709.c | |
+++ b/arch/arm/mach-bcm2709/bcm2709.c | |
@@ -436,6 +436,16 @@ static struct platform_device bcm2708_vcio_device = { | |
}, | |
}; | |
+static u64 rpifw_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); | |
+ | |
+static struct platform_device bcm2708_rpifw_device = { | |
+ .name = "raspberrypi-firmware", | |
+ .dev = { | |
+ .dma_mask = &rpifw_dmamask, | |
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), | |
+ }, | |
+}; | |
+ | |
static struct resource bcm2708_vchiq_resources[] = { | |
{ | |
.start = ARMCTRL_0_BELL_BASE, | |
@@ -892,6 +902,7 @@ void __init bcm2709_init(void) | |
bcm_register_device_dt(&bcm2708_dmaengine_device); | |
bcm_register_device_dt(&bcm2708_vcio_device); | |
+ bcm_register_device_dt(&bcm2708_rpifw_device); | |
bcm_register_device_dt(&bcm2708_vchiq_device); | |
#ifdef CONFIG_BCM2708_GPIO | |
bcm_register_device_dt(&bcm2708_gpio_device); | |
diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c | |
index 0bfb42e..5a36c1e 100644 | |
--- a/drivers/char/broadcom/vc_sm/vmcs_sm.c | |
+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c | |
@@ -3008,6 +3008,7 @@ out: | |
static int __init vc_sm_init(void) | |
{ | |
pr_info("vc-sm: Videocore shared memory driver\n"); | |
+if (0) | |
vchiq_add_connected_callback(vc_sm_connected_init); | |
return 0; | |
} | |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig | |
index 564aa5b..3d07bbf 100644 | |
--- a/drivers/firmware/Kconfig | |
+++ b/drivers/firmware/Kconfig | |
@@ -138,7 +138,7 @@ config QCOM_SCM | |
config RASPBERRYPI_FIRMWARE | |
tristate "Raspberry Pi Firmware Driver" | |
- depends on BCM2835_MBOX | |
+ depends on BCM2708_MBOX | |
help | |
This option enables support for communicating with the firmware on the | |
Raspberry Pi. | |
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c | |
index dd506cd..84352d8 100644 | |
--- a/drivers/firmware/raspberrypi.c | |
+++ b/drivers/firmware/raspberrypi.c | |
@@ -19,7 +19,6 @@ | |
#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) | |
#define MBOX_CHAN(msg) ((msg) & 0xf) | |
#define MBOX_DATA28(msg) ((msg) & ~0xf) | |
-#define MBOX_CHAN_PROPERTY 8 | |
struct rpi_firmware { | |
struct mbox_client cl; | |
@@ -30,37 +29,60 @@ struct rpi_firmware { | |
static DEFINE_MUTEX(transaction_lock); | |
+static struct platform_device *g_pdev; | |
+int bcm_mailbox_read(unsigned chan, uint32_t *data28); | |
+int bcm_mailbox_write(unsigned chan, uint32_t data28); | |
+ | |
static void response_callback(struct mbox_client *cl, void *msg) | |
{ | |
struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl); | |
complete(&fw->c); | |
} | |
-/* | |
+/** | |
+ * rpi_firmware_transaction - Send firmware request | |
+ * @fw: Pointer to firmware structure from rpi_firmware_get(). | |
+ * @chan: Mailbox channel | |
+ * @data: Data to send | |
+ * | |
* Sends a request to the firmware through the BCM2835 mailbox driver, | |
* and synchronously waits for the reply. | |
*/ | |
-static int | |
-rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data) | |
+int rpi_firmware_transaction(struct rpi_firmware *fw, | |
+ enum rpi_fimware_channel chan, u32 data) | |
{ | |
- u32 message = MBOX_MSG(chan, data); | |
+ u32 message; | |
int ret; | |
WARN_ON(data & 0xf); | |
+pr_info("%s: data=0x%x\n", __func__, data); | |
mutex_lock(&transaction_lock); | |
- reinit_completion(&fw->c); | |
- ret = mbox_send_message(fw->chan, &message); | |
- if (ret >= 0) { | |
- wait_for_completion(&fw->c); | |
- ret = 0; | |
- } else { | |
- dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret); | |
+ wmb(); | |
+ ret = bcm_mailbox_write(chan, data); | |
+ if (ret) { | |
+ dev_err(fw->cl.dev, "bcm_mailbox_write returned %d\n", ret); | |
+ goto unlock; | |
} | |
+ | |
+ if (chan == MBOX_CHAN_VCHIQ) /* this channel does not reply */ | |
+ goto unlock; | |
+ | |
+ ret = bcm_mailbox_read(chan, &message); | |
+ rmb(); | |
+ | |
+ if (!ret && chan == MBOX_CHAN_FB && message != 0) { | |
+ dev_err(fw->cl.dev, "MBOX_CHAN_FB message failed 0x%08x\n", message); | |
+ ret = -EIO; | |
+ } | |
+pr_info("%s: message=0x%x\n", __func__, message); | |
+ | |
+unlock: | |
mutex_unlock(&transaction_lock); | |
return ret; | |
} | |
+EXPORT_SYMBOL(rpi_firmware_transaction); | |
/** | |
* rpi_firmware_property_list - Submit firmware property list | |
@@ -183,6 +205,26 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) | |
} | |
} | |
+static int raspberrypi_firmware_set_power(struct rpi_firmware *fw, | |
+ u32 domain, bool on) | |
+{ | |
+ struct { | |
+ u32 domain; | |
+ u32 on; | |
+ } packet; | |
+ int ret; | |
+ | |
+printk("%s(domain=%u, on=%u)\n", __func__, domain, on); | |
+ packet.domain = domain; | |
+ packet.on = on; | |
+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_SET_POWER_STATE, | |
+ &packet, sizeof(packet)); | |
+ if (!ret && packet.on != on) | |
+ ret = -EINVAL; | |
+ | |
+ return ret; | |
+} | |
+ | |
static int rpi_firmware_probe(struct platform_device *pdev) | |
{ | |
struct device *dev = &pdev->dev; | |
@@ -196,28 +238,20 @@ static int rpi_firmware_probe(struct platform_device *pdev) | |
fw->cl.rx_callback = response_callback; | |
fw->cl.tx_block = true; | |
- fw->chan = mbox_request_channel(&fw->cl, 0); | |
- if (IS_ERR(fw->chan)) { | |
- int ret = PTR_ERR(fw->chan); | |
- if (ret != -EPROBE_DEFER) | |
- dev_err(dev, "Failed to get mbox channel: %d\n", ret); | |
- return ret; | |
- } | |
- | |
- init_completion(&fw->c); | |
- | |
+ g_pdev = pdev; | |
platform_set_drvdata(pdev, fw); | |
rpi_firmware_print_firmware_revision(fw); | |
+ if (raspberrypi_firmware_set_power(fw, 3, true)) | |
+ dev_err(dev, "failed to turn on USB power\n"); | |
+ | |
return 0; | |
} | |
static int rpi_firmware_remove(struct platform_device *pdev) | |
{ | |
- struct rpi_firmware *fw = platform_get_drvdata(pdev); | |
- | |
- mbox_free_channel(fw->chan); | |
+ g_pdev = NULL; | |
return 0; | |
} | |
@@ -230,7 +264,7 @@ static int rpi_firmware_remove(struct platform_device *pdev) | |
*/ | |
struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) | |
{ | |
- struct platform_device *pdev = of_find_device_by_node(firmware_node); | |
+ struct platform_device *pdev = g_pdev; | |
if (!pdev) | |
return NULL; | |
@@ -253,7 +287,18 @@ static struct platform_driver rpi_firmware_driver = { | |
.probe = rpi_firmware_probe, | |
.remove = rpi_firmware_remove, | |
}; | |
-module_platform_driver(rpi_firmware_driver); | |
+ | |
+static int __init rpi_firmware_init(void) | |
+{ | |
+ return platform_driver_register(&rpi_firmware_driver); | |
+} | |
+subsys_initcall(rpi_firmware_init); | |
+ | |
+static void __init rpi_firmware_exit(void) | |
+{ | |
+ platform_driver_unregister(&rpi_firmware_driver); | |
+} | |
+module_exit(rpi_firmware_exit); | |
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); | |
MODULE_DESCRIPTION("Raspberry Pi firmware driver"); | |
diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | |
index c739083..c85c9b6 100644 | |
--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | |
+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | |
@@ -39,10 +39,10 @@ | |
#include <linux/dma-mapping.h> | |
#include <linux/version.h> | |
#include <linux/io.h> | |
-#include <linux/platform_data/mailbox-bcm2708.h> | |
#include <linux/platform_device.h> | |
#include <linux/uaccess.h> | |
#include <asm/pgtable.h> | |
+#include <soc/bcm2835/raspberrypi-firmware.h> | |
#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) | |
@@ -86,10 +86,12 @@ free_pagelist(PAGELIST_T *pagelist, int actual); | |
int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) | |
{ | |
struct device *dev = &pdev->dev; | |
+ struct rpi_firmware *fw = platform_get_drvdata(pdev); | |
VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; | |
struct resource *res; | |
void *slot_mem; | |
dma_addr_t slot_phys; | |
+ u32 channelbase; | |
int slot_mem_size, frag_mem_size; | |
int err, irq, i; | |
@@ -150,10 +152,15 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) | |
} | |
/* Send the base address of the slots to VideoCore */ | |
+// err = rpi_firmware_transaction(fw, MBOX_CHAN_VCHIQ, slot_phys); | |
- dsb(); /* Ensure all writes have completed */ | |
+printk("%s: slot_phys=%pad\n", __func__, &slot_phys); | |
+ channelbase = slot_phys; | |
+printk("%s: channelbase=0x%x\n", __func__, channelbase); | |
+ err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, | |
+ &channelbase, sizeof(channelbase)); | |
+printk("%s: channelbase=0x%x\n", __func__, channelbase); | |
- err = bcm_mailbox_write(MBOX_CHAN_VCHIQ, (unsigned int)slot_phys); | |
if (err) { | |
dev_err(dev, "mailbox write failed\n"); | |
return err; | |
diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c | |
index 31e2cba..61d8802 100644 | |
--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c | |
+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c | |
@@ -46,6 +46,7 @@ | |
#include <linux/semaphore.h> | |
#include <linux/list.h> | |
#include <linux/platform_device.h> | |
+#include <soc/bcm2835/raspberrypi-firmware.h> | |
#include "vchiq_core.h" | |
#include "vchiq_ioctl.h" | |
@@ -2793,9 +2794,16 @@ void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, | |
static int vchiq_probe(struct platform_device *pdev) | |
{ | |
+ struct rpi_firmware *fw; | |
int err; | |
void *ptr_err; | |
+ fw = rpi_firmware_get(NULL); | |
+ if (!fw) | |
+ return -EPROBE_DEFER; | |
+ | |
+ platform_set_drvdata(pdev, fw); | |
+ | |
/* create debugfs entries */ | |
err = vchiq_debugfs_init(); | |
if (err != 0) | |
diff --git a/drivers/soc/bcm2835/bcm2708-power.c b/drivers/soc/bcm2835/bcm2708-power.c | |
index e7931a9..63c5052 100644 | |
--- a/drivers/soc/bcm2835/bcm2708-power.c | |
+++ b/drivers/soc/bcm2835/bcm2708-power.c | |
@@ -163,6 +163,7 @@ static int __init bcm_power_init(void) | |
int i; | |
printk(KERN_INFO "bcm_power: Broadcom power driver\n"); | |
+return 0; | |
bcm_mailbox_write(MBOX_CHAN_POWER, 0); | |
for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) | |
diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c | |
index f6ac7da..45c4c43 100644 | |
--- a/drivers/video/fbdev/bcm2708_fb.c | |
+++ b/drivers/video/fbdev/bcm2708_fb.c | |
@@ -1,3 +1,4 @@ | |
+#define DEBUG | |
/* | |
* linux/drivers/video/bcm2708_fb.c | |
* | |
@@ -25,7 +26,6 @@ | |
#include <linux/ioport.h> | |
#include <linux/list.h> | |
#include <linux/platform_data/dma-bcm2708.h> | |
-#include <linux/platform_data/mailbox-bcm2708.h> | |
#include <linux/platform_device.h> | |
#include <linux/clk.h> | |
#include <linux/printk.h> | |
@@ -34,8 +34,9 @@ | |
#include <asm/sizes.h> | |
#include <linux/io.h> | |
#include <linux/dma-mapping.h> | |
+#include <soc/bcm2835/raspberrypi-firmware.h> | |
-//#define BCM2708_FB_DEBUG | |
+#define BCM2708_FB_DEBUG | |
#define MODULE_NAME "bcm2708_fb" | |
#ifdef BCM2708_FB_DEBUG | |
@@ -60,13 +61,13 @@ MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below th | |
/* this data structure describes each frame buffer device we find */ | |
-struct fbinfo_s { | |
- u32 xres, yres, xres_virtual, yres_virtual; | |
- u32 pitch, bpp; | |
- u32 xoffset, yoffset; | |
- u32 base; | |
- u32 screen_size; | |
- u16 cmap[256]; | |
+struct fb_alloc_tags { | |
+ u32 tag1, size1, r1, xres, yres; | |
+ u32 tag2, size2, r2, xres_virtual, yres_virtual; | |
+ u32 tag3, size3, r3, bpp; | |
+ u32 tag4, size4, r4, xoffset, yoffset; | |
+ u32 tag5, size5, r5, base, screen_size; | |
+ u32 tag6, size6, r6, pitch; | |
}; | |
struct bcm2708_fb_stats { | |
@@ -78,9 +79,9 @@ struct bcm2708_fb_stats { | |
struct bcm2708_fb { | |
struct fb_info fb; | |
struct platform_device *dev; | |
- struct fbinfo_s *info; | |
- dma_addr_t dma; | |
+ struct rpi_firmware *fw; | |
u32 cmap[16]; | |
+ u32 gpu_cmap[256]; | |
int dma_chan; | |
int dma_irq; | |
void __iomem *dma_chan_base; | |
@@ -270,54 +271,61 @@ static int bcm2708_fb_check_var(struct fb_var_screeninfo *var, | |
static int bcm2708_fb_set_par(struct fb_info *info) | |
{ | |
- uint32_t val = 0; | |
struct bcm2708_fb *fb = to_bcm2708(info); | |
- volatile struct fbinfo_s *fbinfo = fb->info; | |
- fbinfo->xres = info->var.xres; | |
- fbinfo->yres = info->var.yres; | |
- fbinfo->xres_virtual = info->var.xres_virtual; | |
- fbinfo->yres_virtual = info->var.yres_virtual; | |
- fbinfo->bpp = info->var.bits_per_pixel; | |
- fbinfo->xoffset = info->var.xoffset; | |
- fbinfo->yoffset = info->var.yoffset; | |
- fbinfo->base = 0; /* filled in by VC */ | |
- fbinfo->pitch = 0; /* filled in by VC */ | |
+ struct fb_alloc_tags fbinfo = { | |
+ .tag1 = RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT, | |
+ .size1 = 8, .r1 = 0, | |
+ .xres = info->var.xres, | |
+ .yres = info->var.yres, | |
+ .tag2 = RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT, | |
+ .size2 = 8, .r2 = 0, | |
+ .xres_virtual = info->var.xres_virtual, | |
+ .yres_virtual = info->var.yres_virtual, | |
+ .tag3 = RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, | |
+ .size3 = 4, .r3 = 0, | |
+ .bpp = info->var.bits_per_pixel, | |
+ .tag4 = RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, | |
+ .size4 = 8, .r4 = 0, | |
+ .xoffset = info->var.xoffset, | |
+ .yoffset = info->var.yoffset, | |
+ .tag5 = RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, | |
+ .size5 = 8, .r5 = 0, | |
+ .base = 0, | |
+ .screen_size = 0, | |
+ .tag6 = RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, | |
+ .size6 = 4, .r6 = 0, | |
+ .pitch = 0, | |
+ }; | |
+ int val; | |
print_debug("bcm2708_fb_set_par info(%p) %dx%d (%dx%d), %d, %d\n", info, | |
info->var.xres, info->var.yres, info->var.xres_virtual, | |
info->var.yres_virtual, (int)info->screen_size, | |
info->var.bits_per_pixel); | |
- /* ensure last write to fbinfo is visible to GPU */ | |
- wmb(); | |
- | |
- /* inform vc about new framebuffer */ | |
- bcm_mailbox_write(MBOX_CHAN_FB, fb->dma); | |
- | |
- /* TODO: replace fb driver with vchiq version */ | |
- /* wait for response */ | |
- bcm_mailbox_read(MBOX_CHAN_FB, &val); | |
- | |
- /* ensure GPU writes are visible to us */ | |
- rmb(); | |
- | |
+ val = rpi_firmware_property_list(fb->fw, &fbinfo, sizeof(fbinfo)); | |
if (val == 0) { | |
- fb->fb.fix.line_length = fbinfo->pitch; | |
+ fb->fb.fix.line_length = fbinfo.pitch; | |
if (info->var.bits_per_pixel <= 8) | |
fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; | |
else | |
fb->fb.fix.visual = FB_VISUAL_TRUECOLOR; | |
- fb->fb_bus_address = fbinfo->base; | |
- fbinfo->base &= ~0xc0000000; | |
- fb->fb.fix.smem_start = fbinfo->base; | |
- fb->fb.fix.smem_len = fbinfo->pitch * fbinfo->yres_virtual; | |
- fb->fb.screen_size = fbinfo->screen_size; | |
+printk("fbinfo.base=0x%x\n", fbinfo.base); | |
+ fbinfo.base |= 0x40000000; | |
+ | |
+ fb->fb_bus_address = fbinfo.base; | |
+printk("fb->fb_bus_address=0x%lx\n", fb->fb_bus_address); | |
+ fbinfo.base &= ~0xc0000000; | |
+ fb->fb.fix.smem_start = fbinfo.base; | |
+printk("fb->fb.fix.smem_start=0x%lx\n", fb->fb.fix.smem_start); | |
+ fb->fb.fix.smem_len = fbinfo.pitch * fbinfo.yres_virtual; | |
+ fb->fb.screen_size = fbinfo.screen_size; | |
if (fb->fb.screen_base) | |
iounmap(fb->fb.screen_base); | |
fb->fb.screen_base = | |
- (void *)ioremap_wc(fbinfo->base, fb->fb.screen_size); | |
+ (void *)ioremap_wc(fbinfo.base, fb->fb.screen_size); | |
if (!fb->fb.screen_base) { | |
/* the console may currently be locked */ | |
console_trylock(); | |
@@ -329,8 +337,8 @@ static int bcm2708_fb_set_par(struct fb_info *info) | |
print_debug | |
("BCM2708FB: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d success=%d\n", | |
(void *)fb->fb.screen_base, (void *)fb->fb_bus_address, | |
- fbinfo->xres, fbinfo->yres, fbinfo->bpp, | |
- fbinfo->pitch, (int)fb->fb.screen_size, val); | |
+ fbinfo.xres, fbinfo.yres, fbinfo.bpp, | |
+ fbinfo.pitch, (int)fb->fb.screen_size, val); | |
return val; | |
} | |
@@ -348,19 +356,39 @@ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red, | |
unsigned int transp, struct fb_info *info) | |
{ | |
struct bcm2708_fb *fb = to_bcm2708(info); | |
+ struct packet { | |
+ u32 offset; | |
+ u32 length; | |
+ u32 cmap[256]; | |
+ }; | |
/*print_debug("BCM2708FB: setcolreg %d:(%02x,%02x,%02x,%02x) %x\n", regno, red, green, blue, transp, fb->fb.fix.visual);*/ | |
if (fb->fb.var.bits_per_pixel <= 8) { | |
if (regno < 256) { | |
/* blue [0:4], green [5:10], red [11:15] */ | |
- fb->info->cmap[regno] = ((red >> (16-5)) & 0x1f) << 11 | | |
- ((green >> (16-6)) & 0x3f) << 5 | | |
- ((blue >> (16-5)) & 0x1f) << 0; | |
+ fb->gpu_cmap[regno] = ((red >> (16-5)) & 0x1f) << 11 | | |
+ ((green >> (16-6)) & 0x3f) << 5 | | |
+ ((blue >> (16-5)) & 0x1f) << 0; | |
} | |
/* Hack: we need to tell GPU the palette has changed, but currently bcm2708_fb_set_par takes noticable time when called for every (256) colour */ | |
/* So just call it for what looks like the last colour in a list for now. */ | |
- if (regno == 15 || regno == 255) | |
- bcm2708_fb_set_par(info); | |
+ if (regno == 15 || regno == 255) { | |
+ struct packet *packet; | |
+ int ret; | |
+ | |
+ packet = kmalloc(sizeof(*packet), GFP_KERNEL); | |
+ if (!packet) | |
+ return -ENOMEM; | |
+printk("%s: set palette\n", __func__); | |
+ packet->offset = 0; | |
+ packet->length = regno; | |
+ memcpy(packet->cmap, fb->gpu_cmap, sizeof(packet->cmap)); | |
+ ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE, | |
+ packet, (2 + regno) * sizeof(u32)); | |
+ if (ret) | |
+ pr_err("%s: failed to set palette (%d)\n", __func__, ret); | |
+ kfree(packet); | |
+ } | |
} else if (regno < 16) { | |
fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) | | |
convert_bitfield(blue, &fb->fb.var.blue) | | |
@@ -372,27 +400,30 @@ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red, | |
static int bcm2708_fb_blank(int blank_mode, struct fb_info *info) | |
{ | |
- s32 result = -1; | |
- u32 p[7]; | |
- if ( (blank_mode == FB_BLANK_NORMAL) || | |
- (blank_mode == FB_BLANK_UNBLANK)) { | |
- | |
- p[0] = 28; // size = sizeof u32 * length of p | |
- p[1] = VCMSG_PROCESS_REQUEST; // process request | |
- p[2] = VCMSG_SET_BLANK_SCREEN; // (the tag id) | |
- p[3] = 4; // (size of the response buffer) | |
- p[4] = 4; // (size of the request data) | |
- p[5] = blank_mode; | |
- p[6] = VCMSG_PROPERTY_END; // end tag | |
- | |
- bcm_mailbox_property(&p, p[0]); | |
- | |
- if ( p[1] == VCMSG_REQUEST_SUCCESSFUL ) | |
- result = 0; | |
- else | |
- pr_err("bcm2708_fb_blank(%d) returns=%d p[1]=0x%x\n", blank_mode, p[5], p[1]); | |
+ struct bcm2708_fb *fb = to_bcm2708(info); | |
+ u32 value; | |
+ int ret; | |
+ | |
+ switch (blank_mode) { | |
+ case FB_BLANK_UNBLANK: | |
+ value = 0; | |
+ break; | |
+ case FB_BLANK_NORMAL: | |
+ case FB_BLANK_VSYNC_SUSPEND: | |
+ case FB_BLANK_HSYNC_SUSPEND: | |
+ case FB_BLANK_POWERDOWN: | |
+ value = 1; | |
+ break; | |
+ default: | |
+ return -EINVAL; | |
} | |
- return result; | |
+ | |
+ ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK, | |
+ &value, sizeof(value)); | |
+ if (ret) | |
+ dev_err(info->device, "bcm2708_fb_blank(%d) returns=%d\n", blank_mode, ret); | |
+ | |
+ return ret; | |
} | |
static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |
@@ -408,25 +439,25 @@ static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info | |
static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | |
{ | |
- s32 result = -1; | |
- u32 p[7]; | |
- if (cmd == FBIO_WAITFORVSYNC) { | |
- p[0] = 28; // size = sizeof u32 * length of p | |
- p[1] = VCMSG_PROCESS_REQUEST; // process request | |
- p[2] = VCMSG_SET_VSYNC; // (the tag id) | |
- p[3] = 4; // (size of the response buffer) | |
- p[4] = 4; // (size of the request data) | |
- p[5] = 0; // dummy | |
- p[6] = VCMSG_PROPERTY_END; // end tag | |
- | |
- bcm_mailbox_property(&p, p[0]); | |
- | |
- if ( p[1] == VCMSG_REQUEST_SUCCESSFUL ) | |
- result = 0; | |
- else | |
- pr_err("bcm2708_fb_ioctl %x,%lx returns=%d p[1]=0x%x\n", cmd, arg, p[5], p[1]); | |
+ struct bcm2708_fb *fb = to_bcm2708(info); | |
+ u32 dummy = 0; | |
+ int ret; | |
+ | |
+ switch (cmd) { | |
+ case FBIO_WAITFORVSYNC: | |
+ ret = rpi_firmware_property(fb->fw, | |
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC, | |
+ &dummy, sizeof(dummy)); | |
+ break; | |
+ default: | |
+ dev_err(info->device, "Unknown ioctl 0x%x\n", cmd); | |
+ return -EINVAL; | |
} | |
- return result; | |
+ | |
+ if (ret) | |
+ dev_err(info->device, "ioctl 0x%x failed (%d)\n", cmd, ret); | |
+ | |
+ return ret; | |
} | |
static void bcm2708_fb_fillrect(struct fb_info *info, | |
const struct fb_fillrect *rect) | |
@@ -621,20 +652,7 @@ static struct fb_ops bcm2708_fb_ops = { | |
static int bcm2708_fb_register(struct bcm2708_fb *fb) | |
{ | |
int ret; | |
- dma_addr_t dma; | |
- void *mem; | |
- mem = | |
- dma_alloc_coherent(&fb->dev->dev, PAGE_ALIGN(sizeof(*fb->info)), &dma, | |
- GFP_KERNEL); | |
- | |
- if (NULL == mem) { | |
- pr_err(": unable to allocate fbinfo buffer\n"); | |
- ret = -ENOMEM; | |
- } else { | |
- fb->info = (struct fbinfo_s *)mem; | |
- fb->dma = dma; | |
- } | |
fb->fb.fbops = &bcm2708_fb_ops; | |
fb->fb.flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_COPYAREA; | |
fb->fb.pseudo_palette = fb->cmap; | |
@@ -694,8 +712,13 @@ out: | |
static int bcm2708_fb_probe(struct platform_device *dev) | |
{ | |
struct bcm2708_fb *fb; | |
+ struct rpi_firmware *fw; | |
int ret; | |
+ fw = rpi_firmware_get(NULL); | |
+ if (!fw) | |
+ return -EPROBE_DEFER; | |
+ | |
fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL); | |
if (!fb) { | |
dev_err(&dev->dev, | |
@@ -704,6 +727,7 @@ static int bcm2708_fb_probe(struct platform_device *dev) | |
goto free_region; | |
} | |
+ fb->fw = fw; | |
bcm2708_fb_debugfs_init(fb); | |
fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K, | |
@@ -769,8 +793,6 @@ static int bcm2708_fb_remove(struct platform_device *dev) | |
dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle); | |
bcm_dma_chan_free(fb->dma_chan); | |
- dma_free_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), (void *)fb->info, | |
- fb->dma); | |
bcm2708_fb_debugfs_deinit(fb); | |
free_irq(fb->dma_irq, fb); | |
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h | |
index 9d9efb7..d236119 100644 | |
--- a/include/soc/bcm2835/raspberrypi-firmware.h | |
+++ b/include/soc/bcm2835/raspberrypi-firmware.h | |
@@ -11,6 +11,13 @@ | |
struct rpi_firmware; | |
+enum rpi_fimware_channel { | |
+ MBOX_CHAN_POWER = 0, | |
+ MBOX_CHAN_FB = 1, | |
+ MBOX_CHAN_VCHIQ= 3, | |
+ MBOX_CHAN_PROPERTY = 8, | |
+}; | |
+ | |
enum rpi_firmware_property_status { | |
RPI_FIRMWARE_STATUS_REQUEST = 0, | |
RPI_FIRMWARE_STATUS_SUCCESS = 0x80000000, | |
@@ -60,6 +67,7 @@ enum rpi_firmware_property_tag { | |
RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008, | |
RPI_FIRMWARE_GET_TURBO = 0x00030009, | |
RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a, | |
+ RPI_FIRMWARE_GET_STC = 0x0003000b, | |
RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c, | |
RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d, | |
RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e, | |
@@ -69,10 +77,12 @@ enum rpi_firmware_property_tag { | |
RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, | |
RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, | |
RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, | |
+ RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, | |
RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, | |
RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, | |
RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, | |
RPI_FIRMWARE_SET_TURBO = 0x00038009, | |
+ RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, | |
/* Dispmanx TAGS */ | |
RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, | |
@@ -86,6 +96,7 @@ enum rpi_firmware_property_tag { | |
RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, | |
RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, | |
RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, | |
+ RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, | |
RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, | |
RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, | |
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, | |
@@ -95,6 +106,7 @@ enum rpi_firmware_property_tag { | |
RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, | |
RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, | |
RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, | |
+ RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, | |
RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, | |
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, | |
RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005, | |
@@ -103,11 +115,16 @@ enum rpi_firmware_property_tag { | |
RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, | |
RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, | |
RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, | |
+ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, | |
+ | |
+ RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, | |
RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, | |
RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, | |
}; | |
+int rpi_firmware_transaction(struct rpi_firmware *fw, | |
+ enum rpi_fimware_channel chan, u32 data); | |
int rpi_firmware_property(struct rpi_firmware *fw, | |
u32 tag, void *data, size_t len); | |
int rpi_firmware_property_list(struct rpi_firmware *fw, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment