aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Armstrong <narmstrong@baylibre.com>2017-03-03 12:20:06 -0500
committerArchit Taneja <architt@codeaurora.org>2017-03-10 05:07:47 -0500
commit80e2f97968b537fc9c1789fce1b7f61609a5aae4 (patch)
tree0e0acd947b483b0a8b01a2c985d3527723dade7c
parent2e6777e8d5dd883b983c8de8797ff92bcb158f7c (diff)
drm: bridge: dw-hdmi: Switch to regmap for register access
The Synopsys Designware HDMI TX Controller does not enforce register access on platforms instanciating it. The current driver supports two different types of memory-mapped flat register access, but in order to support the Amlogic Meson SoCs integration, and provide a more generic way to handle all sorts of register mapping, switch the register access to use the regmap infrastructure. In the case of registers that are not flat memory-mapped or do not conform to the current driver implementation, a regmap struct can be given in the plat_data and be used at probe or bind. Since the AHB audio driver is only available with direct memory access, only allow the I2S audio driver to be registered is directly memory-mapped. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Tested-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com> Signed-off-by: Archit Taneja <architt@codeaurora.org> Link: http://patchwork.freedesktop.org/patch/msgid/20170303172007.26541-10-laurent.pinchart+renesas@ideasonboard.com
-rw-r--r--drivers/gpu/drm/bridge/dw-hdmi.c109
-rw-r--r--include/drm/bridge/dw_hdmi.h1
2 files changed, 59 insertions, 51 deletions
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 132c00685796..026a0dce7661 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -19,6 +19,7 @@
19#include <linux/hdmi.h> 19#include <linux/hdmi.h>
20#include <linux/mutex.h> 20#include <linux/mutex.h>
21#include <linux/of_device.h> 21#include <linux/of_device.h>
22#include <linux/regmap.h>
22#include <linux/spinlock.h> 23#include <linux/spinlock.h>
23 24
24#include <drm/drm_of.h> 25#include <drm/drm_of.h>
@@ -171,8 +172,8 @@ struct dw_hdmi {
171 unsigned int audio_n; 172 unsigned int audio_n;
172 bool audio_enable; 173 bool audio_enable;
173 174
174 void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); 175 unsigned int reg_shift;
175 u8 (*read)(struct dw_hdmi *hdmi, int offset); 176 struct regmap *regm;
176}; 177};
177 178
178#define HDMI_IH_PHY_STAT0_RX_SENSE \ 179#define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -183,42 +184,23 @@ struct dw_hdmi {
183 (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \ 184 (HDMI_PHY_RX_SENSE0 | HDMI_PHY_RX_SENSE1 | \
184 HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3) 185 HDMI_PHY_RX_SENSE2 | HDMI_PHY_RX_SENSE3)
185 186
186static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
187{
188 writel(val, hdmi->regs + (offset << 2));
189}
190
191static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
192{
193 return readl(hdmi->regs + (offset << 2));
194}
195
196static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
197{
198 writeb(val, hdmi->regs + offset);
199}
200
201static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
202{
203 return readb(hdmi->regs + offset);
204}
205
206static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) 187static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
207{ 188{
208 hdmi->write(hdmi, val, offset); 189 regmap_write(hdmi->regm, offset << hdmi->reg_shift, val);
209} 190}
210 191
211static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) 192static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
212{ 193{
213 return hdmi->read(hdmi, offset); 194 unsigned int val = 0;
195
196 regmap_read(hdmi->regm, offset << hdmi->reg_shift, &val);
197
198 return val;
214} 199}
215 200
216static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) 201static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
217{ 202{
218 u8 val = hdmi_readb(hdmi, reg) & ~mask; 203 regmap_update_bits(hdmi->regm, reg << hdmi->reg_shift, mask, data);
219
220 val |= data & mask;
221 hdmi_writeb(hdmi, val, reg);
222} 204}
223 205
224static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, 206static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg,
@@ -1989,6 +1971,20 @@ static int dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
1989 return -ENODEV; 1971 return -ENODEV;
1990} 1972}
1991 1973
1974static const struct regmap_config hdmi_regmap_8bit_config = {
1975 .reg_bits = 32,
1976 .val_bits = 8,
1977 .reg_stride = 1,
1978 .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR,
1979};
1980
1981static const struct regmap_config hdmi_regmap_32bit_config = {
1982 .reg_bits = 32,
1983 .val_bits = 32,
1984 .reg_stride = 4,
1985 .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2,
1986};
1987
1992static struct dw_hdmi * 1988static struct dw_hdmi *
1993__dw_hdmi_probe(struct platform_device *pdev, 1989__dw_hdmi_probe(struct platform_device *pdev,
1994 const struct dw_hdmi_plat_data *plat_data) 1990 const struct dw_hdmi_plat_data *plat_data)
@@ -1998,7 +1994,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
1998 struct platform_device_info pdevinfo; 1994 struct platform_device_info pdevinfo;
1999 struct device_node *ddc_node; 1995 struct device_node *ddc_node;
2000 struct dw_hdmi *hdmi; 1996 struct dw_hdmi *hdmi;
2001 struct resource *iores; 1997 struct resource *iores = NULL;
2002 int irq; 1998 int irq;
2003 int ret; 1999 int ret;
2004 u32 val = 1; 2000 u32 val = 1;
@@ -2022,22 +2018,6 @@ __dw_hdmi_probe(struct platform_device *pdev,
2022 mutex_init(&hdmi->audio_mutex); 2018 mutex_init(&hdmi->audio_mutex);
2023 spin_lock_init(&hdmi->audio_lock); 2019 spin_lock_init(&hdmi->audio_lock);
2024 2020
2025 of_property_read_u32(np, "reg-io-width", &val);
2026
2027 switch (val) {
2028 case 4:
2029 hdmi->write = dw_hdmi_writel;
2030 hdmi->read = dw_hdmi_readl;
2031 break;
2032 case 1:
2033 hdmi->write = dw_hdmi_writeb;
2034 hdmi->read = dw_hdmi_readb;
2035 break;
2036 default:
2037 dev_err(dev, "reg-io-width must be 1 or 4\n");
2038 return ERR_PTR(-EINVAL);
2039 }
2040
2041 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); 2021 ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
2042 if (ddc_node) { 2022 if (ddc_node) {
2043 hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); 2023 hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
@@ -2051,11 +2031,38 @@ __dw_hdmi_probe(struct platform_device *pdev,
2051 dev_dbg(hdmi->dev, "no ddc property found\n"); 2031 dev_dbg(hdmi->dev, "no ddc property found\n");
2052 } 2032 }
2053 2033
2054 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2034 if (!plat_data->regm) {
2055 hdmi->regs = devm_ioremap_resource(dev, iores); 2035 const struct regmap_config *reg_config;
2056 if (IS_ERR(hdmi->regs)) { 2036
2057 ret = PTR_ERR(hdmi->regs); 2037 of_property_read_u32(np, "reg-io-width", &val);
2058 goto err_res; 2038 switch (val) {
2039 case 4:
2040 reg_config = &hdmi_regmap_32bit_config;
2041 hdmi->reg_shift = 2;
2042 break;
2043 case 1:
2044 reg_config = &hdmi_regmap_8bit_config;
2045 break;
2046 default:
2047 dev_err(dev, "reg-io-width must be 1 or 4\n");
2048 return ERR_PTR(-EINVAL);
2049 }
2050
2051 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2052 hdmi->regs = devm_ioremap_resource(dev, iores);
2053 if (IS_ERR(hdmi->regs)) {
2054 ret = PTR_ERR(hdmi->regs);
2055 goto err_res;
2056 }
2057
2058 hdmi->regm = devm_regmap_init_mmio(dev, hdmi->regs, reg_config);
2059 if (IS_ERR(hdmi->regm)) {
2060 dev_err(dev, "Failed to configure regmap\n");
2061 ret = PTR_ERR(hdmi->regm);
2062 goto err_res;
2063 }
2064 } else {
2065 hdmi->regm = plat_data->regm;
2059 } 2066 }
2060 2067
2061 hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); 2068 hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
@@ -2165,7 +2172,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
2165 config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID); 2172 config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
2166 config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); 2173 config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID);
2167 2174
2168 if (config3 & HDMI_CONFIG3_AHBAUDDMA) { 2175 if (iores && config3 & HDMI_CONFIG3_AHBAUDDMA) {
2169 struct dw_hdmi_audio_data audio; 2176 struct dw_hdmi_audio_data audio;
2170 2177
2171 audio.phys = iores->start; 2178 audio.phys = iores->start;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 545f04fae3b6..bcceee8114a4 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -59,6 +59,7 @@ struct dw_hdmi_phy_ops {
59}; 59};
60 60
61struct dw_hdmi_plat_data { 61struct dw_hdmi_plat_data {
62 struct regmap *regm;
62 enum drm_mode_status (*mode_valid)(struct drm_connector *connector, 63 enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
63 struct drm_display_mode *mode); 64 struct drm_display_mode *mode);
64 65