Module Name: src Committed By: riastradh Date: Thu Mar 5 17:42:48 UTC 2015
Modified Files: src/sys/external/bsd/drm2/drm: drm_module.c files.drmkms src/sys/modules/drmkms: Makefile Added Files: src/sys/external/bsd/drm2/i2c: drm_encoder_slave.c src/sys/external/bsd/drm2/include/drm: drm_encoder_slave.h Log Message: Rewrite drm_encoder_slave.c, as nouveau will need. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/external/bsd/drm2/drm/drm_module.c \ src/sys/external/bsd/drm2/drm/files.drmkms cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/i2c/drm_encoder_slave.c cvs rdiff -u -r0 -r1.1 \ src/sys/external/bsd/drm2/include/drm/drm_encoder_slave.h cvs rdiff -u -r1.7 -r1.8 src/sys/modules/drmkms/Makefile Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/drm/drm_module.c diff -u src/sys/external/bsd/drm2/drm/drm_module.c:1.9 src/sys/external/bsd/drm2/drm/drm_module.c:1.10 --- src/sys/external/bsd/drm2/drm/drm_module.c:1.9 Wed Nov 12 03:14:00 2014 +++ src/sys/external/bsd/drm2/drm/drm_module.c Thu Mar 5 17:42:48 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: drm_module.c,v 1.9 2014/11/12 03:14:00 christos Exp $ */ +/* $NetBSD: drm_module.c,v 1.10 2015/03/05 17:42:48 riastradh Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_module.c,v 1.9 2014/11/12 03:14:00 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_module.c,v 1.10 2015/03/05 17:42:48 riastradh Exp $"); #include <sys/types.h> #include <sys/conf.h> @@ -45,6 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: drm_module.c #include <linux/mutex.h> #include <drm/drmP.h> +#include <drm/drm_encoder_slave.h> #include <drm/drm_sysctl.h> /* @@ -75,6 +76,7 @@ drm_init(void) drm_connector_ida_init(); drm_global_init(); drm_sysctl_init(&drm_def); + drm_i2c_encoders_init(); return 0; } @@ -95,6 +97,8 @@ drm_guarantee_initialized(void) static void drm_fini(void) { + + drm_i2c_encoders_fini(); drm_sysctl_fini(&drm_def); drm_global_release(); drm_connector_ida_destroy(); Index: src/sys/external/bsd/drm2/drm/files.drmkms diff -u src/sys/external/bsd/drm2/drm/files.drmkms:1.9 src/sys/external/bsd/drm2/drm/files.drmkms:1.10 --- src/sys/external/bsd/drm2/drm/files.drmkms:1.9 Wed Nov 12 02:24:40 2014 +++ src/sys/external/bsd/drm2/drm/files.drmkms Thu Mar 5 17:42:48 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.drmkms,v 1.9 2014/11/12 02:24:40 christos Exp $ +# $NetBSD: files.drmkms,v 1.10 2015/03/05 17:42:48 riastradh Exp $ include "external/bsd/drm2/linux/files.drmkms_linux" @@ -37,7 +37,7 @@ file external/bsd/drm2/dist/drm/drm_dma. file external/bsd/drm2/dist/drm/drm_dp_helper.c drmkms_i2c file external/bsd/drm2/drm/drm_drv.c drmkms file external/bsd/drm2/dist/drm/drm_edid.c drmkms_i2c -#file external/bsd/drm2/dist/drm/drm_encoder_slave.c drmkms_i2c +file external/bsd/drm2/i2c/drm_encoder_slave.c drmkms_i2c file external/bsd/drm2/dist/drm/drm_fb_helper.c drmkms file external/bsd/drm2/dist/drm/drm_flip_work.c drmkms file external/bsd/drm2/drm/drm_fops.c drmkms Index: src/sys/modules/drmkms/Makefile diff -u src/sys/modules/drmkms/Makefile:1.7 src/sys/modules/drmkms/Makefile:1.8 --- src/sys/modules/drmkms/Makefile:1.7 Sat Nov 22 19:18:07 2014 +++ src/sys/modules/drmkms/Makefile Thu Mar 5 17:42:48 2015 @@ -1,9 +1,10 @@ -# $NetBSD: Makefile,v 1.7 2014/11/22 19:18:07 riastradh Exp $ +# $NetBSD: Makefile,v 1.8 2015/03/05 17:42:48 riastradh Exp $ .include "../Makefile.inc" .include "Makefile.inc" .PATH: ${S}/external/bsd/drm2/drm +.PATH: ${S}/external/bsd/drm2/i2c .PATH: ${S}/external/bsd/drm2/pci .PATH: ${S}/external/bsd/drm2/dist/drm @@ -24,7 +25,7 @@ SRCS+= drm_dma.c SRCS+= drm_dp_helper.c SRCS+= drm_drv.c SRCS+= drm_edid.c -#SRCS+= drm_encoder_slave.c # XXX Rewrite for i2c. +SRCS+= drm_encoder_slave.c SRCS+= drm_fb_helper.c # XXX Rewrite for wsconsole. SRCS+= drm_flip_work.c SRCS+= drm_fops.c Added files: Index: src/sys/external/bsd/drm2/i2c/drm_encoder_slave.c diff -u /dev/null src/sys/external/bsd/drm2/i2c/drm_encoder_slave.c:1.1 --- /dev/null Thu Mar 5 17:42:48 2015 +++ src/sys/external/bsd/drm2/i2c/drm_encoder_slave.c Thu Mar 5 17:42:48 2015 @@ -0,0 +1,274 @@ +/* $NetBSD: drm_encoder_slave.c,v 1.1 2015/03/05 17:42:48 riastradh Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: drm_encoder_slave.c,v 1.1 2015/03/05 17:42:48 riastradh Exp $"); + +#include <sys/types.h> +#include <sys/atomic.h> +#include <sys/errno.h> +#include <sys/kmem.h> +#include <sys/mutex.h> +#include <sys/rbtree.h> +#include <sys/systm.h> + +#include <linux/i2c.h> + +#include <drm/drm_encoder_slave.h> + +static struct { + kmutex_t lock; + rb_tree_t tree; /* struct drm_i2c_encoder_driver */ +} drm_i2c_encoder_drivers; + +static int +compare_i2c_encoders(void *cookie __unused, const void *va, const void *vb) +{ + const struct drm_i2c_encoder_driver *const da = va; + const struct drm_i2c_encoder_driver *const db = vb; + + return strncmp(da->i2c_driver.driver.name, db->i2c_driver.driver.name, + I2C_NAME_SIZE); +} + +static int +compare_i2c_encoder_key(void *cookie __unused, const void *n, const void *k) +{ + const struct drm_i2c_encoder_driver *const driver = n; + const char *const name = k; + + return strncmp(driver->i2c_driver.driver.name, name, I2C_NAME_SIZE); +} + +static rb_tree_ops_t drm_i2c_encoder_rb_ops = { + .rbto_compare_nodes = &compare_i2c_encoders, + .rbto_compare_key = &compare_i2c_encoder_key, + .rbto_node_offset = offsetof(struct drm_i2c_encoder_driver, rb_node), + .rbto_context = NULL, +}; + +void +drm_i2c_encoders_init(void) +{ + + mutex_init(&drm_i2c_encoder_drivers.lock, MUTEX_DEFAULT, IPL_NONE); + rb_tree_init(&drm_i2c_encoder_drivers.tree, &drm_i2c_encoder_rb_ops); +} + +void +drm_i2c_encoders_fini(void) +{ + + KASSERT(RB_TREE_MIN(&drm_i2c_encoder_drivers.tree) == NULL); +#if 0 /* XXX no rb_tree_destroy */ + rb_tree_destroy(&drm_i2c_encoder_drivers.tree); +#endif + mutex_destroy(&drm_i2c_encoder_drivers.lock); +} + +int +drm_i2c_encoder_register(struct module *owner __unused, + struct drm_i2c_encoder_driver *driver) +{ + struct drm_i2c_encoder_driver *collision; + int ret = 0; + + mutex_enter(&drm_i2c_encoder_drivers.lock); + collision = rb_tree_insert_node(&drm_i2c_encoder_drivers.tree, driver); + if (collision != driver) + ret = -EEXIST; + mutex_exit(&drm_i2c_encoder_drivers.lock); + + return ret; +} + +void +drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *driver) +{ + + /* XXX How to guarantee? */ + KASSERT(driver->refcnt == 0); + + mutex_enter(&drm_i2c_encoder_drivers.lock); + rb_tree_remove_node(&drm_i2c_encoder_drivers.tree, driver); + mutex_exit(&drm_i2c_encoder_drivers.lock); +} + +struct drm_i2c_encoder_bus_priv { + struct i2c_client *i2c_client; + struct drm_i2c_encoder_driver *i2c_driver; +}; + +int +drm_i2c_encoder_init(struct drm_device *dev, struct drm_encoder_slave *slave, + struct i2c_adapter *adapter, const struct i2c_board_info *info) +{ + struct drm_i2c_encoder_driver *driver; + struct drm_i2c_encoder_bus_priv *bus_priv; + struct i2c_client *client; + unsigned refcnt; + int ret; + + bus_priv = kmem_alloc(sizeof(*bus_priv), KM_SLEEP); + slave->bus_priv = bus_priv; + + mutex_enter(&drm_i2c_encoder_drivers.lock); + driver = rb_tree_find_node(&drm_i2c_encoder_drivers.tree, info->type); + mutex_exit(&drm_i2c_encoder_drivers.lock); + if (driver == NULL) { + ret = -ENODEV; + goto fail0; + } + do { + refcnt = driver->refcnt; + if (refcnt == UINT_MAX) { + ret = -ENFILE; + goto fail0; + } + } while (atomic_cas_uint(&driver->refcnt, refcnt, refcnt + 1) + != refcnt); + bus_priv->i2c_driver = driver; + + client = i2c_new_device(adapter, info); + KASSERT(client != NULL); + bus_priv->i2c_client = client; + + ret = (*driver->encoder_init)(client, dev, slave); + if (ret) + goto fail1; + + if (info->platform_data) + (*slave->slave_funcs->set_config)(&slave->base, + info->platform_data); + + /* Success! */ + return 0; + +fail1: bus_priv->i2c_client = NULL; + i2c_unregister_device(client); + bus_priv->i2c_driver = NULL; + atomic_dec_uint(&driver->refcnt); +fail0: KASSERT(ret < 0); + slave->bus_priv = NULL; + kmem_free(bus_priv, sizeof(*bus_priv)); + return ret; +} + +void +drm_i2c_encoder_destroy(struct drm_encoder *encoder) +{ + struct drm_encoder_slave *const slave = to_encoder_slave(encoder); + struct drm_i2c_encoder_bus_priv *const bus_priv = slave->bus_priv; + struct i2c_client *const client = bus_priv->i2c_client; + struct drm_i2c_encoder_driver *const driver = bus_priv->i2c_driver; + + bus_priv->i2c_client = NULL; + i2c_unregister_device(client); + bus_priv->i2c_driver = NULL; + atomic_dec_uint(&driver->refcnt); +} + +struct i2c_client * +drm_i2c_encoder_get_client(struct drm_encoder *encoder) +{ + struct drm_encoder_slave *const slave = to_encoder_slave(encoder); + struct drm_i2c_encoder_bus_priv *const bus_priv = slave->bus_priv; + + return bus_priv->i2c_client; +} + +static inline struct drm_encoder_slave_funcs * +slave_funcs(struct drm_encoder *encoder) +{ + + return to_encoder_slave(encoder)->slave_funcs; +} + +void +drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + + (*slave_funcs(encoder)->dpms)(encoder, mode); +} + +void +drm_i2c_encoder_prepare(struct drm_encoder *encoder) +{ + + drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); +} + +void +drm_i2c_encoder_commit(struct drm_encoder *encoder) +{ + + drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON); +} + +bool +drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + + return (*slave_funcs(encoder)->mode_fixup)(encoder, mode, + adjusted_mode); +} + +void +drm_i2c_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) +{ + + return (*slave_funcs(encoder)->mode_set)(encoder, mode, adjusted_mode); +} + +enum drm_connector_status +drm_i2c_encoder_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + + return (*slave_funcs(encoder)->detect)(encoder, connector); +} + +void +drm_i2c_encoder_save(struct drm_encoder *encoder) +{ + + (*slave_funcs(encoder)->save)(encoder); +} + +void +drm_i2c_encoder_restore(struct drm_encoder *encoder) +{ + + (*slave_funcs(encoder)->restore)(encoder); +} Index: src/sys/external/bsd/drm2/include/drm/drm_encoder_slave.h diff -u /dev/null src/sys/external/bsd/drm2/include/drm/drm_encoder_slave.h:1.1 --- /dev/null Thu Mar 5 17:42:48 2015 +++ src/sys/external/bsd/drm2/include/drm/drm_encoder_slave.h Thu Mar 5 17:42:48 2015 @@ -0,0 +1,112 @@ +/* $NetBSD: drm_encoder_slave.h,v 1.1 2015/03/05 17:42:48 riastradh Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DRM_DRM_ENCODER_SLAVE_H_ +#define _DRM_DRM_ENCODER_SLAVE_H_ + +#include <sys/types.h> +#include <sys/rbtree.h> + +#include <drm/drm_crtc.h> + +struct drm_encoder_slave_funcs { + void (*set_config)(struct drm_encoder *, void *); + void (*destroy)(struct drm_encoder *); + void (*dpms)(struct drm_encoder *, int mode); + void (*save)(struct drm_encoder *); + void (*restore)(struct drm_encoder *); + bool (*mode_fixup)(struct drm_encoder *, + const struct drm_display_mode *, + struct drm_display_mode *); + int (*mode_valid)(struct drm_encoder *, struct drm_display_mode *); + void (*mode_set)(struct drm_encoder *, + const struct drm_display_mode *, + struct drm_display_mode *); + enum drm_connector_status + (*detect)(struct drm_encoder *, struct drm_connector *); + int (*get_modes)(struct drm_encoder *, struct drm_connector *); + int (*create_resources)(struct drm_encoder *, + struct drm_connector *); + int (*set_property)(struct drm_encoder *, struct drm_connector *, + struct drm_property *, uint64_t); +}; + +struct drm_encoder_slave { + struct drm_encoder base; + struct drm_encoder_slave_funcs *slave_funcs; + void *slave_priv; + void *bus_priv; +}; + +static inline struct drm_encoder_slave * +to_encoder_slave(struct drm_encoder *encoder) +{ + + return container_of(encoder, struct drm_encoder_slave, base); +} + +struct drm_i2c_encoder_driver { + struct i2c_driver i2c_driver; + int (*encoder_init)(struct i2c_client *, + struct drm_device *, + struct drm_encoder_slave *); + rb_node_t rb_node; + volatile unsigned refcnt; +}; + +struct module; + +void drm_i2c_encoders_init(void); +void drm_i2c_encoders_fini(void); + +int drm_i2c_encoder_register(struct module *, + struct drm_i2c_encoder_driver *); +void drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *); + +int drm_i2c_encoder_init(struct drm_device *, struct drm_encoder_slave *, + struct i2c_adapter *, const struct i2c_board_info *); +void drm_i2c_encoder_destroy(struct drm_encoder *); +struct i2c_client * + drm_i2c_encoder_get_client(struct drm_encoder *); + +void drm_i2c_encoder_dpms(struct drm_encoder *, int); +bool drm_i2c_encoder_mode_fixup(struct drm_encoder *, + const struct drm_display_mode *, struct drm_display_mode *); +void drm_i2c_encoder_prepare(struct drm_encoder *); +void drm_i2c_encoder_commit(struct drm_encoder *); +void drm_i2c_encoder_mode_set(struct drm_encoder *, + struct drm_display_mode *, struct drm_display_mode *); +enum drm_connector_status + drm_i2c_encoder_detect(struct drm_encoder *, struct drm_connector *); +void drm_i2c_encoder_save(struct drm_encoder *); +void drm_i2c_encoder_restore(struct drm_encoder *); + +#endif /* _DRM_DRM_ENCODER_SLAVE_H_ */