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