]> Git Repo - J-u-boot.git/blob - boot/expo.c
Merge patch series "clk: mediatek: add OPs to support OF_UPSTREAM"
[J-u-boot.git] / boot / expo.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Implementation of a expo, a collection of scenes providing menu options
4  *
5  * Copyright 2022 Google LLC
6  * Written by Simon Glass <[email protected]>
7  */
8
9 #define LOG_CATEGORY    LOGC_EXPO
10
11 #include <dm.h>
12 #include <expo.h>
13 #include <malloc.h>
14 #include <video.h>
15 #include "scene_internal.h"
16
17 int expo_new(const char *name, void *priv, struct expo **expp)
18 {
19         struct expo *exp;
20
21         exp = calloc(1, sizeof(struct expo));
22         if (!exp)
23                 return log_msg_ret("expo", -ENOMEM);
24         exp->name = strdup(name);
25         if (!exp->name) {
26                 free(exp);
27                 return log_msg_ret("name", -ENOMEM);
28         }
29         exp->priv = priv;
30         INIT_LIST_HEAD(&exp->scene_head);
31         INIT_LIST_HEAD(&exp->str_head);
32
33         *expp = exp;
34
35         return 0;
36 }
37
38 static void estr_destroy(struct expo_string *estr)
39 {
40         free(estr);
41 }
42
43 void expo_destroy(struct expo *exp)
44 {
45         struct scene *scn, *next;
46         struct expo_string *estr, *enext;
47
48         list_for_each_entry_safe(scn, next, &exp->scene_head, sibling)
49                 scene_destroy(scn);
50
51         list_for_each_entry_safe(estr, enext, &exp->str_head, sibling)
52                 estr_destroy(estr);
53
54         free(exp->name);
55         free(exp);
56 }
57
58 uint resolve_id(struct expo *exp, uint id)
59 {
60         log_debug("resolve id %d\n", id);
61         if (!id)
62                 id = exp->next_id++;
63         else if (id >= exp->next_id)
64                 exp->next_id = id + 1;
65
66         return id;
67 }
68
69 void expo_set_dynamic_start(struct expo *exp, uint dyn_start)
70 {
71         exp->next_id = dyn_start;
72 }
73
74 int expo_str(struct expo *exp, const char *name, uint id, const char *str)
75 {
76         struct expo_string *estr;
77
78         estr = calloc(1, sizeof(struct expo_string));
79         if (!estr)
80                 return log_msg_ret("obj", -ENOMEM);
81
82         estr->id = resolve_id(exp, id);
83         estr->str = str;
84         list_add_tail(&estr->sibling, &exp->str_head);
85
86         return estr->id;
87 }
88
89 const char *expo_get_str(struct expo *exp, uint id)
90 {
91         struct expo_string *estr;
92
93         list_for_each_entry(estr, &exp->str_head, sibling) {
94                 if (estr->id == id)
95                         return estr->str;
96         }
97
98         return NULL;
99 }
100
101 int expo_set_display(struct expo *exp, struct udevice *dev)
102 {
103         struct udevice *cons;
104         int ret;
105
106         ret = device_find_first_child_by_uclass(dev, UCLASS_VIDEO_CONSOLE,
107                                                 &cons);
108         if (ret)
109                 return log_msg_ret("con", ret);
110
111         exp->display = dev;
112         exp->cons = cons;
113
114         return 0;
115 }
116
117 int expo_calc_dims(struct expo *exp)
118 {
119         struct scene *scn;
120         int ret;
121
122         if (!exp->cons)
123                 return log_msg_ret("dim", -ENOTSUPP);
124
125         list_for_each_entry(scn, &exp->scene_head, sibling) {
126                 /*
127                  * Do the menus last so that all the menus' text objects
128                  * are dimensioned
129                  */
130                 ret = scene_calc_dims(scn, false);
131                 if (ret)
132                         return log_msg_ret("scn", ret);
133                 ret = scene_calc_dims(scn, true);
134                 if (ret)
135                         return log_msg_ret("scn", ret);
136         }
137
138         return 0;
139 }
140
141 void expo_set_text_mode(struct expo *exp, bool text_mode)
142 {
143         exp->text_mode = text_mode;
144 }
145
146 struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
147 {
148         struct scene *scn;
149
150         list_for_each_entry(scn, &exp->scene_head, sibling) {
151                 if (scn->id == scene_id)
152                         return scn;
153         }
154
155         return NULL;
156 }
157
158 int expo_set_scene_id(struct expo *exp, uint scene_id)
159 {
160         struct scene *scn;
161         int ret;
162
163         scn = expo_lookup_scene_id(exp, scene_id);
164         if (!scn)
165                 return log_msg_ret("id", -ENOENT);
166         ret = scene_arrange(scn);
167         if (ret)
168                 return log_msg_ret("arr", ret);
169
170         exp->scene_id = scene_id;
171
172         return 0;
173 }
174
175 int expo_first_scene_id(struct expo *exp)
176 {
177         struct scene *scn;
178
179         if (list_empty(&exp->scene_head))
180                 return -ENOENT;
181
182         scn = list_first_entry(&exp->scene_head, struct scene, sibling);
183
184         return scn->id;
185 }
186
187 int expo_render(struct expo *exp)
188 {
189         struct udevice *dev = exp->display;
190         struct video_priv *vid_priv = dev_get_uclass_priv(dev);
191         struct scene *scn = NULL;
192         enum colour_idx back;
193         u32 colour;
194         int ret;
195
196         back = CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK) ? VID_BLACK : VID_WHITE;
197         colour = video_index_to_colour(vid_priv, back);
198         ret = video_fill(dev, colour);
199         if (ret)
200                 return log_msg_ret("fill", ret);
201
202         if (exp->scene_id) {
203                 scn = expo_lookup_scene_id(exp, exp->scene_id);
204                 if (!scn)
205                         return log_msg_ret("scn", -ENOENT);
206
207                 ret = scene_render(scn);
208                 if (ret)
209                         return log_msg_ret("ren", ret);
210         }
211
212         video_sync(dev, true);
213
214         return scn ? 0 : -ECHILD;
215 }
216
217 int expo_send_key(struct expo *exp, int key)
218 {
219         struct scene *scn = NULL;
220
221         if (exp->scene_id) {
222                 int ret;
223
224                 scn = expo_lookup_scene_id(exp, exp->scene_id);
225                 if (!scn)
226                         return log_msg_ret("scn", -ENOENT);
227
228                 ret = scene_send_key(scn, key, &exp->action);
229                 if (ret)
230                         return log_msg_ret("key", ret);
231
232                 /* arrange it to get any changes */
233                 ret = scene_arrange(scn);
234                 if (ret)
235                         return log_msg_ret("arr", ret);
236         }
237
238         return scn ? 0 : -ECHILD;
239 }
240
241 int expo_action_get(struct expo *exp, struct expo_action *act)
242 {
243         *act = exp->action;
244         exp->action.type = EXPOACT_NONE;
245
246         return act->type == EXPOACT_NONE ? -EAGAIN : 0;
247 }
248
249 int expo_apply_theme(struct expo *exp, ofnode node)
250 {
251         struct scene *scn;
252         struct expo_theme *theme = &exp->theme;
253         int ret;
254
255         log_debug("Applying theme %s\n", ofnode_get_name(node));
256
257         memset(theme, '\0', sizeof(struct expo_theme));
258         ofnode_read_u32(node, "font-size", &theme->font_size);
259         ofnode_read_u32(node, "menu-inset", &theme->menu_inset);
260         ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
261
262         list_for_each_entry(scn, &exp->scene_head, sibling) {
263                 ret = scene_apply_theme(scn, theme);
264                 if (ret)
265                         return log_msg_ret("app", ret);
266         }
267
268         return 0;
269 }
270
271 int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
272                          void *priv)
273 {
274         struct scene *scn;
275         int ret;
276
277         list_for_each_entry(scn, &exp->scene_head, sibling) {
278                 ret = scene_iter_objs(scn, iter, priv);
279                 if (ret)
280                         return log_msg_ret("wr", ret);
281         }
282
283         return 0;
284 }
This page took 0.04065 seconds and 4 git commands to generate.