uboot/drivers/demo/demo-shape.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 Google, Inc
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <fdtdec.h>
  11#include <malloc.h>
  12#include <dm-demo.h>
  13#include <asm/io.h>
  14#include <asm/gpio.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18/* Shape size */
  19#define WIDTH   8
  20#define HEIGHT  6
  21
  22struct shape_data {
  23        int num_chars;  /* Number of non-space characters output so far */
  24        struct gpio_desc gpio_desc[8];
  25        int gpio_count;
  26};
  27
  28/* Crazy little function to draw shapes on the console */
  29static int shape_hello(struct udevice *dev, int ch)
  30{
  31        const struct dm_demo_pdata *pdata = dev_get_platdata(dev);
  32        struct shape_data *data = dev_get_priv(dev);
  33        static const struct shape {
  34                int start;
  35                int end;
  36                int dstart;
  37                int dend;
  38        } shapes[3] = {
  39                { 0, 1, 0, 1 },
  40                { 0, WIDTH, 0, 0 },
  41                { HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1},
  42        };
  43        struct shape shape;
  44        unsigned int index;
  45        int line, pos, inside;
  46        const char *colour = pdata->colour;
  47        int first = 0;
  48
  49        if (!ch)
  50                ch = pdata->default_char;
  51        if (!ch)
  52                ch = '@';
  53
  54        index = (pdata->sides / 2) - 1;
  55        if (index >= ARRAY_SIZE(shapes))
  56                return -EIO;
  57        shape = shapes[index];
  58
  59        for (line = 0; line < HEIGHT; line++) {
  60                first = 1;
  61                for (pos = 0; pos < WIDTH; pos++) {
  62                        inside = pos >= shape.start && pos < shape.end;
  63                        if (inside) {
  64                                putc(first ? *colour++ : ch);
  65                                data->num_chars++;
  66                                first = 0;
  67                                if (!*colour)
  68                                        colour = pdata->colour;
  69                        } else {
  70                                putc(' ');
  71                        }
  72                }
  73                putc('\n');
  74                shape.start += shape.dstart;
  75                shape.end += shape.dend;
  76                if (shape.start < 0) {
  77                        shape.dstart = -shape.dstart;
  78                        shape.dend = -shape.dend;
  79                        shape.start += shape.dstart;
  80                        shape.end += shape.dend;
  81                }
  82        }
  83
  84        return 0;
  85}
  86
  87static int shape_status(struct udevice *dev, int *status)
  88{
  89        struct shape_data *data = dev_get_priv(dev);
  90
  91        *status = data->num_chars;
  92        return 0;
  93}
  94
  95static int set_light(struct udevice *dev, int light)
  96{
  97        struct shape_data *priv = dev_get_priv(dev);
  98        struct gpio_desc *desc;
  99        int ret;
 100        int i;
 101
 102        desc = priv->gpio_desc;
 103        for (i = 0; i < priv->gpio_count; i++, desc++) {
 104                uint mask = 1 << i;
 105
 106                ret = dm_gpio_set_value(desc, light & mask);
 107                if (ret < 0)
 108                        return ret;
 109        }
 110
 111        return 0;
 112}
 113
 114static int get_light(struct udevice *dev)
 115{
 116        struct shape_data *priv = dev_get_priv(dev);
 117        struct gpio_desc *desc;
 118        uint value = 0;
 119        int ret;
 120        int i;
 121
 122        desc = priv->gpio_desc;
 123        for (i = 0; i < priv->gpio_count; i++, desc++) {
 124                uint mask = 1 << i;
 125
 126                ret = dm_gpio_get_value(desc);
 127                if (ret < 0)
 128                        return ret;
 129                if (ret)
 130                        value |= mask;
 131        }
 132
 133        return value;
 134}
 135
 136static const struct demo_ops shape_ops = {
 137        .hello = shape_hello,
 138        .status = shape_status,
 139        .get_light = get_light,
 140        .set_light = set_light,
 141};
 142
 143static int shape_ofdata_to_platdata(struct udevice *dev)
 144{
 145        struct dm_demo_pdata *pdata = dev_get_platdata(dev);
 146        int ret;
 147
 148        /* Parse the data that is common with all demo devices */
 149        ret = demo_parse_dt(dev);
 150        if (ret)
 151                return ret;
 152
 153        /* Parse the data that only we need */
 154        pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 155                                             "character", '@');
 156
 157        return 0;
 158}
 159
 160static int dm_shape_probe(struct udevice *dev)
 161{
 162        struct shape_data *priv = dev_get_priv(dev);
 163        int ret;
 164
 165        ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc,
 166                                        ARRAY_SIZE(priv->gpio_desc),
 167                                        GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
 168        if (ret < 0)
 169                return ret;
 170        priv->gpio_count = ret;
 171        debug("%s: %d GPIOs\n", __func__, priv->gpio_count);
 172
 173        return 0;
 174}
 175
 176static int dm_shape_remove(struct udevice *dev)
 177{
 178        struct shape_data *priv = dev_get_priv(dev);
 179
 180        return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count);
 181}
 182
 183static const struct udevice_id demo_shape_id[] = {
 184        { "demo-shape", 0 },
 185        { },
 186};
 187
 188U_BOOT_DRIVER(demo_shape_drv) = {
 189        .name   = "demo_shape_drv",
 190        .of_match = demo_shape_id,
 191        .id     = UCLASS_DEMO,
 192        .ofdata_to_platdata = shape_ofdata_to_platdata,
 193        .ops    = &shape_ops,
 194        .probe = dm_shape_probe,
 195        .remove = dm_shape_remove,
 196        .priv_auto_alloc_size = sizeof(struct shape_data),
 197        .platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
 198};
 199