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