Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cd9d142 authored by Andy Yan's avatar Andy Yan Committed by Philipp Zabel
Browse files

drm: bridge/dw_hdmi: add support for multi-byte register width access



On rockchip rk3288, only word(32-bit) accesses are
permitted for hdmi registers.  Byte width accesses (writeb,
readb) generate an imprecise external abort.

Signed-off-by: default avatarAndy Yan <andy.yan@rock-chips.com>
Tested-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Acked-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent cd152393
Loading
Loading
Loading
Loading
+42 −2
Original line number Diff line number Diff line
@@ -128,18 +128,41 @@ struct dw_hdmi {

	unsigned int sample_rate;
	int ratio;

	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
	u8 (*read)(struct dw_hdmi *hdmi, int offset);
};

static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
static void dw_hdmi_writel(struct dw_hdmi *hdmi, u8 val, int offset)
{
	writel(val, hdmi->regs + (offset << 2));
}

static u8 dw_hdmi_readl(struct dw_hdmi *hdmi, int offset)
{
	return readl(hdmi->regs + (offset << 2));
}

static void dw_hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
{
	writeb(val, hdmi->regs + offset);
}

static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
static u8 dw_hdmi_readb(struct dw_hdmi *hdmi, int offset)
{
	return readb(hdmi->regs + offset);
}

static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset)
{
	hdmi->write(hdmi, val, offset);
}

static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset)
{
	return hdmi->read(hdmi, offset);
}

static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
{
	u8 val = hdmi_readb(hdmi, reg) & ~mask;
@@ -1511,6 +1534,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
	struct device_node *ddc_node;
	struct dw_hdmi *hdmi;
	int ret;
	u32 val = 1;

	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
	if (!hdmi)
@@ -1523,6 +1547,22 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
	hdmi->ratio = 100;
	hdmi->encoder = encoder;

	of_property_read_u32(np, "reg-io-width", &val);

	switch (val) {
	case 4:
		hdmi->write = dw_hdmi_writel;
		hdmi->read = dw_hdmi_readl;
		break;
	case 1:
		hdmi->write = dw_hdmi_writeb;
		hdmi->read = dw_hdmi_readb;
		break;
	default:
		dev_err(dev, "reg-io-width must be 1 or 4\n");
		return -EINVAL;
	}

	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
	if (ddc_node) {
		hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);