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