From bd008e5b2953186fc0c6633a885ade95e7043800 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 7 Oct 2014 14:13:51 +0100 Subject: [PATCH 01/15] drm: Implement O_NONBLOCK support on /dev/dri/cardN The implmentation is simple in the extreme: we only want to wait for events if the device was opened in blocking mode, otherwise we grab what is available and report an error if there was none. Signed-off-by: Chris Wilson Cc: dri-devel@lists.freedesktop.org Reviewed-by: Jesse Barnes Testcase: igt/kms_flip/nonblocing_read Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fops.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index ed7bc68f7e87..91e1105f2800 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -515,10 +515,12 @@ ssize_t drm_read(struct file *filp, char __user *buffer, size_t total; ssize_t ret; - ret = wait_event_interruptible(file_priv->event_wait, - !list_empty(&file_priv->event_list)); - if (ret < 0) - return ret; + if ((filp->f_flags & O_NONBLOCK) == 0) { + ret = wait_event_interruptible(file_priv->event_wait, + !list_empty(&file_priv->event_list)); + if (ret < 0) + return ret; + } total = 0; while (drm_dequeue_event(file_priv, total, count, &e)) { @@ -532,7 +534,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer, e->destroy(e); } - return total; + return total ?: -EAGAIN; } EXPORT_SYMBOL(drm_read); From a1f1a79c51fd493887bb66d932ee66a23f8b1527 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 11 Oct 2014 22:08:57 -0700 Subject: [PATCH 02/15] drm: drm_err: Remove unnecessary __func__ argument Removing the unnecessary drm_err __func__ argument by using the equivalent %pf and __builtin_return_address(0) makes the code smaller for every use of the DRM_ERROR macro. For instance: (allmodconfig) $ size drivers/gpu/drm/i915/i915.o* text data bss dec hex filename 922447 193257 296736 1412440 158d58 drivers/gpu/drm/i915/i915.o.new 928111 193257 296736 1418104 15a378 drivers/gpu/drm/i915/i915.o.old Signed-off-by: Joe Perches Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_drv.c | 5 +++-- include/drm/drmP.h | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index bc3da32d4585..2e5c7d941313 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -56,7 +56,7 @@ static struct idr drm_minors_idr; struct class *drm_class; static struct dentry *drm_debugfs_root; -void drm_err(const char *func, const char *format, ...) +void drm_err(const char *format, ...) { struct va_format vaf; va_list args; @@ -66,7 +66,8 @@ void drm_err(const char *func, const char *format, ...) vaf.fmt = format; vaf.va = &args; - printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); + printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV", + __builtin_return_address(0), &vaf); va_end(args); } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 53ed87698a74..d7ebd7b207e3 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -125,8 +125,8 @@ struct dma_buf_attachment; extern __printf(2, 3) void drm_ut_debug_printk(const char *function_name, const char *format, ...); -extern __printf(2, 3) -void drm_err(const char *func, const char *format, ...); +extern __printf(1, 2) +void drm_err(const char *format, ...); /***********************************************************************/ /** \name DRM template customization defaults */ @@ -155,7 +155,7 @@ void drm_err(const char *func, const char *format, ...); * \param arg arguments */ #define DRM_ERROR(fmt, ...) \ - drm_err(__func__, fmt, ##__VA_ARGS__) + drm_err(fmt, ##__VA_ARGS__) /** * Rate limited error output. Like DRM_ERROR() but won't flood the log. @@ -170,7 +170,7 @@ void drm_err(const char *func, const char *format, ...); DEFAULT_RATELIMIT_BURST); \ \ if (__ratelimit(&_rs)) \ - drm_err(__func__, fmt, ##__VA_ARGS__); \ + drm_err(fmt, ##__VA_ARGS__); \ }) #define DRM_INFO(fmt, ...) \ From d87af4d10558fedf636e3df1b10dd2954f9e2a78 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 12 Oct 2014 00:02:32 +0200 Subject: [PATCH 03/15] gpu: drm: drm_dp_mst_topology.c: Fix improper use of strncat Fixed wrong usage of strncat, switched to strlcpy. While sending the string size to function to reduce the potential for misuse in future. Signed-off-by: Rickard Strandqvist Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_mst_topology.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b3adf1445020..094af1d17e95 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -995,19 +995,20 @@ static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb, static void build_mst_prop_path(struct drm_dp_mst_port *port, struct drm_dp_mst_branch *mstb, - char *proppath) + char *proppath, + size_t proppath_size) { int i; char temp[8]; - snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id); + snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id); for (i = 0; i < (mstb->lct - 1); i++) { int shift = (i % 2) ? 0 : 4; int port_num = mstb->rad[i / 2] >> shift; - snprintf(temp, 8, "-%d", port_num); - strncat(proppath, temp, 255); + snprintf(temp, sizeof(temp), "-%d", port_num); + strlcat(proppath, temp, proppath_size); } - snprintf(temp, 8, "-%d", port->port_num); - strncat(proppath, temp, 255); + snprintf(temp, sizeof(temp), "-%d", port->port_num); + strlcat(proppath, temp, proppath_size); } static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, @@ -1078,7 +1079,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, if (created && !port->input) { char proppath[255]; - build_mst_prop_path(port, mstb, proppath); + build_mst_prop_path(port, mstb, proppath, sizeof(proppath)); port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath); } From 32197aab0425dbecc38462a91bc5c8acf70b2036 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 20 Oct 2014 23:53:13 +0900 Subject: [PATCH 04/15] gpu:drm: Fix typo in Documentation/DocBook/drm.xml This patch fix spelling typos found in drm.xml. It is because the file is generated from comments in source codes, I have to fix the typos within source files. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_irq.c | 4 ++-- drivers/gpu/drm/drm_modes.c | 2 +- drivers/gpu/drm/drm_prime.c | 4 ++-- drivers/gpu/drm/i915/i915_cmd_parser.c | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 2 +- include/drm/drm_dp_mst_helper.h | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e79c8d3700d8..7f94989e6fc9 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3611,7 +3611,7 @@ static struct drm_property *property_create_range(struct drm_device *dev, * object with drm_object_attach_property. The returned property object must be * freed with drm_property_destroy. * - * Userspace is allowed to set any interger value in the (min, max) range + * Userspace is allowed to set any integer value in the (min, max) range * inclusive. * * Returns: diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 5ef03c216a27..3e6b582f60dd 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1190,7 +1190,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); * * This functions restores the vblank interrupt state captured with * drm_vblank_off() again. Note that calls to drm_vblank_on() and - * drm_vblank_off() can be unbalanced and so can also be unconditionaly called + * drm_vblank_off() can be unbalanced and so can also be unconditionally called * in driver load code to reflect the current hardware state of the crtc. * * This is the legacy version of drm_crtc_vblank_on(). @@ -1237,7 +1237,7 @@ EXPORT_SYMBOL(drm_vblank_on); * * This functions restores the vblank interrupt state captured with * drm_vblank_off() again. Note that calls to drm_vblank_on() and - * drm_vblank_off() can be unbalanced and so can also be unconditionaly called + * drm_vblank_off() can be unbalanced and so can also be unconditionally called * in driver load code to reflect the current hardware state of the crtc. * * This is the native kms version of drm_vblank_on(). diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index d1b7d2006529..6d8b941c8200 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -914,7 +914,7 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); * * This function is a helper which can be used to validate modes against size * limitations of the DRM device/connector. If a mode is too big its status - * memeber is updated with the appropriate validation failure code. The list + * member is updated with the appropriate validation failure code. The list * itself is not changed. */ void drm_mode_validate_size(struct drm_device *dev, diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 78ca30808422..6872eca6555e 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -328,7 +328,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { */ /** - * drm_gem_prime_export - helper library implemention of the export callback + * drm_gem_prime_export - helper library implementation of the export callback * @dev: drm_device to export from * @obj: GEM object to export * @flags: flags like DRM_CLOEXEC @@ -483,7 +483,7 @@ out_unlock: EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); /** - * drm_gem_prime_import - helper library implemention of the import callback + * drm_gem_prime_import - helper library implementation of the import callback * @dev: drm_device to import into * @dma_buf: dma-buf object to import * diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index c45856bcc8b9..5506242ee766 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -73,7 +73,7 @@ * those commands required by the parser. This generally works because command * opcode ranges have standard command length encodings. So for commands that * the parser does not need to check, it can easily skip them. This is - * implementated via a per-ring length decoding vfunc. + * implemented via a per-ring length decoding vfunc. * * Unfortunately, there are a number of commands that do not follow the standard * length encoding for their opcode range, primarily amongst the MI_* commands. @@ -836,7 +836,7 @@ finish: * @ring: the ring in question * * Only certain platforms require software batch buffer command parsing, and - * only when enabled via module paramter. + * only when enabled via module parameter. * * Return: true if the ring requires software command parsing */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b65bdfc23ccb..65821bad3f6a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -664,7 +664,7 @@ enum punit_power_well { * need to be accessed during AUX communication, * * Generally the common lane corresponds to the pipe and - * the spline (PCS/TX) correponds to the port. + * the spline (PCS/TX) corresponds to the port. * * For dual channel PHY (VLV/CHV): * diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index bd1b28d99920..b7b9a097c213 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1639,7 +1639,7 @@ static uint32_t get_lr_context_size(struct intel_engine_cs *ring) * the creation is a deferred call: it's better to make sure first that we need to use * a given ring with the context. * - * Return: non-zero on eror. + * Return: non-zero on error. */ int intel_lr_context_deferred_create(struct intel_context *ctx, struct intel_engine_cs *ring) diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 9b446ada2532..3ecfcc143bdd 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -28,7 +28,7 @@ struct drm_dp_mst_branch; /** - * struct drm_dp_vcpi - Virtual Channel Payload Identifer + * struct drm_dp_vcpi - Virtual Channel Payload Identifier * @vcpi: Virtual channel ID. * @pbn: Payload Bandwidth Number for this channel * @aligned_pbn: PBN aligned with slot size From 209f5527b7ef06948d79f9dea636764db296db08 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 8 Oct 2014 11:37:20 -0500 Subject: [PATCH 05/15] drm/crtc: Fix two typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: ioclt -> ioctl in comment wrong variable name in debug message Signed-off-by: Chuck Ebbert Reviewed-by: Ville Syrjälä [danvet: Frob manually generated patch to make it apply.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 7f94989e6fc9..4be01899f29d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2943,7 +2943,7 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format); * @file_priv: drm file for the ioctl call * * Add a new FB to the specified CRTC, given a user request. This is the - * original addfb ioclt which only supported RGB formats. + * original addfb ioctl which only supported RGB formats. * * Called by the user via ioctl. * @@ -3080,7 +3080,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) num_planes = drm_format_num_planes(r->pixel_format); if (r->width == 0 || r->width % hsub) { - DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); + DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); return -EINVAL; } From 228f2cb32f0dbeef0b88dc97ea66a3c31b03de99 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 8 Oct 2014 11:40:34 -0500 Subject: [PATCH 06/15] drm/crtc: Remove duplicated ioctl code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make drm_mode_add_fb() call drm_mode_add_fb2() after converting its args to the new internal format, instead of duplicating code. Also picks up a lot more error checking, which the legacy modes should pass after being converted to the new format. Signed-off-by: Chuck Ebbert Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4be01899f29d..b4a6f08d0045 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2955,11 +2955,9 @@ int drm_mode_addfb(struct drm_device *dev, { struct drm_mode_fb_cmd *or = data; struct drm_mode_fb_cmd2 r = {}; - struct drm_mode_config *config = &dev->mode_config; - struct drm_framebuffer *fb; - int ret = 0; + int ret; - /* Use new struct with format internally */ + /* convert to new format and call new ioctl */ r.fb_id = or->fb_id; r.width = or->width; r.height = or->height; @@ -2967,26 +2965,11 @@ int drm_mode_addfb(struct drm_device *dev, r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); r.handles[0] = or->handle; - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; + ret = drm_mode_addfb2(dev, &r, file_priv); + if (ret) + return ret; - if ((config->min_width > r.width) || (r.width > config->max_width)) - return -EINVAL; - - if ((config->min_height > r.height) || (r.height > config->max_height)) - return -EINVAL; - - fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); - if (IS_ERR(fb)) { - DRM_DEBUG_KMS("could not create framebuffer\n"); - return PTR_ERR(fb); - } - - mutex_lock(&file_priv->fbs_lock); - or->fb_id = fb->base.id; - list_add(&fb->filp_head, &file_priv->fbs); - DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); - mutex_unlock(&file_priv->fbs_lock); + or->fb_id = r.fb_id; return ret; } From e45708976aea3a3c3aa959e3cc2b703fefbd758a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 22 Oct 2014 11:16:36 +0200 Subject: [PATCH 07/15] drm/dp-helper: Move the legacy helpers to gma500 Except for gma500 all drivers are converted to the new style helpers, which have much better abstraction of the underlying hw protocols and already much more helper functions (including the entire mst library) on top of them. Since no one seems to work on converting gma500 let's just move the code away so that new drivers don't end up accidentally using this. Cc: Patrik Jakobsson Reviewed-by: Patrik Jakobsson Reviewed-by: Alan Cox [danvet: Add __deprecated as requested by Alan. Also add a short FIXME comment and drop the EXPORT_SYMBOL which is no longer needed.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_helper.c | 192 ------------------------- drivers/gpu/drm/gma500/cdv_intel_dp.c | 195 ++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 20 --- 3 files changed, 195 insertions(+), 212 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 08e33b8b13a4..c088bad7e72f 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -39,198 +39,6 @@ * blocks, ... */ -/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ -static int -i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, - uint8_t write_byte, uint8_t *read_byte) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - int ret; - - ret = (*algo_data->aux_ch)(adapter, mode, - write_byte, read_byte); - return ret; -} - -/* - * I2C over AUX CH - */ - -/* - * Send the address. If the I2C link is running, this 'restarts' - * the connection with the new address, this is used for doing - * a write followed by a read (as needed for DDC) - */ -static int -i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - int mode = MODE_I2C_START; - int ret; - - if (reading) - mode |= MODE_I2C_READ; - else - mode |= MODE_I2C_WRITE; - algo_data->address = address; - algo_data->running = true; - ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); - return ret; -} - -/* - * Stop the I2C transaction. This closes out the link, sending - * a bare address packet with the MOT bit turned off - */ -static void -i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - int mode = MODE_I2C_STOP; - - if (reading) - mode |= MODE_I2C_READ; - else - mode |= MODE_I2C_WRITE; - if (algo_data->running) { - (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); - algo_data->running = false; - } -} - -/* - * Write a single byte to the current I2C address, the - * the I2C link must be running or this returns -EIO - */ -static int -i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - int ret; - - if (!algo_data->running) - return -EIO; - - ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); - return ret; -} - -/* - * Read a single byte from the current I2C address, the - * I2C link must be running or this returns -EIO - */ -static int -i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - int ret; - - if (!algo_data->running) - return -EIO; - - ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); - return ret; -} - -static int -i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) -{ - int ret = 0; - bool reading = false; - int m; - int b; - - for (m = 0; m < num; m++) { - u16 len = msgs[m].len; - u8 *buf = msgs[m].buf; - reading = (msgs[m].flags & I2C_M_RD) != 0; - ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); - if (ret < 0) - break; - if (reading) { - for (b = 0; b < len; b++) { - ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); - if (ret < 0) - break; - } - } else { - for (b = 0; b < len; b++) { - ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); - if (ret < 0) - break; - } - } - if (ret < 0) - break; - } - if (ret >= 0) - ret = num; - i2c_algo_dp_aux_stop(adapter, reading); - DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret); - return ret; -} - -static u32 -i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_SMBUS_READ_BLOCK_DATA | - I2C_FUNC_SMBUS_BLOCK_PROC_CALL | - I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm i2c_dp_aux_algo = { - .master_xfer = i2c_algo_dp_aux_xfer, - .functionality = i2c_algo_dp_aux_functionality, -}; - -static void -i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) -{ - (void) i2c_algo_dp_aux_address(adapter, 0, false); - (void) i2c_algo_dp_aux_stop(adapter, false); -} - -static int -i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) -{ - adapter->algo = &i2c_dp_aux_algo; - adapter->retries = 3; - i2c_dp_aux_reset_bus(adapter); - return 0; -} - -/** - * i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper - * @adapter: i2c adapter to register - * - * This registers an i2c adapter that uses dp aux channel as it's underlaying - * transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure - * and store it in the algo_data member of the @adapter argument. This will be - * used by the i2c over dp aux algorithm to drive the hardware. - * - * RETURNS: - * 0 on success, -ERRNO on failure. - * - * IMPORTANT: - * This interface is deprecated, please switch to the new dp aux helpers and - * drm_dp_aux_register(). - */ -int -i2c_dp_aux_add_bus(struct i2c_adapter *adapter) -{ - int error; - - error = i2c_dp_aux_prepare_bus(adapter); - if (error) - return error; - error = i2c_add_adapter(adapter); - return error; -} -EXPORT_SYMBOL(i2c_dp_aux_add_bus); - /* Helpers for DP link training */ static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r) { diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 9f158eab517a..0fafb8e2483a 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -37,6 +37,201 @@ #include "gma_display.h" #include +/** + * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp + * aux algorithm + * @running: set by the algo indicating whether an i2c is ongoing or whether + * the i2c bus is quiescent + * @address: i2c target address for the currently ongoing transfer + * @aux_ch: driver callback to transfer a single byte of the i2c payload + */ +struct i2c_algo_dp_aux_data { + bool running; + u16 address; + int (*aux_ch) (struct i2c_adapter *adapter, + int mode, uint8_t write_byte, + uint8_t *read_byte); +}; + +/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ +static int +i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int ret; + + ret = (*algo_data->aux_ch)(adapter, mode, + write_byte, read_byte); + return ret; +} + +/* + * I2C over AUX CH + */ + +/* + * Send the address. If the I2C link is running, this 'restarts' + * the connection with the new address, this is used for doing + * a write followed by a read (as needed for DDC) + */ +static int +i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int mode = MODE_I2C_START; + int ret; + + if (reading) + mode |= MODE_I2C_READ; + else + mode |= MODE_I2C_WRITE; + algo_data->address = address; + algo_data->running = true; + ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); + return ret; +} + +/* + * Stop the I2C transaction. This closes out the link, sending + * a bare address packet with the MOT bit turned off + */ +static void +i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int mode = MODE_I2C_STOP; + + if (reading) + mode |= MODE_I2C_READ; + else + mode |= MODE_I2C_WRITE; + if (algo_data->running) { + (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); + algo_data->running = false; + } +} + +/* + * Write a single byte to the current I2C address, the + * the I2C link must be running or this returns -EIO + */ +static int +i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int ret; + + if (!algo_data->running) + return -EIO; + + ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); + return ret; +} + +/* + * Read a single byte from the current I2C address, the + * I2C link must be running or this returns -EIO + */ +static int +i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + int ret; + + if (!algo_data->running) + return -EIO; + + ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); + return ret; +} + +static int +i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, + int num) +{ + int ret = 0; + bool reading = false; + int m; + int b; + + for (m = 0; m < num; m++) { + u16 len = msgs[m].len; + u8 *buf = msgs[m].buf; + reading = (msgs[m].flags & I2C_M_RD) != 0; + ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); + if (ret < 0) + break; + if (reading) { + for (b = 0; b < len; b++) { + ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); + if (ret < 0) + break; + } + } else { + for (b = 0; b < len; b++) { + ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); + if (ret < 0) + break; + } + } + if (ret < 0) + break; + } + if (ret >= 0) + ret = num; + i2c_algo_dp_aux_stop(adapter, reading); + DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret); + return ret; +} + +static u32 +i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_SMBUS_READ_BLOCK_DATA | + I2C_FUNC_SMBUS_BLOCK_PROC_CALL | + I2C_FUNC_10BIT_ADDR; +} + +static const struct i2c_algorithm i2c_dp_aux_algo = { + .master_xfer = i2c_algo_dp_aux_xfer, + .functionality = i2c_algo_dp_aux_functionality, +}; + +static void +i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) +{ + (void) i2c_algo_dp_aux_address(adapter, 0, false); + (void) i2c_algo_dp_aux_stop(adapter, false); +} + +static int +i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) +{ + adapter->algo = &i2c_dp_aux_algo; + adapter->retries = 3; + i2c_dp_aux_reset_bus(adapter); + return 0; +} + +/* + * FIXME: This is the old dp aux helper, gma500 is the last driver that needs to + * be ported over to the new helper code in drm_dp_helper.c like i915 or radeon. + */ +static int __deprecated +i2c_dp_aux_add_bus(struct i2c_adapter *adapter) +{ + int error; + + error = i2c_dp_aux_prepare_bus(adapter); + if (error) + return error; + error = i2c_add_adapter(adapter); + return error; +} + #define _wait_for(COND, MS, W) ({ \ unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ int ret__ = 0; \ diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 9305c718d789..afebb08eee3a 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -404,26 +404,6 @@ #define MODE_I2C_READ 4 #define MODE_I2C_STOP 8 -/** - * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp - * aux algorithm - * @running: set by the algo indicating whether an i2c is ongoing or whether - * the i2c bus is quiescent - * @address: i2c target address for the currently ongoing transfer - * @aux_ch: driver callback to transfer a single byte of the i2c payload - */ -struct i2c_algo_dp_aux_data { - bool running; - u16 address; - int (*aux_ch) (struct i2c_adapter *adapter, - int mode, uint8_t write_byte, - uint8_t *read_byte); -}; - -int -i2c_dp_aux_add_bus(struct i2c_adapter *adapter); - - #define DP_LINK_STATUS_SIZE 6 bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], int lane_count); From 5a1cbdb0fb6748a52a33f4ccd5d49486d7479fbb Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 23 Oct 2014 09:06:28 +0900 Subject: [PATCH 08/15] gpu: drm: Fix warning caused by a parameter description in drm_crtc.c This patch fix following error while "make xmldocs" Warning(.//drivers/gpu/drm/drm_crtc.c:778): Excess function parameter 'mode' description in 'drm_connector_get_cmdline_mode' Signed-off-by: Masanari Iida Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index b4a6f08d0045..4081d7ab8407 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -766,7 +766,6 @@ static void drm_mode_remove(struct drm_connector *connector, /** * drm_connector_get_cmdline_mode - reads the user's cmdline mode * @connector: connector to quwery - * @mode: returned mode * * The kernel supports per-connector configration of its consoles through * use of the video= parameter. This function parses that option and From 3b5b9932fb547a7c89169a1c43a73beee7183ed0 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 31 Oct 2014 14:39:11 +0000 Subject: [PATCH 09/15] drm: Add a note to drm_property_create() about property lifetime Cc: Chandra Konduru Cc: Daniel Vetter Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4081d7ab8407..0f3c24c0981b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3417,6 +3417,10 @@ void drm_fb_release(struct drm_file *priv) * object with drm_object_attach_property. The returned property object must be * freed with drm_property_destroy. * + * Note that the DRM core keeps a per-device list of properties and that, if + * drm_mode_config_cleanup() is called, it will destroy all properties created + * by the driver. + * * Returns: * A pointer to the newly created property on success, NULL on failure. */ From 9d5fab402d3b6fc3d4b895fbb0bde4e4f2378167 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 31 Oct 2014 14:39:12 +0000 Subject: [PATCH 10/15] drm/i915: Don't destroy DRM properties in the driver When drm properties are created, they are added to mode_config.property_list, which is then used in drm_mode_config_cleanup() to destroy every single property created by the driver. Cc: Chandra Konduru Cc: Daniel Vetter Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 47 ------------------------------- 1 file changed, 47 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9350edd6728d..6d7a277458b5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1991,57 +1991,10 @@ static int intel_sdvo_get_modes(struct drm_connector *connector) return !list_empty(&connector->probed_modes); } -static void -intel_sdvo_destroy_enhance_property(struct drm_connector *connector) -{ - struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - struct drm_device *dev = connector->dev; - - if (intel_sdvo_connector->left) - drm_property_destroy(dev, intel_sdvo_connector->left); - if (intel_sdvo_connector->right) - drm_property_destroy(dev, intel_sdvo_connector->right); - if (intel_sdvo_connector->top) - drm_property_destroy(dev, intel_sdvo_connector->top); - if (intel_sdvo_connector->bottom) - drm_property_destroy(dev, intel_sdvo_connector->bottom); - if (intel_sdvo_connector->hpos) - drm_property_destroy(dev, intel_sdvo_connector->hpos); - if (intel_sdvo_connector->vpos) - drm_property_destroy(dev, intel_sdvo_connector->vpos); - if (intel_sdvo_connector->saturation) - drm_property_destroy(dev, intel_sdvo_connector->saturation); - if (intel_sdvo_connector->contrast) - drm_property_destroy(dev, intel_sdvo_connector->contrast); - if (intel_sdvo_connector->hue) - drm_property_destroy(dev, intel_sdvo_connector->hue); - if (intel_sdvo_connector->sharpness) - drm_property_destroy(dev, intel_sdvo_connector->sharpness); - if (intel_sdvo_connector->flicker_filter) - drm_property_destroy(dev, intel_sdvo_connector->flicker_filter); - if (intel_sdvo_connector->flicker_filter_2d) - drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_2d); - if (intel_sdvo_connector->flicker_filter_adaptive) - drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_adaptive); - if (intel_sdvo_connector->tv_luma_filter) - drm_property_destroy(dev, intel_sdvo_connector->tv_luma_filter); - if (intel_sdvo_connector->tv_chroma_filter) - drm_property_destroy(dev, intel_sdvo_connector->tv_chroma_filter); - if (intel_sdvo_connector->dot_crawl) - drm_property_destroy(dev, intel_sdvo_connector->dot_crawl); - if (intel_sdvo_connector->brightness) - drm_property_destroy(dev, intel_sdvo_connector->brightness); -} - static void intel_sdvo_destroy(struct drm_connector *connector) { struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - if (intel_sdvo_connector->tv_format) - drm_property_destroy(connector->dev, - intel_sdvo_connector->tv_format); - - intel_sdvo_destroy_enhance_property(connector); drm_connector_cleanup(connector); kfree(intel_sdvo_connector); } From ba8ce31f438c6bdd1d37b07cfea36d248c7f64d0 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 31 Oct 2014 14:39:13 +0000 Subject: [PATCH 11/15] drm/gma500: Don't destroy DRM properties in the driver When drm properties are created, they are added to mode_config.property_list which is then used in drm_mode_config_cleanup() to destroy every single property created by the driver. Cc: Patrik Jakobsson Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 49 ------------------------- 1 file changed, 49 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 0be96fdb5e28..58529cea575d 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1631,57 +1631,8 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector) return !list_empty(&connector->probed_modes); } -static void -psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector) -{ - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - struct drm_device *dev = connector->dev; - - if (psb_intel_sdvo_connector->left) - drm_property_destroy(dev, psb_intel_sdvo_connector->left); - if (psb_intel_sdvo_connector->right) - drm_property_destroy(dev, psb_intel_sdvo_connector->right); - if (psb_intel_sdvo_connector->top) - drm_property_destroy(dev, psb_intel_sdvo_connector->top); - if (psb_intel_sdvo_connector->bottom) - drm_property_destroy(dev, psb_intel_sdvo_connector->bottom); - if (psb_intel_sdvo_connector->hpos) - drm_property_destroy(dev, psb_intel_sdvo_connector->hpos); - if (psb_intel_sdvo_connector->vpos) - drm_property_destroy(dev, psb_intel_sdvo_connector->vpos); - if (psb_intel_sdvo_connector->saturation) - drm_property_destroy(dev, psb_intel_sdvo_connector->saturation); - if (psb_intel_sdvo_connector->contrast) - drm_property_destroy(dev, psb_intel_sdvo_connector->contrast); - if (psb_intel_sdvo_connector->hue) - drm_property_destroy(dev, psb_intel_sdvo_connector->hue); - if (psb_intel_sdvo_connector->sharpness) - drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness); - if (psb_intel_sdvo_connector->flicker_filter) - drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter); - if (psb_intel_sdvo_connector->flicker_filter_2d) - drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d); - if (psb_intel_sdvo_connector->flicker_filter_adaptive) - drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive); - if (psb_intel_sdvo_connector->tv_luma_filter) - drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter); - if (psb_intel_sdvo_connector->tv_chroma_filter) - drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter); - if (psb_intel_sdvo_connector->dot_crawl) - drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl); - if (psb_intel_sdvo_connector->brightness) - drm_property_destroy(dev, psb_intel_sdvo_connector->brightness); -} - static void psb_intel_sdvo_destroy(struct drm_connector *connector) { - struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector); - - if (psb_intel_sdvo_connector->tv_format) - drm_property_destroy(connector->dev, - psb_intel_sdvo_connector->tv_format); - - psb_intel_sdvo_destroy_enhance_property(connector); drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); From 2c4cc91b0b43ae364d47b0eec560b8e5bd5af746 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 3 Nov 2014 20:51:45 -0500 Subject: [PATCH 12/15] drm: Fix DRM_FORCE_ON_DIGITAL use A connector may be forced on from the command line via video= command line setting. The digital output of dual-mode connectors can also be specifically selected and forced on; eg., 'video=DVI-I-2:D'. However, in this case, the connector->status will be mistakenly set to connector_status_disconnected, and the connector will not be mode set. Fix the connector->status when connector->force is DRM_FORCE_ON_DIGITAL. Note that this seems to have been broken ever since the introduction of the connector forcing support in commit d50ba256b5f1478e15accfcfda9b72fd7a661364 Author: Dave Airlie Date: Wed Sep 23 14:44:08 2009 +1000 drm/kms: start adding command line interface using fb. Signed-off-by: Peter Hurley [danvet: Add note about that this never worked.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_probe_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 6857e9ad6339..7483a47de8e4 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -118,7 +118,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect mode->status = MODE_UNVERIFIED; if (connector->force) { - if (connector->force == DRM_FORCE_ON) + if (connector->force == DRM_FORCE_ON || + connector->force == DRM_FORCE_ON_DIGITAL) connector->status = connector_status_connected; else connector->status = connector_status_disconnected; From b74c6c92f2839206a3714a00af53b4bdc24c7224 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 3 Nov 2014 20:53:41 -0500 Subject: [PATCH 13/15] drm: Remove compiler BUG_ON() test modeset->num_connectors must be 0 to reach the BUG_ON() which tests for non-zero modeset->num_connectors; remove BUG_ON(). Signed-off-by: Peter Hurley Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 0c0c39bac23d..09d47e9ba026 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1570,7 +1570,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) modeset = &fb_helper->crtc_info[i].mode_set; if (modeset->num_connectors == 0) { BUG_ON(modeset->fb); - BUG_ON(modeset->num_connectors); if (modeset->mode) drm_mode_destroy(dev, modeset->mode); modeset->mode = NULL; From e9cf6194ab0cdb8f40f1eca7b230751c2289557e Mon Sep 17 00:00:00 2001 From: Todd Previte Date: Tue, 4 Nov 2014 15:17:35 -0700 Subject: [PATCH 14/15] drm/dp: Add counters in the drm_dp_aux struct for I2C NACKs and DEFERs These counters are used for Displayort compliance testing to detect error conditions when executing tests 4.2.2.4 and 4.2.2.5 in the Displayport Link CTS specificaiton. They determine whether to use the preferred/requested mode or the failsafe mode during these tests. V2: - Addressed previous review feedback - Updated commit message - Changed from uint8_t to uint32_t Cc: dri-devel@lists.freedesktop.org Signed-off-by: Todd Previte [danvet: s/uint32_t/unsigned/ for clearer intent. Also drop the i915 from the subject, it's all core stuff.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_dp_helper.c | 2 ++ include/drm/drm_dp_helper.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index c088bad7e72f..959e2074b0d4 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -462,10 +462,12 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) case DP_AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("I2C nack\n"); + aux->i2c_nack_count++; return -EREMOTEIO; case DP_AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("I2C defer\n"); + aux->i2c_defer_count++; usleep_range(400, 500); continue; diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index afebb08eee3a..6041ad8c2f2d 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -530,6 +530,7 @@ struct drm_dp_aux { struct mutex hw_mutex; ssize_t (*transfer)(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg); + unsigned i2c_nack_count, i2c_defer_count; }; ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, From babc94936b7a48f0411c85a63074c0e378b55761 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 28 Oct 2014 16:20:47 +0200 Subject: [PATCH 15/15] drm/edid: add #defines and helpers for ELD In the interest of reducing magic numbers and having to cross check with the specs all the time. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- include/drm/drm_edid.h | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index b96031d947a0..c2f1bfa22010 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -207,6 +207,61 @@ struct detailed_timing { #define DRM_EDID_HDMI_DC_30 (1 << 4) #define DRM_EDID_HDMI_DC_Y444 (1 << 3) +/* ELD Header Block */ +#define DRM_ELD_HEADER_BLOCK_SIZE 4 + +#define DRM_ELD_VER 0 +# define DRM_ELD_VER_SHIFT 3 +# define DRM_ELD_VER_MASK (0x1f << 3) + +#define DRM_ELD_BASELINE_ELD_LEN 2 /* in dwords! */ + +/* ELD Baseline Block for ELD_Ver == 2 */ +#define DRM_ELD_CEA_EDID_VER_MNL 4 +# define DRM_ELD_CEA_EDID_VER_SHIFT 5 +# define DRM_ELD_CEA_EDID_VER_MASK (7 << 5) +# define DRM_ELD_CEA_EDID_VER_NONE (0 << 5) +# define DRM_ELD_CEA_EDID_VER_CEA861 (1 << 5) +# define DRM_ELD_CEA_EDID_VER_CEA861A (2 << 5) +# define DRM_ELD_CEA_EDID_VER_CEA861BCD (3 << 5) +# define DRM_ELD_MNL_SHIFT 0 +# define DRM_ELD_MNL_MASK (0x1f << 0) + +#define DRM_ELD_SAD_COUNT_CONN_TYPE 5 +# define DRM_ELD_SAD_COUNT_SHIFT 4 +# define DRM_ELD_SAD_COUNT_MASK (0xf << 4) +# define DRM_ELD_CONN_TYPE_SHIFT 2 +# define DRM_ELD_CONN_TYPE_MASK (3 << 2) +# define DRM_ELD_CONN_TYPE_HDMI (0 << 2) +# define DRM_ELD_CONN_TYPE_DP (1 << 2) +# define DRM_ELD_SUPPORTS_AI (1 << 1) +# define DRM_ELD_SUPPORTS_HDCP (1 << 0) + +#define DRM_ELD_AUD_SYNCH_DELAY 6 /* in units of 2 ms */ +# define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */ + +#define DRM_ELD_SPEAKER 7 +# define DRM_ELD_SPEAKER_RLRC (1 << 6) +# define DRM_ELD_SPEAKER_FLRC (1 << 5) +# define DRM_ELD_SPEAKER_RC (1 << 4) +# define DRM_ELD_SPEAKER_RLR (1 << 3) +# define DRM_ELD_SPEAKER_FC (1 << 2) +# define DRM_ELD_SPEAKER_LFE (1 << 1) +# define DRM_ELD_SPEAKER_FLR (1 << 0) + +#define DRM_ELD_PORT_ID 8 /* offsets 8..15 inclusive */ +# define DRM_ELD_PORT_ID_LEN 8 + +#define DRM_ELD_MANUFACTURER_NAME0 16 +#define DRM_ELD_MANUFACTURER_NAME1 17 + +#define DRM_ELD_PRODUCT_CODE0 18 +#define DRM_ELD_PRODUCT_CODE1 19 + +#define DRM_ELD_MONITOR_NAME_STRING 20 /* offsets 20..(20+mnl-1) inclusive */ + +#define DRM_ELD_CEA_SAD(mnl, sad) (20 + (mnl) + 3 * (sad)) + struct edid { u8 header[8]; /* Vendor & product info */ @@ -279,4 +334,51 @@ int drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, const struct drm_display_mode *mode); +/** + * drm_eld_mnl - Get ELD monitor name length in bytes. + * @eld: pointer to an eld memory structure with mnl set + */ +static inline int drm_eld_mnl(const uint8_t *eld) +{ + return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; +} + +/** + * drm_eld_sad_count - Get ELD SAD count. + * @eld: pointer to an eld memory structure with sad_count set + */ +static inline int drm_eld_sad_count(const uint8_t *eld) +{ + return (eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_SAD_COUNT_MASK) >> + DRM_ELD_SAD_COUNT_SHIFT; +} + +/** + * drm_eld_calc_baseline_block_size - Calculate baseline block size in bytes + * @eld: pointer to an eld memory structure with mnl and sad_count set + * + * This is a helper for determining the payload size of the baseline block, in + * bytes, for e.g. setting the Baseline_ELD_Len field in the ELD header block. + */ +static inline int drm_eld_calc_baseline_block_size(const uint8_t *eld) +{ + return DRM_ELD_MONITOR_NAME_STRING - DRM_ELD_HEADER_BLOCK_SIZE + + drm_eld_mnl(eld) + drm_eld_sad_count(eld) * 3; +} + +/** + * drm_eld_size - Get ELD size in bytes + * @eld: pointer to a complete eld memory structure + * + * The returned value does not include the vendor block. It's vendor specific, + * and comprises of the remaining bytes in the ELD memory buffer after + * drm_eld_size() bytes of header and baseline block. + * + * The returned value is guaranteed to be a multiple of 4. + */ +static inline int drm_eld_size(const uint8_t *eld) +{ + return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; +} + #endif /* __DRM_EDID_H__ */