From owner-svn-src-head@FreeBSD.ORG Sat May 2 22:24:34 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DE5208CF; Sat, 2 May 2015 22:24:34 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BEE191E6B; Sat, 2 May 2015 22:24:34 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t42MOYZm036946; Sat, 2 May 2015 22:24:34 GMT (envelope-from loos@FreeBSD.org) Received: (from loos@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t42MOYM8036944; Sat, 2 May 2015 22:24:34 GMT (envelope-from loos@FreeBSD.org) Message-Id: <201505022224.t42MOYM8036944@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: loos set sender to loos@FreeBSD.org using -f From: Luiz Otavio O Souza Date: Sat, 2 May 2015 22:24:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r282357 - head/sys/arm/broadcom/bcm2835 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 May 2015 22:24:35 -0000 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_ */