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