Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Copyright © 2008 Intel Corporation
  3 * Copyright © 2016 Collabora Ltd
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a
  6 * copy of this software and associated documentation files (the "Software"),
  7 * to deal in the Software without restriction, including without limitation
  8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9 * and/or sell copies of the Software, and to permit persons to whom the
 10 * Software is furnished to do so, subject to the following conditions:
 11 *
 12 * The above copyright notice and this permission notice (including the next
 13 * paragraph) shall be included in all copies or substantial portions of the
 14 * Software.
 15 *
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 22 * IN THE SOFTWARE.
 23 *
 24 * Based on code from the i915 driver.
 25 * Original author: Damien Lespiau <damien.lespiau@intel.com>
 26 *
 27 */
 28
 29#include <linux/circ_buf.h>
 30#include <linux/ctype.h>
 31#include <linux/debugfs.h>
 32#include <drm/drmP.h>
 33#include "drm_internal.h"
 34
 35/**
 36 * DOC: CRC ABI
 37 *
 38 * DRM device drivers can provide to userspace CRC information of each frame as
 39 * it reached a given hardware component (a "source").
 40 *
 41 * Userspace can control generation of CRCs in a given CRTC by writing to the
 42 * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
 43 * Accepted values are source names (which are driver-specific) and the "auto"
 44 * keyword, which will let the driver select a default source of frame CRCs
 45 * for this CRTC.
 46 *
 47 * Once frame CRC generation is enabled, userspace can capture them by reading
 48 * the dri/0/crtc-N/crc/data file. Each line in that file contains the frame
 49 * number in the first field and then a number of unsigned integer fields
 50 * containing the CRC data. Fields are separated by a single space and the number
 51 * of CRC fields is source-specific.
 52 *
 53 * Note that though in some cases the CRC is computed in a specified way and on
 54 * the frame contents as supplied by userspace (eDP 1.3), in general the CRC
 55 * computation is performed in an unspecified way and on frame contents that have
 56 * been already processed in also an unspecified way and thus userspace cannot
 57 * rely on being able to generate matching CRC values for the frame contents that
 58 * it submits. In this general case, the maximum userspace can do is to compare
 59 * the reported CRCs of frames that should have the same contents.
 60 */
 61
 62static int crc_control_show(struct seq_file *m, void *data)
 63{
 64	struct drm_crtc *crtc = m->private;
 65
 66	seq_printf(m, "%s\n", crtc->crc.source);
 67
 68	return 0;
 69}
 70
 71static int crc_control_open(struct inode *inode, struct file *file)
 72{
 73	struct drm_crtc *crtc = inode->i_private;
 74
 75	return single_open(file, crc_control_show, crtc);
 76}
 77
 78static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
 79				 size_t len, loff_t *offp)
 80{
 81	struct seq_file *m = file->private_data;
 82	struct drm_crtc *crtc = m->private;
 83	struct drm_crtc_crc *crc = &crtc->crc;
 84	char *source;
 85
 86	if (len == 0)
 87		return 0;
 88
 89	if (len > PAGE_SIZE - 1) {
 90		DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n",
 91			      PAGE_SIZE);
 92		return -E2BIG;
 93	}
 94
 95	source = memdup_user_nul(ubuf, len);
 96	if (IS_ERR(source))
 97		return PTR_ERR(source);
 98
 99	if (source[len] == '\n')
100		source[len] = '\0';
101
102	spin_lock_irq(&crc->lock);
103
104	if (crc->opened) {
105		spin_unlock_irq(&crc->lock);
106		kfree(source);
107		return -EBUSY;
108	}
109
110	kfree(crc->source);
111	crc->source = source;
112
113	spin_unlock_irq(&crc->lock);
114
115	*offp += len;
116	return len;
117}
118
119static const struct file_operations drm_crtc_crc_control_fops = {
120	.owner = THIS_MODULE,
121	.open = crc_control_open,
122	.read = seq_read,
123	.llseek = seq_lseek,
124	.release = single_release,
125	.write = crc_control_write
126};
127
128static int crtc_crc_open(struct inode *inode, struct file *filep)
129{
130	struct drm_crtc *crtc = inode->i_private;
131	struct drm_crtc_crc *crc = &crtc->crc;
132	struct drm_crtc_crc_entry *entries = NULL;
133	size_t values_cnt;
134	int ret;
135
136	if (crc->opened)
137		return -EBUSY;
138
139	ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
140	if (ret)
141		return ret;
142
143	if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) {
144		ret = -EINVAL;
145		goto err_disable;
146	}
147
148	if (WARN_ON(values_cnt == 0)) {
149		ret = -EINVAL;
150		goto err_disable;
151	}
152
153	entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL);
154	if (!entries) {
155		ret = -ENOMEM;
156		goto err_disable;
157	}
158
159	spin_lock_irq(&crc->lock);
160	crc->entries = entries;
161	crc->values_cnt = values_cnt;
162	crc->opened = true;
163	spin_unlock_irq(&crc->lock);
164
165	return 0;
166
167err_disable:
168	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
169	return ret;
170}
171
172static int crtc_crc_release(struct inode *inode, struct file *filep)
173{
174	struct drm_crtc *crtc = filep->f_inode->i_private;
175	struct drm_crtc_crc *crc = &crtc->crc;
176	size_t values_cnt;
177
178	spin_lock_irq(&crc->lock);
179	kfree(crc->entries);
180	crc->entries = NULL;
181	crc->head = 0;
182	crc->tail = 0;
183	crc->values_cnt = 0;
184	crc->opened = false;
185	spin_unlock_irq(&crc->lock);
186
187	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
188
189	return 0;
190}
191
192static int crtc_crc_data_count(struct drm_crtc_crc *crc)
193{
194	assert_spin_locked(&crc->lock);
195	return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR);
196}
197
198/*
199 * 1 frame field of 10 chars plus a number of CRC fields of 10 chars each, space
200 * separated, with a newline at the end and null-terminated.
201 */
202#define LINE_LEN(values_cnt)	(10 + 11 * values_cnt + 1 + 1)
203#define MAX_LINE_LEN		(LINE_LEN(DRM_MAX_CRC_NR))
204
205static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
206			     size_t count, loff_t *pos)
207{
208	struct drm_crtc *crtc = filep->f_inode->i_private;
209	struct drm_crtc_crc *crc = &crtc->crc;
210	struct drm_crtc_crc_entry *entry;
211	char buf[MAX_LINE_LEN];
212	int ret, i;
213
214	spin_lock_irq(&crc->lock);
215
216	if (!crc->source) {
217		spin_unlock_irq(&crc->lock);
218		return 0;
219	}
220
221	/* Nothing to read? */
222	while (crtc_crc_data_count(crc) == 0) {
223		if (filep->f_flags & O_NONBLOCK) {
224			spin_unlock_irq(&crc->lock);
225			return -EAGAIN;
226		}
227
228		ret = wait_event_interruptible_lock_irq(crc->wq,
229							crtc_crc_data_count(crc),
230							crc->lock);
231		if (ret) {
232			spin_unlock_irq(&crc->lock);
233			return ret;
234		}
235	}
236
237	/* We know we have an entry to be read */
238	entry = &crc->entries[crc->tail];
239
240	if (count < LINE_LEN(crc->values_cnt)) {
241		spin_unlock_irq(&crc->lock);
242		return -EINVAL;
243	}
244
245	BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR);
246	crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1);
247
248	spin_unlock_irq(&crc->lock);
249
250	if (entry->has_frame_counter)
251		sprintf(buf, "0x%08x", entry->frame);
252	else
253		sprintf(buf, "XXXXXXXXXX");
254
255	for (i = 0; i < crc->values_cnt; i++)
256		sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]);
257	sprintf(buf + 10 + crc->values_cnt * 11, "\n");
258
259	if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt)))
260		return -EFAULT;
261
262	return LINE_LEN(crc->values_cnt);
263}
264
265static const struct file_operations drm_crtc_crc_data_fops = {
266	.owner = THIS_MODULE,
267	.open = crtc_crc_open,
268	.read = crtc_crc_read,
269	.release = crtc_crc_release,
270};
271
272/**
273 * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs
274 * @crtc: CRTC to whom the frames will belong
275 *
276 * Adds files to debugfs directory that allows userspace to control the
277 * generation of frame CRCs and to read them.
278 *
279 * Returns:
280 * Zero on success, error code on failure.
281 */
282int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
283{
284	struct dentry *crc_ent, *ent;
285
286	if (!crtc->funcs->set_crc_source)
287		return 0;
288
289	crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry);
290	if (!crc_ent)
291		return -ENOMEM;
292
293	ent = debugfs_create_file("control", S_IRUGO, crc_ent, crtc,
294				  &drm_crtc_crc_control_fops);
295	if (!ent)
296		goto error;
297
298	ent = debugfs_create_file("data", S_IRUGO, crc_ent, crtc,
299				  &drm_crtc_crc_data_fops);
300	if (!ent)
301		goto error;
302
303	return 0;
304
305error:
306	debugfs_remove_recursive(crc_ent);
307
308	return -ENOMEM;
309}
310
311/**
312 * drm_crtc_add_crc_entry - Add entry with CRC information for a frame
313 * @crtc: CRTC to which the frame belongs
314 * @has_frame: whether this entry has a frame number to go with
315 * @frame: number of the frame these CRCs are about
316 * @crcs: array of CRC values, with length matching #drm_crtc_crc.values_cnt
317 *
318 * For each frame, the driver polls the source of CRCs for new data and calls
319 * this function to add them to the buffer from where userspace reads.
320 */
321int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
322			   uint32_t frame, uint32_t *crcs)
323{
324	struct drm_crtc_crc *crc = &crtc->crc;
325	struct drm_crtc_crc_entry *entry;
326	int head, tail;
327
328	assert_spin_locked(&crc->lock);
329
330	/* Caller may not have noticed yet that userspace has stopped reading */
331	if (!crc->opened)
332		return -EINVAL;
333
334	head = crc->head;
335	tail = crc->tail;
336
337	if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) {
338		DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n");
339		return -ENOBUFS;
340	}
341
342	entry = &crc->entries[head];
343	entry->frame = frame;
344	entry->has_frame_counter = has_frame;
345	memcpy(&entry->crcs, crcs, sizeof(*crcs) * crc->values_cnt);
346
347	head = (head + 1) & (DRM_CRC_ENTRIES_NR - 1);
348	crc->head = head;
349
350	return 0;
351}
352EXPORT_SYMBOL_GPL(drm_crtc_add_crc_entry);