[PATCH v1 1/2] drm/i2c: tda998x: access chip registers via a regmap

Russell King - ARM Linux admin linux at armlinux.org.uk
Fri Jun 21 22:06:20 UTC 2019


On Fri, Jun 21, 2019 at 05:13:33PM -0400, Sven Van Asbroeck wrote:
> On Fri, Jun 21, 2019 at 11:15 AM Russell King - ARM Linux admin
> <linux at armlinux.org.uk> wrote:
> >
> > Another con is the need to keep the functions that detail the register
> > properties up to date, which if they're wrong may result in unexpected
> > behaviour.
> >
> > I subscribe to the "keep it simple" approach, and regmap, although
> > useful, seems like a giant sledgehammer for this.
> >
> 
> Thank you for the review !
> 
> I added this back when I was debugging audio artifacts related to this
> chip. The regmap's debugfs binding was extremely useful. So I
> dressed it up a bit in the hope that it would have some general use.
> 
> But if the cons outweigh the pros, then this is as far as this patch
> will go...

I won't disagree that debugfs access to the registers is useful,
especially as I keep this patch locally for that exact purpose:

8<===
From: Russell King <rmk+kernel at armlinux.org.uk>
Subject: [PATCH] drm/i2c: tda998x: debugfs register access

Add support for dumping the register contents via debugfs, with a
mechanism to write to the TDA998x registers to allow experimentation.

Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 114 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 5312fde8b624..6ad1fd1d28a5 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -16,10 +16,13 @@
  */
 
 #include <linux/component.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
 #include <linux/gpio/consumer.h>
 #include <linux/hdmi.h>
 #include <linux/module.h>
 #include <linux/platform_data/tda9950.h>
+#include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <sound/asoundef.h>
 #include <sound/hdmi-codec.h>
@@ -1239,6 +1242,116 @@ static int tda998x_audio_codec_init(struct tda998x_priv *priv,
 }
 
 /* DRM connector functions */
+static u8 tda998x_debugfs_pages[] = {
+	0x00, 0x01, 0x02, 0x09, 0x10, 0x11, 0x12, 0x13
+};
+
+static void *tda998x_regs_start(struct seq_file *s, loff_t *pos)
+{
+	return *pos < ARRAY_SIZE(tda998x_debugfs_pages) ? pos : NULL;
+}
+
+static void *tda998x_regs_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return *pos < ARRAY_SIZE(tda998x_debugfs_pages) ? pos : NULL;
+}
+
+static void tda998x_regs_stop(struct seq_file *s, void *v)
+{
+}
+
+static int tda998x_regs_show(struct seq_file *s, void *v)
+{
+	struct tda998x_priv *priv = s->private;
+	u8 page = tda998x_debugfs_pages[*(loff_t *)v];
+	unsigned int i, j;
+	u8 buf[16];
+
+	seq_printf(s, "==================== page %02x ======================\n", page);
+	seq_printf(s, "     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
+	for (i = 0; i < 256; i += sizeof(buf)) {
+		reg_read_range(priv, REG(page, i), buf, sizeof(buf));
+
+		seq_printf(s, "%02x:", i);
+		for (j = 0; j < sizeof(buf); j++)
+			seq_printf(s, " %02x", buf[j]);
+		seq_printf(s, " : ");
+		for (j = 0; j < sizeof(buf); j++)
+			seq_printf(s, "%c",
+				   isascii(buf[j]) && isprint(buf[j]) ?
+				   buf[j] : '.');
+		seq_putc(s, '\n');
+	}
+	return 0;
+}
+
+static const struct seq_operations tda998x_regs_sops = {
+	.start	= tda998x_regs_start,
+	.next	= tda998x_regs_next,
+	.stop	= tda998x_regs_stop,
+	.show	= tda998x_regs_show,
+};
+
+static int tda998x_regs_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &tda998x_regs_sops);
+	if (ret < 0)
+		return ret;
+
+	((struct seq_file *)file->private_data)->private = inode->i_private;
+
+	return 0;
+}
+
+static ssize_t tda998x_regs_write(struct file *file, const char __user *buf,
+				  size_t count, loff_t *offset)
+{
+	struct tda998x_priv *priv =
+		((struct seq_file *)file->private_data)->private;
+	unsigned int page, addr, mask, val;
+	unsigned char rval;
+	char buffer[16];
+
+	memset(buffer, 0, sizeof(buffer));
+	if (count > sizeof(buffer) - 1)
+		count = sizeof(buffer) - 1;
+	if (copy_from_user(buffer, buf, count))
+		return -EFAULT;
+
+	if (sscanf(buffer, "%x %x %x %x", &page, &addr, &mask, &val) != 4)
+		return -EINVAL;
+	if (page > 0xff || addr > 0xff || mask > 0xff || val > 0xff)
+		return -ERANGE;
+
+	rval = reg_read(priv, REG(page, addr));
+	rval &= ~mask;
+	rval |= val & mask;
+	reg_write(priv, REG(page, addr), rval);
+
+	printk("i2c write %02x @ page:%02x address:%02x\n", rval, page, addr);
+
+	return count;
+}
+
+static const struct file_operations tda998x_regs_fops = {
+	.owner = THIS_MODULE,
+	.open = tda998x_regs_open,
+	.read = seq_read,
+	.write = tda998x_regs_write,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static int tda998x_late_register(struct drm_connector *connector)
+{
+	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+
+	debugfs_create_file("tda998x-regs", 0600, connector->debugfs_entry,
+			    priv, &tda998x_regs_fops);
+
+	return 0;
+}
 
 static enum drm_connector_status
 tda998x_connector_detect(struct drm_connector *connector, bool force)
@@ -1259,6 +1372,7 @@ static const struct drm_connector_funcs tda998x_connector_funcs = {
 	.reset = drm_atomic_helper_connector_reset,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.detect = tda998x_connector_detect,
+	.late_register = tda998x_late_register,
 	.destroy = tda998x_connector_destroy,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-- 
2.7.4


-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up


More information about the dri-devel mailing list