The change adds support of internal HDMI I2C master controller, this
subdevice is used by default, if "ddc-i2c-bus" DT property is omitted.
The main purpose of this functionality is to support reading EDID from
an HDMI monitor on boards, which don't have an I2C bus connected to
DDC pins.
The current implementation does not support "I2C Master Interface
Extended Read Mode" to read data addressed by non-zero segment
pointer, this means that if EDID has more than 1 extension blocks,
EDID reading operation won't succeed, in my practice all tested HDMI
monitors have at maximum one extension block.
Signed-off-by: Vladimir Zapolskiy
---
The change is based on v4.3.0-rc2 and it is applicable to rmk/drm-dwhdmi-devel,
please let me know, if it should be rebased.
v3 of the change was
Tested-by: Philipp Zabel
Changes frov v3 to v4, thanks to Doug and Philipp for review:
- set speed mode after software reset in dw_hdmi_i2c_init()
- by default set standard speed mode instead of fast speed mode, on iMX6Q
this configures SCL to 100 KHz, which is compliant with HDMI 1.3a spec
- do I2C bus controller reinitialization on every data transfer,
this change hopefully solves some observed problems on RK3288 platform
- added short functional change description to dw_hdmi.txt
Changes from v2 to v3, thanks to Russell:
- moved register field value definitions to dw_hdmi.h
- made completions uninterruptible to avoid transfer retries if interrupted
- use one completion for both read and write transfers as in v1, operation_reg
is removed
- redundant i2c->stat = 0 is removed from dw_hdmi_i2c_read/write()
- struct i2c_algorithm dw_hdmi_algorithm is qualified as const
- dw_hdmi_i2c_adapter() does not modify struct dw_hdmi on error path
- dw_hdmi_i2c_irq() does not modify hdmi->i2c->stat, if interrupt is not for
I2CM
- spin lock is removed from dw_hdmi_i2c_irq()
- removed spin lock from dw_hdmi_i2c_xfer() around write to
HDMI_IH_MUTE_I2CM_STAT0 register
- split loop over message array in dw_hdmi_i2c_xfer() to validation and
transfer parts
- added a mutex to serialize I2C transfer requests, i2c->lock is completely
removed
- removed if(len) check from dw_hdmi_i2c_write(), hardware supports only len>0
transfers
- described extension blocks <= 1 limitation in the commit message
- a number of minor clean ups
Changes from v1 to v2:
- fixed a devm_kfree() signature
- split completions for read and write operations
.../devicetree/bindings/drm/bridge/dw_hdmi.txt | 4 +-
drivers/gpu/drm/bridge/dw_hdmi.c | 258 -
drivers/gpu/drm/bridge/dw_hdmi.h | 19 ++
3 files changed, 274 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
index a905c14..55f5a7c 100644
--- a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
+++ b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
@@ -19,7 +19,9 @@ Required properties:
Optional properties
- reg-io-width: the width of the reg:1,4, default set to 1 if not present
-- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing,
+ if the property is omitted, a functionally reduced I2C bus
+ controller on DW HDMI is probed
- clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
Example:
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0083d4e..58dcacf 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1,14 +1,15 @@
/*
+ * DesignWare High-Definition Multimedia Interface (HDMI) driver
+ *
+ * Copyright (C) 2013-2015 Mentor Graphics Inc.
* Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010, Guennadi Liakhovetski
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * Designware High-Definition Multimedia Interface (HDMI) driver
- *
- * Copyright (C) 2010, Guennadi Liakhovetski
*/
#include
#include
@@ -99,6 +100,17 @@ struct hdmi_data_info {
struct hdmi_vmode video_mode;
};
+struct dw_hdmi_i2c {
+ struct i2c_adapter adap;
+
+ struct mutexlock;
+ struct completion cmp;
+ u8 stat;
+
+ u8 slave_reg;
+ boolis_regaddr;
+};
+
struct dw_hdmi {
struct drm_connector connector;
struct drm_encoder *encoder;
@@ -108,6 +120,7 @@ struct dw_hdmi {
struct device *dev;
struct clk *isfr_clk;
struct clk *iahb_clk;
+ struct dw_hdmi_i2c *i2c;
struct hdmi_data_info hdmi_data;
const struct dw_hdmi_plat_data *plat_data;
@@ -184,6