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