• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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