configs: starfive: add starfive_visionfive2_defconfig
[platform/kernel/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 <sjg@chromium.org>
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <expo.h>
12 #include <malloc.h>
13 #include <video.h>
14 #include "scene_internal.h"
15
16 int expo_new(const char *name, void *priv, struct expo **expp)
17 {
18         struct expo *exp;
19
20         exp = calloc(1, sizeof(struct expo));
21         if (!exp)
22                 return log_msg_ret("expo", -ENOMEM);
23         exp->name = strdup(name);
24         if (!exp->name) {
25                 free(exp);
26                 return log_msg_ret("name", -ENOMEM);
27         }
28         exp->priv = priv;
29         INIT_LIST_HEAD(&exp->scene_head);
30         INIT_LIST_HEAD(&exp->str_head);
31
32         *expp = exp;
33
34         return 0;
35 }
36
37 static void estr_destroy(struct expo_string *estr)
38 {
39         free(estr);
40 }
41
42 void expo_destroy(struct expo *exp)
43 {
44         struct scene *scn, *next;
45         struct expo_string *estr, *enext;
46
47         list_for_each_entry_safe(scn, next, &exp->scene_head, sibling)
48                 scene_destroy(scn);
49
50         list_for_each_entry_safe(estr, enext, &exp->str_head, sibling)
51                 estr_destroy(estr);
52
53         free(exp->name);
54         free(exp);
55 }
56
57 int expo_str(struct expo *exp, const char *name, uint id, const char *str)
58 {
59         struct expo_string *estr;
60
61         estr = calloc(1, sizeof(struct expo_string));
62         if (!estr)
63                 return log_msg_ret("obj", -ENOMEM);
64
65         estr->id = resolve_id(exp, id);
66         estr->str = str;
67         list_add_tail(&estr->sibling, &exp->str_head);
68
69         return estr->id;
70 }
71
72 const char *expo_get_str(struct expo *exp, uint id)
73 {
74         struct expo_string *estr;
75
76         list_for_each_entry(estr, &exp->str_head, sibling) {
77                 if (estr->id == id)
78                         return estr->str;
79         }
80
81         return NULL;
82 }
83
84 int expo_set_display(struct expo *exp, struct udevice *dev)
85 {
86         exp->display = dev;
87
88         return 0;
89 }
90
91 void exp_set_text_mode(struct expo *exp, bool text_mode)
92 {
93         exp->text_mode = text_mode;
94 }
95
96 struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
97 {
98         struct scene *scn;
99
100         list_for_each_entry(scn, &exp->scene_head, sibling) {
101                 if (scn->id == scene_id)
102                         return scn;
103         }
104
105         return NULL;
106 }
107
108 int expo_set_scene_id(struct expo *exp, uint scene_id)
109 {
110         if (!expo_lookup_scene_id(exp, scene_id))
111                 return log_msg_ret("id", -ENOENT);
112         exp->scene_id = scene_id;
113
114         return 0;
115 }
116
117 int expo_render(struct expo *exp)
118 {
119         struct udevice *dev = exp->display;
120         struct video_priv *vid_priv = dev_get_uclass_priv(dev);
121         struct scene *scn = NULL;
122         u32 colour;
123         int ret;
124
125         colour = video_index_to_colour(vid_priv, VID_WHITE);
126         ret = video_fill(dev, colour);
127         if (ret)
128                 return log_msg_ret("fill", ret);
129
130         if (exp->scene_id) {
131                 scn = expo_lookup_scene_id(exp, exp->scene_id);
132                 if (!scn)
133                         return log_msg_ret("scn", -ENOENT);
134
135                 ret = scene_render(scn);
136                 if (ret)
137                         return log_msg_ret("ren", ret);
138         }
139
140         video_sync(dev, true);
141
142         return scn ? 0 : -ECHILD;
143 }
144
145 int expo_send_key(struct expo *exp, int key)
146 {
147         struct scene *scn = NULL;
148
149         if (exp->scene_id) {
150                 int ret;
151
152                 scn = expo_lookup_scene_id(exp, exp->scene_id);
153                 if (!scn)
154                         return log_msg_ret("scn", -ENOENT);
155
156                 ret = scene_send_key(scn, key, &exp->action);
157                 if (ret)
158                         return log_msg_ret("key", ret);
159         }
160
161         return scn ? 0 : -ECHILD;
162 }
163
164 int expo_action_get(struct expo *exp, struct expo_action *act)
165 {
166         *act = exp->action;
167         exp->action.type = EXPOACT_NONE;
168
169         return act->type == EXPOACT_NONE ? -EAGAIN : 0;
170 }