• 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 <linux/device.h>
12 #include <linux/kernel.h>
13 #include <linux/fs.h>
14 
15 #include "sunxi_drm_fb.h"
16 #include "sunxi_drm_plane.h"
17 #include "sunxi_drm_gem.h"
18 #include "sunxi_drm_crtc.h"
19 #include "sunxi_drm_encoder.h"
20 #include "sunxi_drm_connector.h"
21 #include "sunxi_drm_sysfs.h"
22 #include "sunxi_drm_drv.h"
23 
24 #if 0
25 struct device *sunxi_drv_dev;
26 
27 static ssize_t sunxi_planes_info_show(struct device *device,
28 			   struct device_attribute *attr,
29 			   char *buf)
30 {
31 	ssize_t n = 0;
32 	struct drm_device *drm_dev = sunxi_drm_get_drm_device();
33 
34 	n += sunxi_drm_planes_show(buf + n, drm_dev, NULL);
35 
36 	return n;
37 }
38 
39 static ssize_t sunxi_planes_info_store(struct device *device,
40 			   struct device_attribute *attr,
41 			   const char *buf, size_t count)
42 {
43 	return count;
44 }
45 
46 static DEVICE_ATTR(planes_info, 0660, sunxi_planes_info_show, sunxi_planes_info_store);
47 
48 
49 static ssize_t sunxi_crtc_info_show(struct device *device,
50 			   struct device_attribute *attr,
51 			   char *buf)
52 {
53 	ssize_t n = 0;
54 	struct drm_device *drm_dev = sunxi_drm_get_drm_device();
55 
56 	n += sunxi_drm_crtc_show(buf + n, drm_dev);
57 
58 	return n;
59 }
60 
61 static ssize_t sunxi_crtc_info_store(struct device *device,
62 			   struct device_attribute *attr,
63 			   const char *buf, size_t count)
64 {
65 	return count;
66 }
67 
68 static DEVICE_ATTR(crtc_info, 0660, sunxi_crtc_info_show, sunxi_crtc_info_store);
69 
70 
71 static unsigned int fb_id;
72 
73 static char sunxi_printable_char(int c)
74 {
75 	return isascii(c) && isprint(c) ? c : '?';
76 }
77 
78 char *sunxi_drm_get_path_name(char *dir, uint32_t format,
79 						uint32_t w, uint32_t h)
80 {
81 	char *buf = kmalloc(100, GFP_KERNEL);
82 
83 	snprintf(buf, 32,
84 		 "%s/%dx%d_%c%c%c%c",
85 		 dir, w, h,
86 		 sunxi_printable_char(format & 0xff),
87 		 sunxi_printable_char((format >> 8) & 0xff),
88 		 sunxi_printable_char((format >> 16) & 0xff),
89 		 sunxi_printable_char((format >> 24) & 0x7f));
90 
91 	return buf;
92 }
93 
94 static ssize_t sunxi_fb_capture_show(struct device *device,
95 			   struct device_attribute *attr,
96 			   char *buf)
97 {
98 	ssize_t n = 0;
99 	unsigned int i;
100 	bool find = false;
101 	struct drm_framebuffer *fb = NULL;
102 	struct sunxi_drm_fb *sunxi_fb = NULL;
103 	unsigned char *vaddr;
104 
105 	struct file *fp;
106 	mm_segment_t fs;
107 	loff_t pos;
108 
109 	char *path;
110 	struct drm_device *dev = sunxi_drm_get_drm_device();
111 
112 	mutex_lock(&dev->mode_config.fb_lock);
113 	drm_for_each_fb(fb, dev) {
114 		DRM_INFO("fb base id:%d\n", fb->base.id);
115 		if (fb->base.id == fb_id) {
116 			find = true;
117 			break;
118 		}
119 	}
120 	mutex_unlock(&dev->mode_config.fb_lock);
121 
122 	if (!find) {
123 		DRM_ERROR("[ERROR]fb_id:%d is invalid!\n", fb_id);
124 		return n;
125 	}
126 
127 	sunxi_fb = to_sunxi_fb(fb);
128 
129 	path = sunxi_drm_get_path_name("/mnt", fb->pixel_format,
130 					fb->width, fb->height);
131 	if ((fb->pixel_format == DRM_FORMAT_XRGB8888)
132 			|| (fb->pixel_format == DRM_FORMAT_ARGB8888)) {
133 		fp = filp_open(path, O_RDWR | O_CREAT, 0644);
134 		if (IS_ERR(fp)) {
135 			n += sprintf(buf + n, "create file error\n");
136 			kfree(path);
137 			return n;
138 		}
139 
140 		fs = get_fs();
141 		set_fs(KERNEL_DS);
142 
143 		vaddr = sunxi_fb->obj[0]->vaddr;
144 
145 		n += sprintf(buf + n, "Wait for capture!\n");
146 		pos = fp->f_pos;
147 		vfs_write(fp, vaddr, fb->pitches[0] * fb->height, &pos);
148 		n += sprintf(buf + n, "Capture finished!\n");
149 
150 		set_fs(fs);
151 		filp_close(fp, NULL);
152 	} else if (fb->pixel_format == DRM_FORMAT_RGB888) {
153 		unsigned char alpha = 0xff;
154 
155 		fp = filp_open(path, O_RDWR | O_CREAT, 0644);
156 		if (IS_ERR(fp)) {
157 			n += sprintf(buf + n, "create file error\n");
158 			kfree(path);
159 			return n;
160 		}
161 
162 		vaddr = sunxi_fb->obj[0]->vaddr;
163 
164 		fs = get_fs();
165 		set_fs(KERNEL_DS);
166 
167 		n += sprintf(buf + n, "Wait for capture, for 0~2 minute...\n");
168 		pos = fp->f_pos;
169 		for (i = 0; i < fb->width * fb->height; i++) {
170 			vfs_write(fp, &vaddr[3 * i], 3, &pos);
171 			vfs_write(fp, &alpha, 1, &pos);
172 		}
173 		n += sprintf(buf + n, "Capture finished!\n");
174 
175 		set_fs(fs);
176 		filp_close(fp, NULL);
177 	} else {
178 		n += sprintf(buf + n, "[ERROR]NOT support format:%c%c%c%c\n",
179 				(char)(fb->pixel_format & 0xff),
180 				(char)((fb->pixel_format >> 8) & 0xff),
181 				(char)((fb->pixel_format >> 16) & 0xff),
182 				(char)((fb->pixel_format >> 24) & 0xff));
183 	}
184 
185 	n += sprintf(buf + n, "Program Finished!\n");
186 	kfree(path);
187 	return n;
188 }
189 
190 static ssize_t sunxi_fb_capture_store(struct device *device,
191 			   struct device_attribute *attr,
192 			   const char *buf, size_t count)
193 {
194 	fb_id = simple_strtoul(buf, NULL, 0);
195 
196 	return count;
197 }
198 
199 static DEVICE_ATTR(fb_capture, 0660, sunxi_fb_capture_show,
200 				sunxi_fb_capture_store);
201 
202 
203 static ssize_t sunxi_drm_fb_info_dump(char *buf)
204 {
205 	ssize_t n = 0;
206 	struct drm_framebuffer *fb;
207 	struct drm_device *dev = sunxi_drm_get_drm_device();
208 
209 	mutex_lock(&dev->mode_config.fb_lock);
210 	n += sprintf(buf + n, "fb num:%d\n", dev->mode_config.num_fb);
211 	drm_for_each_fb(fb, dev)
212 		n += sunxi_drm_fb_show(buf + n, fb);
213 	mutex_unlock(&dev->mode_config.fb_lock);
214 
215 	return n;
216 }
217 
218 static ssize_t sunxi_fb_info_show(struct device *device,
219 			   struct device_attribute *attr,
220 			   char *buf)
221 {
222 	ssize_t n = 0;
223 
224 	n += sunxi_drm_fb_info_dump(buf + n);
225 
226 	return n;
227 }
228 
229 static ssize_t sunxi_fb_info_store(struct device *device,
230 			   struct device_attribute *attr,
231 			   const char *buf, size_t count)
232 {
233 	return count;
234 }
235 
236 static DEVICE_ATTR(fb_info, 0660, sunxi_fb_info_show, sunxi_fb_info_store);
237 
238 static ssize_t sunxi_encoder_info_show(struct device *device,
239 			   struct device_attribute *attr,
240 			   char *buf)
241 {
242 	ssize_t n = 0;
243 	struct drm_device *drm_dev = sunxi_drm_get_drm_device();
244 
245 	n += sunxi_drm_encoder_show(buf + n, drm_dev);
246 
247 	return n;
248 }
249 
250 static ssize_t sunxi_encoder_info_store(struct device *device,
251 			   struct device_attribute *attr,
252 			   const char *buf, size_t count)
253 {
254 	return count;
255 }
256 
257 static DEVICE_ATTR(encoder_info, 0660, sunxi_encoder_info_show, sunxi_encoder_info_store);
258 
259 
260 static ssize_t sunxi_connector_info_show(struct device *device,
261 			   struct device_attribute *attr,
262 			   char *buf)
263 {
264 	ssize_t n = 0;
265 	struct drm_device *drm_dev = sunxi_drm_get_drm_device();
266 
267 	n += sunxi_drm_connector_show(buf + n, drm_dev);
268 
269 	return n;
270 }
271 
272 static ssize_t sunxi_connector_info_store(struct device *device,
273 			   struct device_attribute *attr,
274 			   const char *buf, size_t count)
275 {
276 	return count;
277 }
278 
279 static DEVICE_ATTR(connector_info, 0660, sunxi_connector_info_show, sunxi_connector_info_store);
280 
281 
282 static ssize_t sunxi_drm_debug_show(struct device *device,
283 			   struct device_attribute *attr,
284 			   char *buf)
285 {
286 	ssize_t n = 0;
287 
288 	n += sprintf(buf + n, "drm_debug=%u\n\n", drm_debug);
289 	n += sprintf(buf + n, "params explain:\n");
290 	n += sprintf(buf + n, "NONE print:0x00\n");
291 	n += sprintf(buf + n, "CORE print:0x01\n");
292 	n += sprintf(buf + n, "DRIVER print:0x02\n");
293 	n += sprintf(buf + n, "KMS print:0x04\n");
294 	n += sprintf(buf + n, "PRIME print:0x08\n");
295 	n += sprintf(buf + n, "ATOMIC print:0x10\n");
296 	n += sprintf(buf + n, "VBL print:0x20\n");
297 
298 	return n;
299 }
300 
301 static ssize_t sunxi_drm_debug_store(struct device *device,
302 			   struct device_attribute *attr,
303 			   const char *buf, size_t count)
304 {
305 	if (kstrtoul(buf, 0, (unsigned long *)&drm_debug) < 0) {
306 		DRM_ERROR("ERROR input\n");
307 		return 0;
308 	}
309 
310 	return count;
311 }
312 
313 static DEVICE_ATTR(debug, 0660, sunxi_drm_debug_show, sunxi_drm_debug_store);
314 
315 static struct attribute *sunxi_dev_attrs[] = {
316 	&dev_attr_planes_info.attr,
317 	&dev_attr_crtc_info.attr,
318 	&dev_attr_fb_capture.attr,
319 	&dev_attr_fb_info.attr,
320 	&dev_attr_encoder_info.attr,
321 	&dev_attr_connector_info.attr,
322 	&dev_attr_debug.attr,
323 	NULL
324 };
325 
326 static const struct attribute_group sunxi_dev_group = {
327 	.attrs = sunxi_dev_attrs,
328 };
329 
330 static const struct attribute_group *sunxi_drm_dev_groups[] = {
331 	&sunxi_dev_group,
332 	NULL
333 };
334 
335 int sunxi_drm_sysfs_init(struct drm_device *dev)
336 {
337 	sunxi_drv_dev = device_create_with_groups(dev->primary->kdev->class,
338 						dev->dev, 0, dev,
339 						sunxi_drm_dev_groups,
340 						"driver");
341 	if (IS_ERR(sunxi_drv_dev)) {
342 		DRM_ERROR("failed to register connector device: %ld\n",
343 						PTR_ERR(sunxi_drv_dev));
344 		return -1;
345 	}
346 
347 	return 0;
348 }
349 
350 
351 void sunxi_drm_sysfs_exit(struct drm_device *dev)
352 {
353 	device_unregister(sunxi_drv_dev);
354 }
355 #endif
356 
357