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 "include.h"
11 #include "disp_device.h"
12
13 static LIST_HEAD(device_list);
14
disp_device_set_manager(struct disp_device * dispdev,struct disp_manager * mgr)15 s32 disp_device_set_manager(struct disp_device *dispdev,
16 struct disp_manager *mgr)
17 {
18 if ((dispdev == NULL) || (mgr == NULL)) {
19 DE_WRN("NULL hdl!\n");
20 return DIS_FAIL;
21 }
22 DE_INF("device %d, mgr %d\n", dispdev->disp, mgr->disp);
23
24 dispdev->manager = mgr;
25 mgr->device = dispdev;
26
27 return DIS_SUCCESS;
28 }
29
disp_device_unset_manager(struct disp_device * dispdev)30 s32 disp_device_unset_manager(struct disp_device *dispdev)
31 {
32 if (dispdev == NULL) {
33 DE_WRN("NULL hdl!\n");
34 return DIS_FAIL;
35 }
36
37 if (dispdev->manager)
38 dispdev->manager->device = NULL;
39 dispdev->manager = NULL;
40
41 return DIS_SUCCESS;
42 }
43
disp_device_get_resolution(struct disp_device * dispdev,u32 * xres,u32 * yres)44 s32 disp_device_get_resolution(struct disp_device *dispdev, u32 *xres,
45 u32 *yres)
46 {
47 if (dispdev == NULL) {
48 DE_WRN("NULL hdl!\n");
49 return DIS_FAIL;
50 }
51
52 *xres = dispdev->timings.x_res;
53 *yres = dispdev->timings.y_res;
54
55 return 0;
56 }
57
disp_device_get_timings(struct disp_device * dispdev,struct disp_video_timings * timings)58 s32 disp_device_get_timings(struct disp_device *dispdev,
59 struct disp_video_timings *timings)
60 {
61 if (dispdev == NULL) {
62 DE_WRN("NULL hdl!\n");
63 return DIS_FAIL;
64 }
65
66 if (timings)
67 memcpy(timings, &dispdev->timings,
68 sizeof(struct disp_video_timings));
69
70 return 0;
71 }
72
disp_device_is_interlace(struct disp_device * dispdev)73 s32 disp_device_is_interlace(struct disp_device *dispdev)
74 {
75 if (dispdev == NULL) {
76 DE_WRN("NULL hdl!\n");
77 return DIS_FAIL;
78 }
79
80 return dispdev->timings.b_interlace;
81 }
82
disp_device_get_status(struct disp_device * dispdev)83 s32 disp_device_get_status(struct disp_device *dispdev)
84 {
85 if (dispdev == NULL) {
86 DE_WRN("NULL hdl!\n");
87 return 0;
88 }
89
90 return disp_al_device_get_status(dispdev->hwdev_index);
91 }
92
disp_device_is_in_safe_period(struct disp_device * dispdev)93 bool disp_device_is_in_safe_period(struct disp_device *dispdev)
94 {
95 int cur_line;
96 int start_delay;
97 bool ret = true;
98
99 if (dispdev == NULL) {
100 DE_WRN("NULL hdl!\n");
101 goto exit;
102 }
103
104 start_delay = disp_al_device_get_start_delay(dispdev->hwdev_index);
105 cur_line = disp_al_device_get_cur_line(dispdev->hwdev_index);
106 if (cur_line >= start_delay)
107 ret = false;
108
109 exit:
110 return ret;
111 }
112
disp_device_show_builtin_patten(struct disp_device * dispdev,u32 patten)113 void disp_device_show_builtin_patten(struct disp_device *dispdev, u32 patten)
114 {
115 if (dispdev)
116 disp_al_show_builtin_patten(dispdev->hwdev_index, patten);
117 }
118
disp_device_usec_before_vblank(struct disp_device * dispdev)119 u32 disp_device_usec_before_vblank(struct disp_device *dispdev)
120 {
121 int cur_line;
122 int start_delay;
123 u32 usec = 0;
124 struct disp_video_timings *timings;
125 u32 usec_per_line;
126 unsigned long long n_temp, base_temp;
127 u32 mod;
128
129 if (dispdev == NULL) {
130 DE_WRN("NULL hdl!\n");
131 goto exit;
132 }
133
134 start_delay = disp_al_device_get_start_delay(dispdev->hwdev_index);
135 cur_line = disp_al_device_get_cur_line(dispdev->hwdev_index);
136 if (cur_line > (start_delay - 4)) {
137 timings = &dispdev->timings;
138 n_temp = (unsigned long long)timings->hor_total_time *
139 (unsigned long long)(1000000);
140 base_temp = (unsigned long long)timings->pixel_clk;
141 /*mod = (u32)do_div(n_temp, base_temp);*/
142 n_temp = (u32)n_temp/base_temp;
143 mod = (u32)n_temp%base_temp;
144 usec_per_line = (u32)n_temp;
145 usec = (timings->ver_total_time - cur_line + 1) * usec_per_line;
146 }
147
148 exit:
149 return usec;
150 }
151
152 /* get free device */
disp_device_get(int disp,enum disp_output_type output_type)153 struct disp_device *disp_device_get(int disp, enum disp_output_type output_type)
154 {
155 struct disp_device *dispdev = NULL;
156
157 list_for_each_entry(dispdev, &device_list, list) {
158 if ((dispdev->type == output_type) && (dispdev->disp == disp)
159 && (dispdev->manager == NULL)) {
160 return dispdev;
161 }
162 }
163
164 return NULL;
165 }
166
167 /**
168 * @name :disp_device_get_from_priv
169 * @brief :get disp_device by comparing pointer of priv_data
170 * @param[IN] :priv_data:pointer of private date of disp_device
171 * @return :pointer of disp_device; NULL if not found
172 */
disp_device_get_from_priv(void * priv_data)173 struct disp_device *disp_device_get_from_priv(void *priv_data)
174 {
175 struct disp_device *dispdev = NULL;
176
177 list_for_each_entry(dispdev, &device_list, list) {
178 if (dispdev->priv_data == priv_data)
179 return dispdev;
180 }
181
182 return NULL;
183 }
184
disp_device_find(int disp,enum disp_output_type output_type)185 struct disp_device *disp_device_find(int disp,
186 enum disp_output_type output_type)
187 {
188 struct disp_device *dispdev = NULL;
189
190 list_for_each_entry(dispdev, &device_list, list) {
191 if ((dispdev->type == output_type) && (dispdev->disp == disp))
192 return dispdev;
193 }
194
195 return NULL;
196 }
197
disp_device_get_list_head(void)198 struct list_head *disp_device_get_list_head(void)
199 {
200 return &device_list;
201 }
202
disp_device_register(struct disp_device * dispdev)203 s32 disp_device_register(struct disp_device *dispdev)
204 {
205 list_add_tail(&dispdev->list, &device_list);
206 return 0;
207 }
208
disp_device_unregister(struct disp_device * dispdev)209 s32 disp_device_unregister(struct disp_device *dispdev)
210 {
211 list_del(&dispdev->list);
212 return 0;
213 }
214