svn commit: r282357 - head/sys/arm/broadcom/bcm2835
Luiz Otavio O Souza
loos at FreeBSD.org
Sat May 2 22:24:35 UTC 2015
Author: loos
Date: Sat May 2 22:24:33 2015
New Revision: 282357
URL: https://svnweb.freebsd.org/changeset/base/282357
Log:
Add the routines to query and setup the framebuffer state using the
BCM2835_MBOX_CHAN_PROP channel. The old channel (BCM2835_MBOX_CHAN_FB)
seems deprecated on recent firmware versions and is causing a freeze on
RPi 2.
The actual changes in the framebuffer drivers will follow in subsequent
commits.
Modified:
head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
Modified: head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c Sat May 2 20:41:49 2015 (r282356)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_mbox.c Sat May 2 22:24:33 2015 (r282357)
@@ -318,6 +318,47 @@ bcm2835_mbox_init_dma(device_t dev, size
return (buf);
}
+static int
+bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys,
+ struct bcm2835_mbox_hdr *msg, size_t len)
+{
+ int idx;
+ struct bcm2835_mbox_tag_hdr *tag;
+ uint8_t *last;
+
+ if ((uint32_t)msg_phys != resp_phys) {
+ device_printf(dev, "response channel mismatch\n");
+ return (EIO);
+ }
+ if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) {
+ device_printf(dev, "mbox response error\n");
+ return (EIO);
+ }
+
+ /* Loop until the end tag. */
+ tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1);
+ last = (uint8_t *)msg + len;
+ for (idx = 0; tag->tag != 0; idx++) {
+ if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) {
+ device_printf(dev, "tag %d response error\n", idx);
+ return (EIO);
+ }
+ /* Clear the response bit. */
+ tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+
+ /* Next tag. */
+ tag = (struct bcm2835_mbox_tag_hdr *)((uint8_t *)tag +
+ sizeof(*tag) + tag->val_buf_size);
+
+ if ((uint8_t *)tag > last) {
+ device_printf(dev, "mbox buffer size error\n");
+ return (EIO);
+ }
+ }
+
+ return (0);
+}
+
int
bcm2835_mbox_set_power_state(device_t dev, uint32_t device_id, boolean_t on)
{
@@ -413,3 +454,136 @@ bcm2835_mbox_get_clock_rate(device_t dev
return (0);
}
+
+int
+bcm2835_mbox_fb_get_w_h(device_t dev, struct bcm2835_fb_config *fb)
+{
+ device_t mbox;
+ int err;
+ bus_dma_tag_t msg_tag;
+ bus_dmamap_t msg_map;
+ bus_addr_t msg_phys;
+ struct msg_fb_get_w_h *msg;
+ uint32_t reg;
+
+ /* get mbox device */
+ mbox = devclass_get_device(devclass_find("mbox"), 0);
+ if (mbox == NULL) {
+ device_printf(dev, "can't find mbox\n");
+ return (ENXIO);
+ }
+
+ /* Allocate memory for the message */
+ msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map,
+ &msg_phys);
+ if (msg == NULL)
+ return (ENOMEM);
+
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, GET_PHYSICAL_W_H);
+ msg->physical_w_h.tag_hdr.val_len = 0;
+ BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, GET_VIRTUAL_W_H);
+ msg->virtual_w_h.tag_hdr.val_len = 0;
+ BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET);
+ msg->offset.tag_hdr.val_len = 0;
+ msg->end_tag = 0;
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE);
+ MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD);
+ MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, ®);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD);
+
+ err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg));
+ if (err == 0) {
+ fb->xres = msg->physical_w_h.body.resp.width;
+ fb->yres = msg->physical_w_h.body.resp.height;
+ fb->vxres = msg->virtual_w_h.body.resp.width;
+ fb->vyres = msg->virtual_w_h.body.resp.height;
+ fb->xoffset = msg->offset.body.resp.x;
+ fb->yoffset = msg->offset.body.resp.y;
+ }
+
+ bus_dmamap_unload(msg_tag, msg_map);
+ bus_dmamem_free(msg_tag, msg, msg_map);
+ bus_dma_tag_destroy(msg_tag);
+
+ return (err);
+}
+
+int
+bcm2835_mbox_fb_init(device_t dev, struct bcm2835_fb_config *fb)
+{
+ device_t mbox;
+ int err;
+ bus_dma_tag_t msg_tag;
+ bus_dmamap_t msg_map;
+ bus_addr_t msg_phys;
+ struct msg_fb_setup *msg;
+ uint32_t reg;
+
+ /* get mbox device */
+ mbox = devclass_get_device(devclass_find("mbox"), 0);
+ if (mbox == NULL) {
+ device_printf(dev, "can't find mbox\n");
+ return (ENXIO);
+ }
+
+ /* Allocate memory for the message */
+ msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map,
+ &msg_phys);
+ if (msg == NULL)
+ return (ENOMEM);
+
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, SET_PHYSICAL_W_H);
+ msg->physical_w_h.body.req.width = fb->xres;
+ msg->physical_w_h.body.req.height = fb->yres;
+ BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, SET_VIRTUAL_W_H);
+ msg->virtual_w_h.body.req.width = fb->vxres;
+ msg->virtual_w_h.body.req.height = fb->vyres;
+ BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET);
+ msg->offset.body.req.x = fb->xoffset;
+ msg->offset.body.req.y = fb->yoffset;
+ BCM2835_MBOX_INIT_TAG(&msg->depth, SET_DEPTH);
+ msg->depth.body.req.bpp = fb->bpp;
+ BCM2835_MBOX_INIT_TAG(&msg->alpha, SET_ALPHA_MODE);
+ msg->alpha.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
+ BCM2835_MBOX_INIT_TAG(&msg->buffer, ALLOCATE_BUFFER);
+ msg->buffer.body.req.alignment = PAGE_SIZE;
+ BCM2835_MBOX_INIT_TAG(&msg->pitch, GET_PITCH);
+ msg->end_tag = 0;
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE);
+ MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD);
+ MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, ®);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD);
+
+ err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg));
+ if (err == 0) {
+ fb->xres = msg->physical_w_h.body.resp.width;
+ fb->yres = msg->physical_w_h.body.resp.height;
+ fb->vxres = msg->virtual_w_h.body.resp.width;
+ fb->vyres = msg->virtual_w_h.body.resp.height;
+ fb->xoffset = msg->offset.body.resp.x;
+ fb->yoffset = msg->offset.body.resp.y;
+ fb->pitch = msg->pitch.body.resp.pitch;
+ fb->base = msg->buffer.body.resp.fb_address;
+ fb->size = msg->buffer.body.resp.fb_size;
+ }
+
+ bus_dmamap_unload(msg_tag, msg_map);
+ bus_dmamem_free(msg_tag, msg, msg_map);
+ bus_dma_tag_destroy(msg_tag);
+
+ return (err);
+}
Modified: head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
==============================================================================
--- head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h Sat May 2 20:41:49 2015 (r282356)
+++ head/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h Sat May 2 22:24:33 2015 (r282357)
@@ -52,6 +52,12 @@ struct bcm2835_mbox_tag_hdr {
uint32_t val_len;
};
+#define BCM2835_MBOX_INIT_TAG(tag_, tagid_) do { \
+ (tag_)->tag_hdr.tag = BCM2835_MBOX_TAG_##tagid_; \
+ (tag_)->tag_hdr.val_buf_size = sizeof((tag_)->body); \
+ (tag_)->tag_hdr.val_len = sizeof((tag_)->body.req); \
+} while (0)
+
#define BCM2835_MBOX_POWER_ID_EMMC 0x00000000
#define BCM2835_MBOX_POWER_ID_UART0 0x00000001
#define BCM2835_MBOX_POWER_ID_UART1 0x00000002
@@ -322,4 +328,151 @@ struct msg_get_max_temperature {
uint32_t end_tag;
};
+#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003
+#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004
+
+struct bcm2835_mbox_tag_fb_w_h {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t width;
+ uint32_t height;
+ } req;
+ struct {
+ uint32_t width;
+ uint32_t height;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005
+#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005
+
+struct bcm2835_mbox_tag_depth {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t bpp;
+ } req;
+ struct {
+ uint32_t bpp;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007
+#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007
+
+#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0
+#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1
+#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2
+
+struct bcm2835_mbox_tag_alpha_mode {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t alpha;
+ } req;
+ struct {
+ uint32_t alpha;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009
+
+struct bcm2835_mbox_tag_virtual_offset {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t x;
+ uint32_t y;
+ } req;
+ struct {
+ uint32_t x;
+ uint32_t y;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008
+
+struct bcm2835_mbox_tag_pitch {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ uint32_t pitch;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001
+
+struct bcm2835_mbox_tag_allocate_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t alignment;
+ } req;
+ struct {
+ uint32_t fb_address;
+ uint32_t fb_size;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001
+
+struct bcm2835_mbox_tag_release_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ } resp;
+ } body;
+};
+
+struct bcm2835_fb_config {
+ uint32_t xres;
+ uint32_t yres;
+ uint32_t vxres;
+ uint32_t vyres;
+ uint32_t xoffset;
+ uint32_t yoffset;
+ uint32_t bpp;
+ uint32_t pitch;
+ uint32_t base;
+ uint32_t size;
+};
+
+struct msg_fb_get_w_h {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_fb_w_h physical_w_h;
+ struct bcm2835_mbox_tag_fb_w_h virtual_w_h;
+ struct bcm2835_mbox_tag_virtual_offset offset;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_fb_get_w_h(device_t, struct bcm2835_fb_config *);
+
+struct msg_fb_setup {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_fb_w_h physical_w_h;
+ struct bcm2835_mbox_tag_fb_w_h virtual_w_h;
+ struct bcm2835_mbox_tag_virtual_offset offset;
+ struct bcm2835_mbox_tag_depth depth;
+ struct bcm2835_mbox_tag_alpha_mode alpha;
+ struct bcm2835_mbox_tag_allocate_buffer buffer;
+ struct bcm2835_mbox_tag_pitch pitch;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_fb_init(device_t, struct bcm2835_fb_config *);
+
#endif /* _BCM2835_MBOX_PROP_H_ */
More information about the svn-src-head
mailing list