• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 Allwinnertech Co.Ltd
3  * Authors: zhengwanyu
4  *
5  * This program is free software; you can redistribute  it and/or modify it
6  * under  the terms of  the GNU General  Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  *
10  */
11 #include <drm/drm_fb_helper.h>
12 #include <drm/drm_plane_helper.h>
13 #include <drm/drm_crtc_helper.h>
14 #include <drm/drm_atomic_helper.h>
15 #include <drm/drm_sysfs.h>
16 #include <drm/drm_print.h>
17 #include <video/sunxi_display2.h>
18 
19 #include "drm_internal.h"
20 #include "sunxi_drm_drv.h"
21 #include "sunxi_drm_encoder.h"
22 #include "sunxi_drm_connector.h"
23 
24 #include "de/include.h"
25 
26 #ifdef CONFIG_AW_DRM_TV
27 #include "sunxi_device/sunxi_tv.h"
28 #endif
29 
30 static unsigned int sunxi_conector_cnt;
31 static struct sunxi_drm_connector *sunxi_con[MAX_CONNECTOR_COUNT];
32 
sunxi_drm_connector_get_count(void)33 unsigned int sunxi_drm_connector_get_count(void)
34 {
35 	return sunxi_conector_cnt;
36 }
37 
sunxi_drm_connector_get_connector(int id)38 struct sunxi_drm_connector *sunxi_drm_connector_get_connector(int id)
39 {
40 	if (id >= sunxi_conector_cnt) {
41 		DRM_ERROR("wrong connector id, out of range\n");
42 		return NULL;
43 	}
44 
45 	return sunxi_con[id];
46 }
47 
48 void
sunxi_drm_connector_set_connector(int id,struct sunxi_drm_connector * conn)49 sunxi_drm_connector_set_connector(int id, struct sunxi_drm_connector *conn)
50 {
51 	if (id >= sunxi_conector_cnt) {
52 		DRM_ERROR("wrong connector id, out of range\n");
53 		return;
54 	}
55 
56 	sunxi_con[id] = conn;
57 }
58 
sunxi_drm_connector_state(char * buf,struct drm_connector_state * state)59 static ssize_t sunxi_drm_connector_state(char *buf, struct drm_connector_state *state)
60 {
61 	ssize_t n = 0;
62 
63 	n += sprintf(n + buf, "[connector_state]:\n");
64 
65 	if (state->crtc)
66 		n += sprintf(n + buf, "attaching crtc index:%d\n", state->crtc->index);
67 
68 	if (state->best_encoder)
69 		n += sprintf(n + buf, "attaching best encoder index:%d\n", state->best_encoder->index);
70 
71 	return n;
72 }
73 
74 /*ssize_t sunxi_drm_connector_show(char *buf, struct drm_device *dev)
75 {
76 	int ret;
77 	ssize_t n = 0;
78 	struct drm_connector *connector;
79 	struct sunxi_drm_connector *sconn;
80 
81 	mutex_lock(&dev->mode_config.mutex);
82 	ret = drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
83 	if (ret)
84 		return n;
85 
86 	drm_for_each_connector(connector, dev) {
87 		sconn = to_sunxi_connector(connector);
88 		n += sprintf(n + buf, "connector id:%d\n", connector->index);
89 		if (sconn->type == DISP_OUTPUT_TYPE_LCD)
90 			n += sprintf(n + buf, "LCD%d\n", sconn->type_id);
91 		else if (sconn->type == DISP_OUTPUT_TYPE_HDMI)
92 			n += sprintf(n + buf, "HDMI%d\n", sconn->type_id);
93 		else if (sconn->type == DISP_OUTPUT_TYPE_TV)
94 			n += sprintf(n + buf, "TV%d\n", sconn->type_id);
95 		else
96 			n += sprintf(n + buf, "Unknow connector type!\n");
97 
98 		n += sprintf(n + buf, "name:%s\n", connector->name);
99 		n += sprintf(n + buf, "allow interlace:%d double_scan:%d stereo:%d\n",
100 				connector->interlace_allowed, connector->doublescan_allowed,
101 				connector->stereo_allowed);
102 		n += sprintf(n + buf, "register:%d\n", connector->registered);
103 		n += sprintf(n + buf, "status:%d  polled:%d\n",
104 				connector->status, connector->polled);
105 		n += sprintf(n + buf, "dpms:%s\n", connector->dpms ? "off" : "on");
106 		n += sprintf(n + buf, "possible encoder id:%d %d %d\n",
107 			connector->encoder_ids[0], connector->encoder_ids[1],
108 			connector->encoder_ids[2]);
109 		if (connector->encoder)
110 			n += sprintf(n + buf, "attached encoder:%d\n", connector->encoder->index);
111 		else
112 			n += sprintf(n + buf, "No attached encoder\n");
113 
114 		n += sunxi_drm_connector_state(buf + n, connector->state);
115 		n += sprintf(n + buf, "\n");
116 	}
117 
118 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
119 	mutex_unlock(&dev->mode_config.mutex);
120 
121 	return n;
122 }*/
123 
124 struct drm_encoder *
sunxi_connector_best_encoder(struct drm_connector * connector)125 sunxi_connector_best_encoder(struct drm_connector *connector)
126 {
127 #if 0
128 	struct drm_device *dev = connector->dev;
129 	struct drm_mode_object *obj;
130 	struct drm_encoder *encoder = NULL, *best_encoder = NULL;
131 	struct sunxi_drm_encoder *sencoder;
132 	int i;
133 
134 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
135 		if (connector->encoder_ids[i] != 0) {
136 			/*check if it has drm_mode_object*/
137 			obj = drm_mode_object_find(dev,
138 				NULL,
139 				connector->encoder_ids[i],
140 				DRM_MODE_OBJECT_ENCODER);
141 			if (!obj) {
142 				DRM_ERROR("Unknown ENCODER ID %d\n",
143 				connector->encoder_ids[i]);
144 				continue;
145 			}
146 
147 			encoder = obj_to_encoder(obj);
148 			sencoder = to_sunxi_encoder(encoder);
149 
150 			if (best_encoder == NULL)
151 				best_encoder = encoder;
152 
153 			if (connector->encoder == encoder) {
154 				best_encoder = encoder;
155 				break;
156 			} else {
157 				if (!sencoder->is_in_use(sencoder)) {
158 					best_encoder = encoder;
159 					break;
160 				}
161 			}
162 		}
163 	}
164 
165 	DRM_DEBUG_KMS("GET best encoder id:%d for connector:%d\n",
166 		best_encoder->base.id, connector->base.id);
167 	return best_encoder;
168 #endif
169 	struct drm_encoder *encoder;
170 	drm_connector_for_each_possible_encoder(connector, encoder)
171 		return encoder;
172 
173 	return NULL;
174 }
175 
sunxi_drm_connector_init(struct drm_device * dev)176 int sunxi_drm_connector_init(struct drm_device *dev)
177 {
178 	int i, max_con = 0;
179 	struct sunxi_drm_connector *scon = NULL;
180 	int sunxi_con_type;
181 #ifdef CONFIG_AW_DRM_LCD
182 	int lcd_type_id = 0;
183 #endif
184 
185 #ifdef CONFIG_AW_DRM_TV
186 	int tv_type_id = 0;
187 #endif
188 
189 /* create drm_connectors according boot info,
190   * NOTE: Only surpport single connector display and dual connectors display!!!
191   */
192 	max_con = sunxi_drm_get_connector_count();
193 	sunxi_conector_cnt = max_con;
194 
195 	for (i = 0; i < max_con; i++) {
196 		sunxi_con_type = sunxi_drm_get_connector_type(i);
197 		switch (sunxi_con_type) {
198 		/*LCD*/
199 		case 1:
200 #ifdef CONFIG_AW_DRM_LCD
201 			scon = sunxi_drm_connector_lcd_create(dev,
202 					i, lcd_type_id);
203 			if (!scon) {
204 				DRM_ERROR("create lcd:%d connector failed!\n",
205 					lcd_type_id);
206 				goto con_err;
207 			}
208 
209 			++lcd_type_id;
210 #endif
211 			break;
212 
213 		/*TV*/
214 		case 2:
215 #ifdef CONFIG_AW_DRM_TV
216 			scon = sunxi_drm_connector_tv_create(dev,
217 					i, tv_type_id);
218 			if (!scon) {
219 				DRM_ERROR("create tv:%d connector failed!\n",
220 					tv_type_id);
221 				goto con_err;
222 			}
223 
224 			++tv_type_id;
225 #endif
226 			break;
227 
228 		/*HDMI*/
229 		case 3:
230 #if defined(CONFIG_AW_DRM_HDMI14) || defined(CONFIG_AW_DRM_HDMI20)
231 			scon = sunxi_drm_connector_hdmi_create(dev,
232 					i);
233 			if (!scon) {
234 				DRM_ERROR("create hdmi connector failed!\n");
235 				goto con_err;
236 			}
237 #endif
238 			break;
239 
240 		default:
241 			DRM_ERROR("Unknown connector output type:%d\n", sunxi_con_type);
242 			goto con_err;
243 		}
244 
245 		sunxi_con[i] = scon;
246 	}
247 
248 	return 0;
249 
250 con_err:
251 	DRM_ERROR("sunxi connector init failed\n");
252 	return -1;
253 }
254 
sunxi_drm_connector_destroy(int conn_id)255 void sunxi_drm_connector_destroy(int conn_id)
256 {
257 	struct sunxi_drm_connector *sunxi_conn;
258 
259 	sunxi_conn = sunxi_drm_connector_get_connector(conn_id);
260 	if (!sunxi_conn)
261 		return;
262 
263 	if (sunxi_conn) {
264 		drm_connector_cleanup(&sunxi_conn->connector);
265 		kfree(sunxi_conn);
266 		sunxi_drm_connector_set_connector(conn_id, NULL);
267 	}
268 }
269 
sunxi_drm_connector_exit(struct drm_device * dev)270 void sunxi_drm_connector_exit(struct drm_device *dev)
271 {
272 	int i, max_con;
273 
274 	max_con = sunxi_drm_connector_get_count();
275 
276 	for (i = 0; i < max_con; i++)
277 		sunxi_drm_connector_destroy(i);
278 }
279 
bsp_disp_hdmi_get_color_format(void)280 s32 bsp_disp_hdmi_get_color_format(void)
281 {
282 	struct sunxi_drm_connector *sconn;
283 	unsigned int i, cnt;
284 
285 	cnt = sunxi_drm_connector_get_count();
286 
287 	for (i = 0; i < cnt; i++) {
288 		sconn = sunxi_drm_connector_get_connector(i);
289 #if defined(CONFIG_AW_DRM_HDMI14) || defined(CONFIG_AW_DRM_HDMI20)
290 		if (sconn->type == DISP_OUTPUT_TYPE_HDMI)
291 			return sunxi_drm_connector_hdmi_get_color_format(
292 				&sconn->connector);
293 #endif
294 	}
295 
296 	return 0;
297 }
298