• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (c) 2021 Allwinnertech Co., Ltd.
4  * Author: libairong <libairong@allwinnertech.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9 */
10 #include <linux/of.h>
11 #include <linux/of_device.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 
15 #include "super_lcd_driver.h"
16 #include "../of_service.h"
17 
18 #define DP printk("[DEBUG] %s, %s, %d \n", __FILE__, __func__, __LINE__);
19 
20 #define GAMMA_TBL_ROW       30
21 #define GAMMA_TBL_COLUMN    2
22 
get_gamma_tbl_from_dts(char * node_name,char * subname,u8 * ptbl,int * row_size)23 static int get_gamma_tbl_from_dts(char *node_name, char *subname, u8 *ptbl, int *row_size)
24 {
25 	int ret;
26 	struct device_node *lcd0_node;
27 	// Get property, that is flag property from lcd0
28 	char command_name[32];
29 	int command_len;
30 	int i;
31 	u32 data[2];
32 
33 	lcd0_node = get_node_by_name(node_name);
34 
35 	for (i = 0; ; i++) {
36 		// Get property
37 		command_len = sprintf(command_name, "%s_%d", subname, i);
38 
39 		if (command_len > 32) {
40 			printk("[WARN] command_name is too long \n");
41 		}
42 
43 		ret = of_property_read_variable_u32_array(lcd0_node, command_name, data, 0, ARRAY_SIZE(data));
44 
45 		if (ret < 0) {
46 			// printk("[ERR]property %s is not found \n", command_name);
47 			break;
48 		}
49 
50 		*(ptbl + i * GAMMA_TBL_COLUMN + 0) = (u8) data[0];
51 		*(ptbl + i * GAMMA_TBL_COLUMN + 1) = (u8) data[1];
52 
53 	}
54 
55 	*row_size = i;
56 	return 0;
57 }
58 
lcd_cfg_panel_info(struct panel_extend_para * info)59 static void lcd_cfg_panel_info(struct panel_extend_para *info)
60 {
61 	u32 i = 0, j = 0;
62 	u32 items;
63 	u8 lcd_gamma_tbl[GAMMA_TBL_ROW][GAMMA_TBL_COLUMN];
64 	int gamma_tbl_row_size = 0;
65 	int ret;
66 
67 	u32 lcd_cmap_tbl[2][3][4] = {
68 	{
69 		{LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
70 		{LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
71 		{LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
72 		},
73 		{
74 		{LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
75 		{LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
76 		{LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
77 		},
78 	};
79 
80 	ret = get_gamma_tbl_from_dts("lcd0", "lcd_gamma", (u8 *)lcd_gamma_tbl, &gamma_tbl_row_size);
81 
82 	items = gamma_tbl_row_size;
83 
84 	if (items < 1) {
85 		printk("the size of lcd_gamma table is less then 1 \n");
86 		return;
87 	}
88 
89 	for (i = 0; i < items - 1; i++) {
90 		u32 num = lcd_gamma_tbl[i+1][0] - lcd_gamma_tbl[i][0];
91 
92 		for (j = 0; j < num; j++) {
93 			u32 value = 0;
94 
95 			value = lcd_gamma_tbl[i][1] +
96 				((lcd_gamma_tbl[i+1][1] - lcd_gamma_tbl[i][1])
97 				* j) / num;
98 			info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
99 							(value<<16)
100 							+ (value<<8) + value;
101 		}
102 	}
103 	info->lcd_gamma_tbl[255] = (lcd_gamma_tbl[items-1][1]<<16) +
104 					(lcd_gamma_tbl[items-1][1]<<8)
105 					+ lcd_gamma_tbl[items-1][1];
106 
107 	memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
108 
109 }
110 
get_func_pointer(u32 opcode)111 unsigned long get_func_pointer(u32 opcode)
112 {
113 	int func_table_line;
114 	int i;
115 
116 	func_table_line = sizeof(lcd_func_table) / 2 / 8;
117 
118 	for (i = 0; i < func_table_line; i++) {
119 		if (lcd_func_table[i][0] == opcode) {
120 			return lcd_func_table[i][1];
121 		}
122 	}
123 
124 	return 0;
125 
126 }
127 
handle_data(u32 sel,u32 * data)128 void handle_data(u32 sel, u32 *data)
129 {
130 	u32 opcode = *data;
131 	unsigned long p_func_addr;
132 	u32 cmd_count;
133 	u8 cmd_params[15] = {0};
134 	int i;
135 
136 	p_func_addr = get_func_pointer(opcode);
137 
138 	if (p_func_addr == 0) {
139 		printk("[ERR] not found function in func_table by opcode \n");
140 		return;
141 	}
142 
143 	// Get function and exec by opcode
144 	if (opcode < 10) {
145 		void (*p_func)(u32) = (void *)p_func_addr;
146 		(*p_func)(sel);
147 	} else if (opcode < 20) {
148 		s32 (*p_func)(u32) = (void *)p_func_addr;
149 		(*p_func)(sel);
150 	} else if (opcode < 30) {
151 		// void (*p_func)(u32, u32, u32) = (void *)p_func_addr;
152 		// (*p_func)(sel, );
153 	} else if (opcode < 40) {
154 		s32 (*p_func)(u32) = (void *)p_func_addr;
155 		(*p_func)((*(data + 1)));
156 	} else if (opcode < 50) {
157 		void (*p_func)(u32, u32) = (void *)p_func_addr;
158 		(*p_func)(sel, (*(data + 1)));
159 	} else if (opcode < 70) {
160 		s32 (*p_func)(u32, u32, u32) = (void *)p_func_addr;
161 		(*p_func)(sel, (*(data + 1)), (*(data + 2)));
162 	} else if (opcode < 80) {
163 		// s32 (*p_func)(u32, u8 *, u32) = (void *)p_func_addr;
164 		// (*p_func)(sel, );
165 	} else if (opcode < 90) {
166 		// s32 (*p_func)(u32 sel, u8, u8 *, u32 *) = (void *)p_func;
167 	} else if (opcode < 100) {
168 		s32 (*p_func)(u32, u8, u8 *, u32) = (void *)p_func_addr;
169 		// data : [opcode cmd param_count params]
170 
171 		cmd_count = (*(data + 2));
172 
173 		if (cmd_count > 15) {
174 			printk("[EER] paras are more then 15 \n");
175 			return;
176 		}
177 
178 		for (i = 0; i < cmd_count; i++) {
179 			cmd_params[i] = *(data + 3 + i);
180 		}
181 
182 		(*p_func)(sel, (u8)(*(data + 1)), cmd_params, cmd_count);
183 	} else {
184 		printk("[WRN] opcode can not be exec \n");
185 	}
186 
187 }
188 
exec_command(u32 sel,char * node_name,char * subname)189 void exec_command(u32 sel, char *node_name, char *subname)
190 {
191 	int ret;
192 	struct device_node *lcd0_node;
193 	// Get property, that is flag property from lcd0
194 	char command_name[32];
195 	int command_len;
196 	int i;
197 	u32 data[20];  // Should define a macro
198 
199 	lcd0_node = get_node_by_name(node_name);
200 
201 	for (i = 0; ; i++) {
202 		// Get property
203 		command_len = sprintf(command_name, "%s_%d", subname, i);
204 
205 		if (command_len > 32) {
206 			printk("[WARN] command_name is too long \n");
207 		}
208 
209 		ret = of_property_read_variable_u32_array(lcd0_node, command_name, data, 0, ARRAY_SIZE(data));
210 		// printk("ret = %d, command_namd : %s \n", ret, command_name);
211 
212 		if (ret < 0) {
213 			// printk("[INFO]property %s is not found \n", node_name);
214 			break;
215 		}
216 
217 		handle_data(sel, data);
218 	}
219 
220 }
221 
lcd_open_flow(u32 sel)222 static s32 lcd_open_flow(u32 sel)
223 {
224 	exec_command(sel, "lcd0", "lcd_open_command");
225 
226 	return 0;
227 }
228 
lcd_close_flow(u32 sel)229 static s32 lcd_close_flow(u32 sel)
230 {
231 	exec_command(sel, "lcd0", "lcd_close_command");
232 
233 	return 0;
234 }
235 
lcd_user_defined_func(u32 sel,u32 para1,u32 para2,u32 para3)236 static s32 lcd_user_defined_func(u32 sel, u32 para1, u32 para2, u32 para3)
237 {
238 	return 0;
239 }
240 
241 struct __lcd_panel  super_lcd_panel = {
242 	.name = "super_lcd_driver",
243 	.func = {
244 		.cfg_panel_info = lcd_cfg_panel_info,
245 		.cfg_open_flow = lcd_open_flow,
246 		.cfg_close_flow = lcd_close_flow,
247 		.lcd_user_defined_func = lcd_user_defined_func,
248 	},
249 };
250