1 /*
2 * Allwinner SoCs display driver.
3 *
4 * Copyright (C) 2016 Allwinner.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10 #include "disp_lcd.h"
11 #include "../of_service.h"
12 #include "lcd_debug.h"
13
14 static struct device_node *node;
15
16 /**
17 * copy_result_to_prop_dts
18 */
copy_result_to_prop_dts(struct property * result,struct dt_property * prop_dts)19 void copy_result_to_prop_dts(struct property *result, struct dt_property *prop_dts)
20 {
21 memcpy(prop_dts->name, result->name, NAME_LENGTH);
22 memcpy(prop_dts->value, result->value, result->length);
23 prop_dts->length = result->length;
24 }
25
retrieve_prop(struct para * lcd_debug_para)26 int retrieve_prop(struct para *lcd_debug_para)
27 {
28 struct dt_property *prop_src = &lcd_debug_para->prop_src;
29 struct property *result;
30
31 if (prop_src->index == 0) {
32 result = get_property_by_name(node, prop_src->name, &prop_src->length);
33
34 if (result == NULL) {
35 return -1;
36 }
37
38 copy_result_to_prop_dts(result, &lcd_debug_para->prop_dts);
39 return 0;
40 } else {
41 char *reference_name;
42
43 switch (lcd_debug_para->flag) {
44 case BASE:
45 reference_name = BASE_PROPERTY_NAME;
46 break;
47 case OPEN:
48 reference_name = OPEN_PROPERTY_NAME;
49 break;
50 case CLOSE:
51 reference_name = CLOSE_PROPERTY_NAME;
52 break;
53 }
54 result = get_property_by_index(node, reference_name, prop_src->index);
55
56 if (result == NULL) {
57 return -1;
58 }
59
60 copy_result_to_prop_dts(result, &lcd_debug_para->prop_dts);
61 lcd_debug_para->prop_dts.index = prop_src->index;
62 return 0;
63 }
64 }
65
66 /* insert a new property after prop_src-name and index */
create_prop(struct para * lcd_debug_para)67 int create_prop(struct para *lcd_debug_para)
68 {
69 char *reference_name;
70 struct property *pp;
71 int ret;
72
73 pp = kcalloc(1, sizeof(struct property), GFP_KERNEL | __GFP_ZERO);
74 pp->name = kmalloc(NAME_LENGTH, GFP_KERNEL | __GFP_ZERO);
75 pp->value = kmalloc(VALUE_LENGTH, GFP_KERNEL | __GFP_ZERO);
76
77 strcpy(pp->name, lcd_debug_para->prop_src.name);
78 memcpy(pp->value, lcd_debug_para->prop_src.value, lcd_debug_para->prop_src.length);
79 pp->length = lcd_debug_para->prop_src.length;
80
81 switch (lcd_debug_para->flag) {
82 case BASE:
83 reference_name = BASE_PROPERTY_NAME;
84 break;
85 case OPEN:
86 reference_name = OPEN_PROPERTY_NAME;
87 break;
88 case CLOSE:
89 reference_name = CLOSE_PROPERTY_NAME;
90 break;
91 default:
92 goto free_mem;
93 }
94 ret = insert_property(node, &pp, reference_name, lcd_debug_para->prop_src.index);
95 if (ret == 0) {
96 return 0;
97 }
98
99 free_mem:
100 kfree(pp->name);
101 kfree(pp->value);
102 kfree(pp);
103 return 2;
104 }
105
106 /* FIXME, can not to call function, when build disp to be a module. */
107 #ifdef MODULE
of_update_property(struct device_node * np,struct property * newprop)108 int of_update_property(struct device_node *np, struct property *newprop)
109 {
110 printk("[INFO] Can not to update a property in device tree, when disp was built to be a module \n");
111 return -1;
112 }
113 #endif
114
115 /* Update a property by name */
update_prop(struct para * lcd_debug_para)116 int update_prop(struct para *lcd_debug_para)
117 {
118 struct property *pp;
119 struct property *newprop;
120 struct dt_property *prop_src;
121 struct dt_property *prop_dts;
122 int length;
123
124 prop_src = &(lcd_debug_para->prop_src);
125 prop_dts = &(lcd_debug_para->prop_dts);
126
127 pp = get_property_by_name(node, prop_src->name, &length);
128
129 if (pp == NULL) {
130 return 1;
131 }
132
133 newprop = kmalloc(sizeof(struct property), GFP_KERNEL | __GFP_ZERO);
134 newprop->name = kmalloc(NAME_LENGTH, GFP_KERNEL | __GFP_ZERO);
135 newprop->value = kmalloc(VALUE_LENGTH, GFP_KERNEL | __GFP_ZERO);
136 memcpy(newprop->name, prop_src->name, strlen(prop_src->name));
137 memcpy(newprop->value, prop_src->value, prop_src->length);
138 newprop->length = prop_src->length;
139
140 return of_update_property(node, newprop);
141 }
142
delete_prop(struct para * lcd_debug_para)143 int delete_prop(struct para *lcd_debug_para)
144 {
145 struct property *pp;
146 struct dt_property *prop_src;
147 int length;
148
149 prop_src = &(lcd_debug_para->prop_src);
150
151 pp = get_property_by_name(node, prop_src->name, &length);
152 if (pp == NULL) {
153 return 1;
154 }
155
156 return delete_property(node, pp);
157
158 }
159
init_device_node(char * node_name)160 int init_device_node(char *node_name)
161 {
162 node = get_node_by_name(node_name);
163 return 0;
164 }
165
166 static bool flag;
handle_request(struct para * lcd_debug_para)167 int handle_request(struct para *lcd_debug_para)
168 {
169 if (flag == 0) {
170 init_device_node("lcd0");
171 flag = 1;
172 }
173 switch (lcd_debug_para->opcode) {
174 case CREATE:
175 {
176 return create_prop(lcd_debug_para);
177 }
178 case RETRIEVIE:
179 {
180 return retrieve_prop(lcd_debug_para);
181 }
182 case UPDATE:
183 {
184 return update_prop(lcd_debug_para);
185 }
186 case DELETE:
187 {
188 return delete_prop(lcd_debug_para);
189 }
190 default:
191 {
192 return -1;
193 }
194 }
195 }
196
197