xref: /dflybsd-src/sys/dev/drm/drm_dp_aux_dev.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
18621f407SFrançois Tigeot /*
28621f407SFrançois Tigeot  * Copyright © 2015 Intel Corporation
38621f407SFrançois Tigeot  *
48621f407SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
58621f407SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
68621f407SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
78621f407SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88621f407SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
98621f407SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
108621f407SFrançois Tigeot  *
118621f407SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
128621f407SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
138621f407SFrançois Tigeot  * Software.
148621f407SFrançois Tigeot  *
158621f407SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168621f407SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178621f407SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188621f407SFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198621f407SFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
208621f407SFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
218621f407SFrançois Tigeot  * IN THE SOFTWARE.
228621f407SFrançois Tigeot  *
238621f407SFrançois Tigeot  * Authors:
248621f407SFrançois Tigeot  *    Rafael Antognolli <rafael.antognolli@intel.com>
258621f407SFrançois Tigeot  *
268621f407SFrançois Tigeot  */
278621f407SFrançois Tigeot 
288621f407SFrançois Tigeot #include <linux/device.h>
298621f407SFrançois Tigeot #include <linux/fs.h>
308621f407SFrançois Tigeot #include <linux/slab.h>
311e12ee3bSFrançois Tigeot #include <linux/init.h>
328621f407SFrançois Tigeot #include <linux/kernel.h>
338621f407SFrançois Tigeot #include <linux/module.h>
348621f407SFrançois Tigeot #include <linux/uaccess.h>
35*3f2dd94aSFrançois Tigeot #include <linux/uio.h>
368621f407SFrançois Tigeot #include <drm/drm_dp_helper.h>
378621f407SFrançois Tigeot #include <drm/drm_crtc.h>
381e12ee3bSFrançois Tigeot #include <drm/drmP.h>
398621f407SFrançois Tigeot 
401dedbd3bSFrançois Tigeot #include "drm_crtc_helper_internal.h"
411dedbd3bSFrançois Tigeot 
428621f407SFrançois Tigeot struct drm_dp_aux_dev {
438621f407SFrançois Tigeot 	unsigned index;
448621f407SFrançois Tigeot 	struct drm_dp_aux *aux;
458621f407SFrançois Tigeot 	struct device *dev;
468621f407SFrançois Tigeot 	struct kref refcount;
478621f407SFrançois Tigeot 	atomic_t usecount;
488621f407SFrançois Tigeot };
498621f407SFrançois Tigeot 
508621f407SFrançois Tigeot #define DRM_AUX_MINORS	256
518621f407SFrançois Tigeot #define AUX_MAX_OFFSET	(1 << 20)
528621f407SFrançois Tigeot #if 0
538621f407SFrançois Tigeot static DEFINE_IDR(aux_idr);
548621f407SFrançois Tigeot static DEFINE_MUTEX(aux_idr_mutex);
558621f407SFrançois Tigeot static struct class *drm_dp_aux_dev_class;
568621f407SFrançois Tigeot static int drm_dev_major = -1;
578621f407SFrançois Tigeot 
588621f407SFrançois Tigeot static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index)
598621f407SFrançois Tigeot {
608621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev = NULL;
618621f407SFrançois Tigeot 
628621f407SFrançois Tigeot 	mutex_lock(&aux_idr_mutex);
638621f407SFrançois Tigeot 	aux_dev = idr_find(&aux_idr, index);
648621f407SFrançois Tigeot 	if (!kref_get_unless_zero(&aux_dev->refcount))
658621f407SFrançois Tigeot 		aux_dev = NULL;
668621f407SFrançois Tigeot 	mutex_unlock(&aux_idr_mutex);
678621f407SFrançois Tigeot 
688621f407SFrançois Tigeot 	return aux_dev;
698621f407SFrançois Tigeot }
708621f407SFrançois Tigeot 
718621f407SFrançois Tigeot static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux)
728621f407SFrançois Tigeot {
738621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev;
748621f407SFrançois Tigeot 	int index;
758621f407SFrançois Tigeot 
768621f407SFrançois Tigeot 	aux_dev = kzalloc(sizeof(*aux_dev), GFP_KERNEL);
778621f407SFrançois Tigeot 	if (!aux_dev)
788621f407SFrançois Tigeot 		return ERR_PTR(-ENOMEM);
798621f407SFrançois Tigeot 	aux_dev->aux = aux;
808621f407SFrançois Tigeot 	atomic_set(&aux_dev->usecount, 1);
818621f407SFrançois Tigeot 	kref_init(&aux_dev->refcount);
828621f407SFrançois Tigeot 
838621f407SFrançois Tigeot 	mutex_lock(&aux_idr_mutex);
848621f407SFrançois Tigeot 	index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
858621f407SFrançois Tigeot 				 GFP_KERNEL);
868621f407SFrançois Tigeot 	mutex_unlock(&aux_idr_mutex);
878621f407SFrançois Tigeot 	if (index < 0) {
888621f407SFrançois Tigeot 		kfree(aux_dev);
898621f407SFrançois Tigeot 		return ERR_PTR(index);
908621f407SFrançois Tigeot 	}
918621f407SFrançois Tigeot 	aux_dev->index = index;
928621f407SFrançois Tigeot 
938621f407SFrançois Tigeot 	return aux_dev;
948621f407SFrançois Tigeot }
958621f407SFrançois Tigeot 
968621f407SFrançois Tigeot static void release_drm_dp_aux_dev(struct kref *ref)
978621f407SFrançois Tigeot {
988621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev =
998621f407SFrançois Tigeot 		container_of(ref, struct drm_dp_aux_dev, refcount);
1008621f407SFrançois Tigeot 
1018621f407SFrançois Tigeot 	kfree(aux_dev);
1028621f407SFrançois Tigeot }
1038621f407SFrançois Tigeot 
1048621f407SFrançois Tigeot static ssize_t name_show(struct device *dev,
1058621f407SFrançois Tigeot 			 struct device_attribute *attr, char *buf)
1068621f407SFrançois Tigeot {
1078621f407SFrançois Tigeot 	ssize_t res;
1088621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev =
1098621f407SFrançois Tigeot 		drm_dp_aux_dev_get_by_minor(MINOR(dev->devt));
1108621f407SFrançois Tigeot 
1118621f407SFrançois Tigeot 	if (!aux_dev)
1128621f407SFrançois Tigeot 		return -ENODEV;
1138621f407SFrançois Tigeot 
1148621f407SFrançois Tigeot 	res = sprintf(buf, "%s\n", aux_dev->aux->name);
1158621f407SFrançois Tigeot 	kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
1168621f407SFrançois Tigeot 
1178621f407SFrançois Tigeot 	return res;
1188621f407SFrançois Tigeot }
1198621f407SFrançois Tigeot static DEVICE_ATTR_RO(name);
1208621f407SFrançois Tigeot 
1218621f407SFrançois Tigeot static struct attribute *drm_dp_aux_attrs[] = {
1228621f407SFrançois Tigeot 	&dev_attr_name.attr,
1238621f407SFrançois Tigeot 	NULL,
1248621f407SFrançois Tigeot };
1258621f407SFrançois Tigeot ATTRIBUTE_GROUPS(drm_dp_aux);
1268621f407SFrançois Tigeot 
1278621f407SFrançois Tigeot static int auxdev_open(struct inode *inode, struct file *file)
1288621f407SFrançois Tigeot {
1298621f407SFrançois Tigeot 	unsigned int minor = iminor(inode);
1308621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev;
1318621f407SFrançois Tigeot 
1328621f407SFrançois Tigeot 	aux_dev = drm_dp_aux_dev_get_by_minor(minor);
1338621f407SFrançois Tigeot 	if (!aux_dev)
1348621f407SFrançois Tigeot 		return -ENODEV;
1358621f407SFrançois Tigeot 
1368621f407SFrançois Tigeot 	file->private_data = aux_dev;
1378621f407SFrançois Tigeot 	return 0;
1388621f407SFrançois Tigeot }
1398621f407SFrançois Tigeot 
1408621f407SFrançois Tigeot static loff_t auxdev_llseek(struct file *file, loff_t offset, int whence)
1418621f407SFrançois Tigeot {
1428621f407SFrançois Tigeot 	return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET);
1438621f407SFrançois Tigeot }
1448621f407SFrançois Tigeot 
145*3f2dd94aSFrançois Tigeot static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
1468621f407SFrançois Tigeot {
147*3f2dd94aSFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
148*3f2dd94aSFrançois Tigeot 	loff_t pos = iocb->ki_pos;
1498621f407SFrançois Tigeot 	ssize_t res = 0;
1508621f407SFrançois Tigeot 
1518621f407SFrançois Tigeot 	if (!atomic_inc_not_zero(&aux_dev->usecount))
1528621f407SFrançois Tigeot 		return -ENODEV;
1538621f407SFrançois Tigeot 
154*3f2dd94aSFrançois Tigeot 	iov_iter_truncate(to, AUX_MAX_OFFSET - pos);
1558621f407SFrançois Tigeot 
156*3f2dd94aSFrançois Tigeot 	while (iov_iter_count(to)) {
157*3f2dd94aSFrançois Tigeot 		uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES];
158*3f2dd94aSFrançois Tigeot 		ssize_t todo = min(iov_iter_count(to), sizeof(buf));
1598621f407SFrançois Tigeot 
1608621f407SFrançois Tigeot 		if (signal_pending(current)) {
161*3f2dd94aSFrançois Tigeot 			res = -ERESTARTSYS;
162*3f2dd94aSFrançois Tigeot 			break;
1638621f407SFrançois Tigeot 		}
1648621f407SFrançois Tigeot 
165*3f2dd94aSFrançois Tigeot 		res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
166*3f2dd94aSFrançois Tigeot 		if (res <= 0)
167*3f2dd94aSFrançois Tigeot 			break;
168*3f2dd94aSFrançois Tigeot 
169*3f2dd94aSFrançois Tigeot 		if (copy_to_iter(buf, res, to) != res) {
170*3f2dd94aSFrançois Tigeot 			res = -EFAULT;
171*3f2dd94aSFrançois Tigeot 			break;
1728621f407SFrançois Tigeot 		}
1738621f407SFrançois Tigeot 
174*3f2dd94aSFrançois Tigeot 		pos += res;
175*3f2dd94aSFrançois Tigeot 	}
176*3f2dd94aSFrançois Tigeot 
177*3f2dd94aSFrançois Tigeot 	if (pos != iocb->ki_pos)
178*3f2dd94aSFrançois Tigeot 		res = pos - iocb->ki_pos;
179*3f2dd94aSFrançois Tigeot 	iocb->ki_pos = pos;
180*3f2dd94aSFrançois Tigeot 
1818621f407SFrançois Tigeot 	atomic_dec(&aux_dev->usecount);
1828621f407SFrançois Tigeot 	wake_up_atomic_t(&aux_dev->usecount);
1838621f407SFrançois Tigeot 	return res;
1848621f407SFrançois Tigeot }
1858621f407SFrançois Tigeot 
186*3f2dd94aSFrançois Tigeot static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
1878621f407SFrançois Tigeot {
188*3f2dd94aSFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data;
189*3f2dd94aSFrançois Tigeot 	loff_t pos = iocb->ki_pos;
1908621f407SFrançois Tigeot 	ssize_t res = 0;
1918621f407SFrançois Tigeot 
1928621f407SFrançois Tigeot 	if (!atomic_inc_not_zero(&aux_dev->usecount))
1938621f407SFrançois Tigeot 		return -ENODEV;
1948621f407SFrançois Tigeot 
195*3f2dd94aSFrançois Tigeot 	iov_iter_truncate(from, AUX_MAX_OFFSET - pos);
1968621f407SFrançois Tigeot 
197*3f2dd94aSFrançois Tigeot 	while (iov_iter_count(from)) {
198*3f2dd94aSFrançois Tigeot 		uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES];
199*3f2dd94aSFrançois Tigeot 		ssize_t todo = min(iov_iter_count(from), sizeof(buf));
2008621f407SFrançois Tigeot 
2018621f407SFrançois Tigeot 		if (signal_pending(current)) {
202*3f2dd94aSFrançois Tigeot 			res = -ERESTARTSYS;
203*3f2dd94aSFrançois Tigeot 			break;
2048621f407SFrançois Tigeot 		}
2058621f407SFrançois Tigeot 
206*3f2dd94aSFrançois Tigeot 		if (!copy_from_iter_full(buf, todo, from)) {
207*3f2dd94aSFrançois Tigeot 			res = -EFAULT;
208*3f2dd94aSFrançois Tigeot 			break;
2098621f407SFrançois Tigeot 		}
2108621f407SFrançois Tigeot 
211*3f2dd94aSFrançois Tigeot 		res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
212*3f2dd94aSFrançois Tigeot 		if (res <= 0)
213*3f2dd94aSFrançois Tigeot 			break;
214*3f2dd94aSFrançois Tigeot 
215*3f2dd94aSFrançois Tigeot 		pos += res;
2168621f407SFrançois Tigeot 	}
2178621f407SFrançois Tigeot 
218*3f2dd94aSFrançois Tigeot 	if (pos != iocb->ki_pos)
219*3f2dd94aSFrançois Tigeot 		res = pos - iocb->ki_pos;
220*3f2dd94aSFrançois Tigeot 	iocb->ki_pos = pos;
221*3f2dd94aSFrançois Tigeot 
2228621f407SFrançois Tigeot 	atomic_dec(&aux_dev->usecount);
2238621f407SFrançois Tigeot 	wake_up_atomic_t(&aux_dev->usecount);
2248621f407SFrançois Tigeot 	return res;
2258621f407SFrançois Tigeot }
2268621f407SFrançois Tigeot 
2278621f407SFrançois Tigeot static int auxdev_release(struct inode *inode, struct file *file)
2288621f407SFrançois Tigeot {
2298621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev = file->private_data;
2308621f407SFrançois Tigeot 
2318621f407SFrançois Tigeot 	kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
2328621f407SFrançois Tigeot 	return 0;
2338621f407SFrançois Tigeot }
2348621f407SFrançois Tigeot 
2358621f407SFrançois Tigeot static const struct file_operations auxdev_fops = {
2368621f407SFrançois Tigeot 	.owner		= THIS_MODULE,
2378621f407SFrançois Tigeot 	.llseek		= auxdev_llseek,
238*3f2dd94aSFrançois Tigeot 	.read_iter	= auxdev_read_iter,
239*3f2dd94aSFrançois Tigeot 	.write_iter	= auxdev_write_iter,
2408621f407SFrançois Tigeot 	.open		= auxdev_open,
2418621f407SFrançois Tigeot 	.release	= auxdev_release,
2428621f407SFrançois Tigeot };
2438621f407SFrançois Tigeot 
2448621f407SFrançois Tigeot #define to_auxdev(d) container_of(d, struct drm_dp_aux_dev, aux)
2458621f407SFrançois Tigeot 
2468621f407SFrançois Tigeot static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_aux(struct drm_dp_aux *aux)
2478621f407SFrançois Tigeot {
2488621f407SFrançois Tigeot 	struct drm_dp_aux_dev *iter, *aux_dev = NULL;
2498621f407SFrançois Tigeot 	int id;
2508621f407SFrançois Tigeot 
2518621f407SFrançois Tigeot 	/* don't increase kref count here because this function should only be
2528621f407SFrançois Tigeot 	 * used by drm_dp_aux_unregister_devnode. Thus, it will always have at
2538621f407SFrançois Tigeot 	 * least one reference - the one that drm_dp_aux_register_devnode
2548621f407SFrançois Tigeot 	 * created
2558621f407SFrançois Tigeot 	 */
2568621f407SFrançois Tigeot 	mutex_lock(&aux_idr_mutex);
2578621f407SFrançois Tigeot 	idr_for_each_entry(&aux_idr, iter, id) {
2588621f407SFrançois Tigeot 		if (iter->aux == aux) {
2598621f407SFrançois Tigeot 			aux_dev = iter;
2608621f407SFrançois Tigeot 			break;
2618621f407SFrançois Tigeot 		}
2628621f407SFrançois Tigeot 	}
2638621f407SFrançois Tigeot 	mutex_unlock(&aux_idr_mutex);
2648621f407SFrançois Tigeot 	return aux_dev;
2658621f407SFrançois Tigeot }
2668621f407SFrançois Tigeot 
2678621f407SFrançois Tigeot void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
2688621f407SFrançois Tigeot {
2698621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev;
2708621f407SFrançois Tigeot 	unsigned int minor;
2718621f407SFrançois Tigeot 
2728621f407SFrançois Tigeot 	aux_dev = drm_dp_aux_dev_get_by_aux(aux);
2738621f407SFrançois Tigeot 	if (!aux_dev) /* attach must have failed */
2748621f407SFrançois Tigeot 		return;
2758621f407SFrançois Tigeot 
2768621f407SFrançois Tigeot 	mutex_lock(&aux_idr_mutex);
2778621f407SFrançois Tigeot 	idr_remove(&aux_idr, aux_dev->index);
2788621f407SFrançois Tigeot 	mutex_unlock(&aux_idr_mutex);
2798621f407SFrançois Tigeot 
2808621f407SFrançois Tigeot 	atomic_dec(&aux_dev->usecount);
281*3f2dd94aSFrançois Tigeot 	wait_on_atomic_t(&aux_dev->usecount, atomic_t_wait,
2828621f407SFrançois Tigeot 			 TASK_UNINTERRUPTIBLE);
2838621f407SFrançois Tigeot 
2848621f407SFrançois Tigeot 	minor = aux_dev->index;
2858621f407SFrançois Tigeot 	if (aux_dev->dev)
2868621f407SFrançois Tigeot 		device_destroy(drm_dp_aux_dev_class,
2878621f407SFrançois Tigeot 			       MKDEV(drm_dev_major, minor));
2888621f407SFrançois Tigeot 
2898621f407SFrançois Tigeot 	DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name);
2908621f407SFrançois Tigeot 	kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
2918621f407SFrançois Tigeot }
2928621f407SFrançois Tigeot 
2938621f407SFrançois Tigeot int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
2948621f407SFrançois Tigeot {
2958621f407SFrançois Tigeot 	struct drm_dp_aux_dev *aux_dev;
2968621f407SFrançois Tigeot 	int res;
2978621f407SFrançois Tigeot 
2988621f407SFrançois Tigeot 	aux_dev = alloc_drm_dp_aux_dev(aux);
2998621f407SFrançois Tigeot 	if (IS_ERR(aux_dev))
3008621f407SFrançois Tigeot 		return PTR_ERR(aux_dev);
3018621f407SFrançois Tigeot 
3028621f407SFrançois Tigeot 	aux_dev->dev = device_create(drm_dp_aux_dev_class, aux->dev,
3038621f407SFrançois Tigeot 				     MKDEV(drm_dev_major, aux_dev->index), NULL,
3048621f407SFrançois Tigeot 				     "drm_dp_aux%d", aux_dev->index);
3058621f407SFrançois Tigeot 	if (IS_ERR(aux_dev->dev)) {
3068621f407SFrançois Tigeot 		res = PTR_ERR(aux_dev->dev);
3078621f407SFrançois Tigeot 		aux_dev->dev = NULL;
3088621f407SFrançois Tigeot 		goto error;
3098621f407SFrançois Tigeot 	}
3108621f407SFrançois Tigeot 
3118621f407SFrançois Tigeot 	DRM_DEBUG("drm_dp_aux_dev: aux [%s] registered as minor %d\n",
3128621f407SFrançois Tigeot 		  aux->name, aux_dev->index);
3138621f407SFrançois Tigeot 	return 0;
3148621f407SFrançois Tigeot error:
3158621f407SFrançois Tigeot 	drm_dp_aux_unregister_devnode(aux);
3168621f407SFrançois Tigeot 	return res;
3178621f407SFrançois Tigeot }
3188621f407SFrançois Tigeot 
3198621f407SFrançois Tigeot int drm_dp_aux_dev_init(void)
3208621f407SFrançois Tigeot {
3218621f407SFrançois Tigeot 	int res;
3228621f407SFrançois Tigeot 
3238621f407SFrançois Tigeot 	drm_dp_aux_dev_class = class_create(THIS_MODULE, "drm_dp_aux_dev");
3248621f407SFrançois Tigeot 	if (IS_ERR(drm_dp_aux_dev_class)) {
3251dedbd3bSFrançois Tigeot 		return PTR_ERR(drm_dp_aux_dev_class);
3268621f407SFrançois Tigeot 	}
3278621f407SFrançois Tigeot 	drm_dp_aux_dev_class->dev_groups = drm_dp_aux_groups;
3288621f407SFrançois Tigeot 
3298621f407SFrançois Tigeot 	res = register_chrdev(0, "aux", &auxdev_fops);
3308621f407SFrançois Tigeot 	if (res < 0)
3318621f407SFrançois Tigeot 		goto out;
3328621f407SFrançois Tigeot 	drm_dev_major = res;
3338621f407SFrançois Tigeot 
3348621f407SFrançois Tigeot 	return 0;
3358621f407SFrançois Tigeot out:
3368621f407SFrançois Tigeot 	class_destroy(drm_dp_aux_dev_class);
3378621f407SFrançois Tigeot 	return res;
3388621f407SFrançois Tigeot }
3398621f407SFrançois Tigeot 
3408621f407SFrançois Tigeot void drm_dp_aux_dev_exit(void)
3418621f407SFrançois Tigeot {
3428621f407SFrançois Tigeot 	unregister_chrdev(drm_dev_major, "aux");
3438621f407SFrançois Tigeot 	class_destroy(drm_dp_aux_dev_class);
3448621f407SFrançois Tigeot }
3451e12ee3bSFrançois Tigeot #endif	/* 0 */
346