uboot/arch/arm/mach-bcm283x/msg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2012 Stephen Warren
   4 */
   5
   6#include <common.h>
   7#include <memalign.h>
   8#include <phys2bus.h>
   9#include <asm/arch/mbox.h>
  10
  11struct msg_set_power_state {
  12        struct bcm2835_mbox_hdr hdr;
  13        struct bcm2835_mbox_tag_set_power_state set_power_state;
  14        u32 end_tag;
  15};
  16
  17struct msg_get_clock_rate {
  18        struct bcm2835_mbox_hdr hdr;
  19        struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
  20        u32 end_tag;
  21};
  22
  23struct msg_query {
  24        struct bcm2835_mbox_hdr hdr;
  25        struct bcm2835_mbox_tag_physical_w_h physical_w_h;
  26        u32 end_tag;
  27};
  28
  29struct msg_setup {
  30        struct bcm2835_mbox_hdr hdr;
  31        struct bcm2835_mbox_tag_physical_w_h physical_w_h;
  32        struct bcm2835_mbox_tag_virtual_w_h virtual_w_h;
  33        struct bcm2835_mbox_tag_depth depth;
  34        struct bcm2835_mbox_tag_pixel_order pixel_order;
  35        struct bcm2835_mbox_tag_alpha_mode alpha_mode;
  36        struct bcm2835_mbox_tag_virtual_offset virtual_offset;
  37        struct bcm2835_mbox_tag_overscan overscan;
  38        struct bcm2835_mbox_tag_allocate_buffer allocate_buffer;
  39        struct bcm2835_mbox_tag_pitch pitch;
  40        u32 end_tag;
  41};
  42
  43int bcm2835_power_on_module(u32 module)
  44{
  45        ALLOC_CACHE_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1);
  46        int ret;
  47
  48        BCM2835_MBOX_INIT_HDR(msg_pwr);
  49        BCM2835_MBOX_INIT_TAG(&msg_pwr->set_power_state,
  50                              SET_POWER_STATE);
  51        msg_pwr->set_power_state.body.req.device_id = module;
  52        msg_pwr->set_power_state.body.req.state =
  53                BCM2835_MBOX_SET_POWER_STATE_REQ_ON |
  54                BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT;
  55
  56        ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN,
  57                                     &msg_pwr->hdr);
  58        if (ret) {
  59                printf("bcm2835: Could not set module %u power state\n",
  60                       module);
  61                return -EIO;
  62        }
  63
  64        return 0;
  65}
  66
  67int bcm2835_get_mmc_clock(u32 clock_id)
  68{
  69        ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1);
  70        int ret;
  71
  72        ret = bcm2835_power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
  73        if (ret)
  74                return ret;
  75
  76        BCM2835_MBOX_INIT_HDR(msg_clk);
  77        BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);
  78        msg_clk->get_clock_rate.body.req.clock_id = clock_id;
  79
  80        ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr);
  81        if (ret) {
  82                printf("bcm2835: Could not query eMMC clock rate\n");
  83                return -EIO;
  84        }
  85
  86        return msg_clk->get_clock_rate.body.resp.rate_hz;
  87}
  88
  89int bcm2835_get_video_size(int *widthp, int *heightp)
  90{
  91        ALLOC_CACHE_ALIGN_BUFFER(struct msg_query, msg_query, 1);
  92        int ret;
  93
  94        BCM2835_MBOX_INIT_HDR(msg_query);
  95        BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h,
  96                                     GET_PHYSICAL_W_H);
  97        ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr);
  98        if (ret) {
  99                printf("bcm2835: Could not query display resolution\n");
 100                return ret;
 101        }
 102        *widthp = msg_query->physical_w_h.body.resp.width;
 103        *heightp = msg_query->physical_w_h.body.resp.height;
 104
 105        return 0;
 106}
 107
 108int bcm2835_set_video_params(int *widthp, int *heightp, int depth_bpp,
 109                             int pixel_order, int alpha_mode, ulong *fb_basep,
 110                             ulong *fb_sizep, int *pitchp)
 111{
 112        ALLOC_CACHE_ALIGN_BUFFER(struct msg_setup, msg_setup, 1);
 113        int ret;
 114
 115        BCM2835_MBOX_INIT_HDR(msg_setup);
 116        BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H);
 117        msg_setup->physical_w_h.body.req.width = *widthp;
 118        msg_setup->physical_w_h.body.req.height = *heightp;
 119        BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H);
 120        msg_setup->virtual_w_h.body.req.width = *widthp;
 121        msg_setup->virtual_w_h.body.req.height = *heightp;
 122        BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH);
 123        msg_setup->depth.body.req.bpp = 32;
 124        BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER);
 125        msg_setup->pixel_order.body.req.order = pixel_order;
 126        BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE);
 127        msg_setup->alpha_mode.body.req.alpha = alpha_mode;
 128        BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET);
 129        msg_setup->virtual_offset.body.req.x = 0;
 130        msg_setup->virtual_offset.body.req.y = 0;
 131        BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN);
 132        msg_setup->overscan.body.req.top = 0;
 133        msg_setup->overscan.body.req.bottom = 0;
 134        msg_setup->overscan.body.req.left = 0;
 135        msg_setup->overscan.body.req.right = 0;
 136        BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER);
 137        msg_setup->allocate_buffer.body.req.alignment = 0x100;
 138        BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_setup->pitch, GET_PITCH);
 139
 140        ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr);
 141        if (ret) {
 142                printf("bcm2835: Could not configure display\n");
 143                return ret;
 144        }
 145        *widthp = msg_setup->physical_w_h.body.resp.width;
 146        *heightp = msg_setup->physical_w_h.body.resp.height;
 147        *pitchp = msg_setup->pitch.body.resp.pitch;
 148        *fb_basep = bus_to_phys(
 149                        msg_setup->allocate_buffer.body.resp.fb_address);
 150        *fb_sizep = msg_setup->allocate_buffer.body.resp.fb_size;
 151
 152        return 0;
 153}
 154