1 /*
2 * Allwinner SoCs display driver.
3 *
4 * Copyright (C) 2019 Allwinner.
5 *
6 * Author:zhengwanyu <zhengwanyu@allwinnertech.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13 #include "sunxi_dsi.h"
14
15 /**
16 * dsi module mode switch
17 * @id :dsi id
18 * @param[IN] :cmd_en: command mode enable
19 * @param[IN] :lp_en: lower power mode enable
20 * @return :0 if success
21 */
sunxi_dsi_mode_switch(struct sunxi_dsi * dsi,u32 cmd_en,u32 lp_en)22 s32 sunxi_dsi_mode_switch(struct sunxi_dsi *dsi, u32 cmd_en, u32 lp_en)
23 {
24 s32 ret = -1;
25
26 if (dsi->tcon_mode == DISP_TCON_SLAVE_MODE)
27 goto OUT;
28
29 ret = dsi_mode_switch(dsi->id, cmd_en, lp_en);
30 if (dsi->tcon_mode == DISP_TCON_DUAL_DSI
31 && (dsi->id + 1) < DEVICE_DSI_NUM)
32 ret = dsi_mode_switch(dsi->id + 1, cmd_en, lp_en);
33 else if (dsi->tcon_mode != DISP_TCON_NORMAL_MODE
34 && dsi->tcon_mode != DISP_TCON_DUAL_DSI)
35 ret = dsi_mode_switch(dsi->slave_tcon_num, cmd_en, lp_en);
36
37 OUT:
38 return ret;
39 }
40
41
sunxi_dsi_clk_en(struct sunxi_dsi * dsi,u32 en)42 static s32 sunxi_dsi_clk_en(struct sunxi_dsi *dsi, u32 en)
43 {
44 s32 ret = -1;
45
46
47 if (dsi->tcon_mode == DISP_TCON_SLAVE_MODE)
48 goto OUT;
49
50 ret = dsi_clk_enable(dsi->id, en);
51 if (dsi->tcon_mode == DISP_TCON_DUAL_DSI &&
52 dsi->id + 1 < DEVICE_DSI_NUM)
53 ret = dsi_clk_enable(dsi->id + 1, en);
54 else if (dsi->tcon_mode != DISP_TCON_NORMAL_MODE &&
55 dsi->tcon_mode != DISP_TCON_DUAL_DSI)
56 ret = dsi_clk_enable(dsi->slave_tcon_num, en);
57 OUT:
58 return ret;
59 }
60
sunxi_dsi_clk_enable(struct sunxi_dsi * dsi)61 s32 sunxi_dsi_clk_enable(struct sunxi_dsi *dsi)
62 {
63 return sunxi_dsi_clk_en(dsi, 1);
64 }
65
sunxi_dsi_clk_disable(struct sunxi_dsi * dsi)66 s32 sunxi_dsi_clk_disable(struct sunxi_dsi *dsi)
67 {
68 return sunxi_dsi_clk_en(dsi, 0);
69 }
70
sunxi_dsi_dcs_wr(struct sunxi_dsi * dsi,u8 command,u8 * para,u32 para_num)71 static s32 sunxi_dsi_dcs_wr(struct sunxi_dsi *dsi, u8 command, u8 *para,
72 u32 para_num)
73 {
74 s32 ret = -1;
75
76
77 if (dsi->tcon_mode == DISP_TCON_SLAVE_MODE)
78 goto OUT;
79
80 ret = dsi_dcs_wr(dsi->id, command, para, para_num);
81 if (dsi->tcon_mode == DISP_TCON_DUAL_DSI
82 && (dsi->id + 1) < DEVICE_DSI_NUM
83 && dsi->port_num == DISP_LCD_DSI_SINGLE_PORT)
84 ret = dsi_dcs_wr(dsi->id + 1, command, para, para_num);
85 else if (dsi->tcon_mode != DISP_TCON_NORMAL_MODE &&
86 dsi->tcon_mode != DISP_TCON_DUAL_DSI)
87 ret = dsi_dcs_wr(dsi->slave_tcon_num, command, para,
88 para_num);
89 OUT:
90 return ret;
91 }
92
93 /**
94 * sunxi_dsi_dcs_wr - write command and para to mipi panel.
95 * @dsi: The index of screen.
96 * @command: Command to be transfer.
97 */
sunxi_dsi_dcs_write_0para(struct sunxi_dsi * dsi,u8 command)98 s32 sunxi_dsi_dcs_write_0para(struct sunxi_dsi *dsi, u8 command)
99 {
100 u8 tmp[5];
101
102 sunxi_dsi_dcs_wr(dsi, command, tmp, 0);
103
104 return -1;
105 }
106
107 /**
108 * sunxi_dsi_dcs_write_1para - write command and para to mipi panel.
109 * @dsi: The index of screen.
110 * @command: Command to be transfer.
111 * @paran: Para to be transfer.
112 */
sunxi_dsi_dcs_write_1para(struct sunxi_dsi * dsi,u8 command,u8 para1)113 s32 sunxi_dsi_dcs_write_1para(struct sunxi_dsi *dsi, u8 command, u8 para1)
114 {
115 u8 tmp[5];
116
117 tmp[0] = para1;
118 sunxi_dsi_dcs_wr(dsi, command, tmp, 1);
119
120 return -1;
121 }
122
sunxi_dsi_dcs_write_2para(struct sunxi_dsi * dsi,u8 command,u8 para1,u8 para2)123 s32 sunxi_dsi_dcs_write_2para(struct sunxi_dsi *dsi, u8 command, u8 para1,
124 u8 para2)
125 {
126 u8 tmp[5];
127
128 tmp[0] = para1;
129 tmp[1] = para2;
130 sunxi_dsi_dcs_wr(dsi, command, tmp, 2);
131
132 return -1;
133 }
134
sunxi_dsi_dcs_write_3para(struct sunxi_dsi * dsi,u8 command,u8 para1,u8 para2,u8 para3)135 s32 sunxi_dsi_dcs_write_3para(struct sunxi_dsi *dsi, u8 command, u8 para1,
136 u8 para2, u8 para3)
137 {
138 u8 tmp[5];
139
140 tmp[0] = para1;
141 tmp[1] = para2;
142 tmp[2] = para3;
143 sunxi_dsi_dcs_wr(dsi, command, tmp, 3);
144
145 return -1;
146 }
147
sunxi_dsi_dcs_write_4para(struct sunxi_dsi * dsi,u8 command,u8 para1,u8 para2,u8 para3,u8 para4)148 s32 sunxi_dsi_dcs_write_4para(struct sunxi_dsi *dsi, u8 command, u8 para1,
149 u8 para2, u8 para3, u8 para4)
150 {
151 u8 tmp[5];
152
153 tmp[0] = para1;
154 tmp[1] = para2;
155 tmp[2] = para3;
156 tmp[3] = para4;
157 sunxi_dsi_dcs_wr(dsi, command, tmp, 4);
158
159 return -1;
160 }
161
sunxi_dsi_dcs_write_5para(struct sunxi_dsi * dsi,u8 command,u8 para1,u8 para2,u8 para3,u8 para4,u8 para5)162 s32 sunxi_dsi_dcs_write_5para(struct sunxi_dsi *dsi, u8 command, u8 para1,
163 u8 para2, u8 para3, u8 para4, u8 para5)
164 {
165 u8 tmp[5];
166
167 tmp[0] = para1;
168 tmp[1] = para2;
169 tmp[2] = para3;
170 tmp[3] = para4;
171 tmp[4] = para5;
172 sunxi_dsi_dcs_wr(dsi, command, tmp, 5);
173
174 return -1;
175 }
176
sunxi_dsi_dcs_write_6para(struct sunxi_dsi * dsi,u8 command,u8 para1,u8 para2,u8 para3,u8 para4,u8 para5,u8 para6)177 s32 sunxi_dsi_dcs_write_6para(struct sunxi_dsi *dsi, u8 command, u8 para1,
178 u8 para2, u8 para3, u8 para4, u8 para5, u8 para6)
179 {
180 u8 tmp[6];
181
182 tmp[0] = para1;
183 tmp[1] = para2;
184 tmp[2] = para3;
185 tmp[3] = para4;
186 tmp[4] = para5;
187 tmp[5] = para6;
188 sunxi_dsi_dcs_wr(dsi, command, tmp, 6);
189
190 return -1;
191 }
192
193
sunxi_dsi_gen_wr(struct sunxi_dsi * dsi,u8 command,u8 * para,u32 para_num)194 s32 sunxi_dsi_gen_wr(struct sunxi_dsi *dsi,
195 u8 command, u8 *para, u32 para_num)
196 {
197 s32 ret = -1;
198
199 if (dsi->tcon_mode == DISP_TCON_SLAVE_MODE)
200 goto OUT;
201
202 ret = dsi_gen_wr(dsi->id, command, para, para_num);
203 if (dsi->tcon_mode == DISP_TCON_DUAL_DSI &&
204 (dsi->id + 1) < DEVICE_DSI_NUM &&
205 dsi->port_num == DISP_LCD_DSI_SINGLE_PORT)
206 ret = dsi_gen_wr(dsi->id + 1, command, para, para_num);
207 else if (dsi->tcon_mode != DISP_TCON_NORMAL_MODE &&
208 dsi->tcon_mode != DISP_TCON_DUAL_DSI)
209 ret = dsi_gen_wr(dsi->slave_tcon_num, command, para,
210 para_num);
211 OUT:
212 return ret;
213 }
214
sunxi_dsi_gen_short_read(u32 id,u8 * para_p,u8 para_num,u8 * result)215 s32 sunxi_dsi_gen_short_read(u32 id, u8 *para_p, u8 para_num,
216 u8 *result)
217 {
218 s32 ret = -1;
219
220 if (!result || !para_p || para_num > 2) {
221 pr_err("[sunxi-dsi]error: wrong para\n");
222 goto OUT;
223 }
224
225 ret = dsi_gen_short_rd(id, para_p, para_num, result);
226 OUT:
227 return ret;
228 }
229
sunxi_dsi_dcs_read(u32 id,u8 cmd,u8 * result,u32 * num_p)230 s32 sunxi_dsi_dcs_read(u32 id, u8 cmd, u8 *result, u32 *num_p)
231 {
232 s32 ret = -1;
233
234 if (!result || !num_p) {
235 pr_err("[sunxi-dsi]error: wrong para\n");
236 goto OUT;
237 }
238 ret = dsi_dcs_rd(id, cmd, result, num_p);
239 OUT:
240 return ret;
241 }
242
sunxi_set_max_ret_size(u32 id,u32 size)243 s32 sunxi_set_max_ret_size(u32 id, u32 size)
244 {
245 return dsi_set_max_ret_size(id, size);
246 }
247
sunxi_dsi_turn_on_peripheral_command(struct sunxi_dsi * dsi)248 s32 sunxi_dsi_turn_on_peripheral_command(struct sunxi_dsi *dsi)
249 {
250 #ifdef CONFIG_ARCH_SUN20IW1
251 return 0;
252 #else
253 return dsi_turn_on_peripheral_command(dsi->id);
254 #endif
255 }
256