linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] new driver for TLV320AIC23B
@ 2006-05-10 21:55 Scott Alfter
  2006-05-10 22:32 ` Alexey Dobriyan
  2006-05-10 22:42 ` [v4l-dvb-maintainer] " Hans Verkuil
  0 siblings, 2 replies; 4+ messages in thread
From: Scott Alfter @ 2006-05-10 21:55 UTC (permalink / raw)
  To: v4l-dvb-maintainer; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 635 bytes --]

Signed-off-by: Scott Alfter <salfter@ssai.us>

It took a little bit longer than I thought, but the attached patch adds a
driver for the TI TLV320AIC23B audio codec.  It implements analog audio capture
at 32, 44.1, and 48 kHz (16-bit stereo).  The hardware is capable of more (it
supports more sample rates and includes analog output), but in its current
form, the driver works well with ivtv.

The patch is attached; a test mailing indicated that Thunderbird attaches
patches inline instead of encoded.  The patch is also available from this URL:

http://alfter.us/files/linux-2.6.16-tlv320aic23b.patch

Scott Alfter
salfter@ssai.us



[-- Attachment #2: linux-2.6.16-tlv320aic23b.patch --]
[-- Type: text/plain, Size: 9611 bytes --]

diff -Nupr -X dontdiff linux-2.6.16-gentoo-r1/drivers/media/video/Makefile linux-2.6.16-gentoo-r1/drivers/media/video/Makefile
--- linux-2.6.16-gentoo-r1/drivers/media/video/Makefile	2006-03-19 21:53:29.000000000 -0800
+++ linux-2.6.16-gentoo-r1/drivers/media/video/Makefile	2006-04-25 15:37:58.000000000 -0700
@@ -45,7 +45,7 @@ obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2
 obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_EM28XX) += saa711x.o tvp5150.o
-obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o
+obj-$(CONFIG_VIDEO_AUDIO_DECODER) += wm8775.o cs53l32a.o tlv320aic23b.o
 obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
 obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
diff -Nupr -X dontdiff linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.c linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.c
--- linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.c	2006-05-09 17:19:00.000000000 -0700
@@ -0,0 +1,248 @@
+/*
+ * tlv320aic23b - driver version 0.0.1
+ *
+ * Copyright (C) 2006 Scott Alfter <salfter@ssai.us>
+ *
+ * Based on wm8775 driver
+ *
+ * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ * - Cleanup
+ * - V4L2 API update
+ * - sound fixes
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("tlv320aic23b driver");
+MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+
+enum {
+	R7 = 7, R11 = 11,
+	R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R23 = 23,
+	TOT_REGS
+};
+
+struct tlv320aic23b_state {
+	u8 input;		/* Last selected input (0-0xf) */
+	u8 muted;
+};
+
+static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val)
+{
+	int i;
+
+	if ((reg < 0 || reg >9)&&(reg!=15)) {
+		v4l_err(client, "Invalid register R%d\n", reg);
+		return -1;
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (i2c_smbus_write_byte_data(client, (reg << 1) |
+					(val >> 8), val & 0xff) == 0) {
+			return 0;
+		}
+	}
+	v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+	return -1;
+}
+
+static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd,
+			  void *arg)
+{
+	struct tlv320aic23b_state *state = i2c_get_clientdata(client);
+	struct v4l2_audio *input = arg;
+	struct v4l2_control *ctrl = arg;
+	u32* freq=arg;
+
+	switch (cmd) {
+	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+		// TODO: set sample rate according to arg, which is an unsigned int
+		// with the sample rate: 32000, 44100, or 48000 Hz
+		switch (*freq)
+		{
+			case 32000:
+				tlv320aic23b_write(client, 8, 0x018); /* set sample rate to 32 kHz */
+				break;
+			case 44100:
+				tlv320aic23b_write(client, 8, 0x022); /* set sample rate to 44.1 kHz */
+				break;
+			case 48000:
+				tlv320aic23b_write(client, 8, 0x000); /* set sample rate to 48 kHz */
+				break;
+		}
+		break;
+	case VIDIOC_S_AUDIO:
+		
+		/* With only one line-level input, the input value can be ignored */
+		if (state->muted)
+			break;
+		tlv320aic23b_write(client, 0, 0x119); // set gain on both channels to +3.0 dB
+		break;
+
+	case VIDIOC_G_AUDIO:
+		break;
+
+	case VIDIOC_G_CTRL:
+		if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+			return -EINVAL;
+		ctrl->value = state->muted;
+		break;
+
+	case VIDIOC_S_CTRL:
+		if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+			return -EINVAL;
+		state->muted = ctrl->value;
+		tlv320aic23b_write(client, 0, 0x180); // mute both channels
+		if (!state->muted)
+			tlv320aic23b_write(client, 0, 0x119); // set gain on both channels to +3.0 dB
+		break;
+
+	case VIDIOC_LOG_STATUS:
+		v4l_info(client, "Input: %d%s\n", state->input,
+			    state->muted ? " (muted)" : "");
+		break;
+
+	case VIDIOC_S_FREQUENCY:
+		/* If I remove this, then it can happen that I have no
+		   sound the first time I tune from static to a valid channel.
+		   It's difficult to reproduce and is almost certainly related
+		   to the zero cross detect circuit. */
+		/* original looks like a dupe of VIDIOC_S_AUDIO */
+		tlv320aic23b_write(client, 0, 0x119); // set gain on both channels to +3.0 dB
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static struct i2c_driver i2c_driver;
+
+static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct tlv320aic23b_state *state;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return 0;
+
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (client == 0)
+		return -ENOMEM;
+
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &i2c_driver;
+	snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b");
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+	state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL);
+	if (state == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+	state->input = 2;
+	state->muted = 0;
+	i2c_set_clientdata(client, state);
+
+	/* initialize tlv320aic23b */
+	tlv320aic23b_write(client, 15, 0x000);	/* RESET */
+	tlv320aic23b_write(client, 6, 0x00A); /* turn off DAC & mic input */
+	tlv320aic23b_write(client, 7, 0x049); /* left-justified, 24-bit, master mode */
+	tlv320aic23b_write(client, 0, 0x119); /* set gain on both channels to +3.0 dB */
+	tlv320aic23b_write(client, 8, 0x000); /* set sample rate to 48 kHz */
+	tlv320aic23b_write(client, 9, 0x001); /* activate digital interface */
+	
+	i2c_attach_client(client);
+
+	return 0;
+}
+
+static int tlv320aic23b_probe(struct i2c_adapter *adapter)
+{
+	if (adapter->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adapter, &addr_data, tlv320aic23b_attach);
+	return 0;
+}
+
+static int tlv320aic23b_detach(struct i2c_client *client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+	if (err) {
+		return err;
+	}
+	kfree(client);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+	.driver = {
+		.name = "tlv320aic23b",
+	},
+	.id             = I2C_DRIVERID_TLV320AIC23B,
+	.attach_adapter = tlv320aic23b_probe,
+	.detach_client  = tlv320aic23b_detach,
+	.command        = tlv320aic23b_command,
+};
+
+
+static int __init tlv320aic23b_init_module(void)
+{
+	return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit tlv320aic23b_cleanup_module(void)
+{
+	i2c_del_driver(&i2c_driver);
+}
+
+module_init(tlv320aic23b_init_module);
+module_exit(tlv320aic23b_cleanup_module);
diff -Nupr -X dontdiff linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c
--- linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c	2006-05-08 17:41:44.000000000 -0700
@@ -0,0 +1,44 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+};
+
+static const struct modversion_info ____versions[]
+__attribute_used__
+__attribute__((section("__versions"))) = {
+	{ 0x799c1ddd, "struct_module" },
+	{ 0x2583286b, "i2c_del_driver" },
+	{ 0x181d00ce, "i2c_register_driver" },
+	{ 0xb4e757c0, "i2c_detach_client" },
+	{ 0x81713cdd, "i2c_probe" },
+	{ 0x2a6031cb, "i2c_attach_client" },
+	{ 0x37a0cba, "kfree" },
+	{ 0x16f2559e, "kmem_cache_alloc" },
+	{ 0xb76ba150, "malloc_sizes" },
+	{ 0xaf25400d, "snprintf" },
+	{ 0x5a3b6eca, "kzalloc" },
+	{ 0x9ddcce27, "i2c_smbus_write_byte_data" },
+	{ 0xdd132261, "printk" },
+	{ 0x6483655c, "param_get_short" },
+	{ 0x40046949, "param_set_short" },
+	{ 0x806d5133, "param_array_get" },
+	{ 0x89cef6fb, "param_array_set" },
+};
+
+static const char __module_depends[]
+__attribute_used__
+__attribute__((section(".modinfo"))) =
+"depends=i2c-core";
+
+
+MODULE_INFO(srcversion, "519388420026FA82AF6CAD0");


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] new driver for TLV320AIC23B
  2006-05-10 21:55 [PATCH] new driver for TLV320AIC23B Scott Alfter
@ 2006-05-10 22:32 ` Alexey Dobriyan
  2006-05-10 23:32   ` [v4l-dvb-maintainer] " Johannes Stezenbach
  2006-05-10 22:42 ` [v4l-dvb-maintainer] " Hans Verkuil
  1 sibling, 1 reply; 4+ messages in thread
From: Alexey Dobriyan @ 2006-05-10 22:32 UTC (permalink / raw)
  To: Scott Alfter; +Cc: v4l-dvb-maintainer, linux-kernel

On Wed, May 10, 2006 at 02:55:28PM -0700, Scott Alfter wrote:
>                                                 the attached patch adds a
> driver for the TI TLV320AIC23B audio codec.  It implements analog audio capture
> at 32, 44.1, and 48 kHz (16-bit stereo).  The hardware is capable of more (it
> supports more sample rates and includes analog output), but in its current
> form, the driver works well with ivtv.

> --- linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.c
> +++ linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.c

> +static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind)
> +{
> +	struct i2c_client *client;
> +	struct tlv320aic23b_state *state;
> +
> +	/* Check if the adapter supports the needed features */
> +	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
> +		return 0;
> +
> +	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
> +	if (client == 0)
> +		return -ENOMEM;

client is a pointer, so

	if (client == NULL)

or

	if (!client)

> +	snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b");

	snprintf(buf, sizeof(buf), ...)

is idiomatic.

> +static int tlv320aic23b_detach(struct i2c_client *client)
> +{
> +	int err;
> +
> +	err = i2c_detach_client(client);
> +	if (err) {
> +		return err;
> +	}

Preferred style is

	if (err)
		return err;

> diff -Nupr -X dontdiff linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c

> --- linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c
> +++ linux-2.6.16-gentoo-r1/drivers/media/video/tlv320aic23b.mod.c

This file is generated and you have outdated dontdiff. Use "-X Documentation/dontdiff".


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [v4l-dvb-maintainer] [PATCH] new driver for TLV320AIC23B
  2006-05-10 21:55 [PATCH] new driver for TLV320AIC23B Scott Alfter
  2006-05-10 22:32 ` Alexey Dobriyan
@ 2006-05-10 22:42 ` Hans Verkuil
  1 sibling, 0 replies; 4+ messages in thread
From: Hans Verkuil @ 2006-05-10 22:42 UTC (permalink / raw)
  To: v4l-dvb-maintainer; +Cc: Scott Alfter, linux-kernel

On Wednesday 10 May 2006 23:55, Scott Alfter wrote:
> Signed-off-by: Scott Alfter <salfter@ssai.us>
>
> It took a little bit longer than I thought, but the attached patch
> adds a driver for the TI TLV320AIC23B audio codec.  It implements
> analog audio capture at 32, 44.1, and 48 kHz (16-bit stereo).  The
> hardware is capable of more (it supports more sample rates and
> includes analog output), but in its current form, the driver works
> well with ivtv.
>
> The patch is attached; a test mailing indicated that Thunderbird
> attaches patches inline instead of encoded.  The patch is also
> available from this URL:
>
> http://alfter.us/files/linux-2.6.16-tlv320aic23b.patch
>
> Scott Alfter
> salfter@ssai.us

Hi Scott,

I've taken a quick look and I noticed a few things: first of all I 
recommend making a patch against the v4l-dvb repository as there have 
been a few changes compared to 2.6.16 that are relevant. In particular 
your device should start supporting VIDIOC_INT_G/S_AUDIO_ROUTING 
commands instead of VIDIOC_G/S_AUDIO. See the definition of these 
commands in v4l2-common.h for more info. This also implies that a 
media/tlv320aic23b.h header should be added (look at the existing 
headers such as wm8775.h).

I also noticed what seems to be a superfluous TODO in the 
VIDIOC_INT_AUDIO_CLOCK_FREQ implementation.

The enum (R7, R11, etc) isn't used and can be removed.

The input field of struct tlv320aic23b_state doesn't seem to be used, so 
that too can be removed.

You probably do not have to implement the VIDIOC_S_FREQUENCY command, 
that was wm8775 specific. I doubt it is necessary for this driver.

It is also a good idea to add support for older kernels to this driver 
(again, see the #if lines in the wm8775.c driver).

Hmm, well that seems to be it.

Thanks!

	Hans

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [v4l-dvb-maintainer] Re: [PATCH] new driver for TLV320AIC23B
  2006-05-10 22:32 ` Alexey Dobriyan
@ 2006-05-10 23:32   ` Johannes Stezenbach
  0 siblings, 0 replies; 4+ messages in thread
From: Johannes Stezenbach @ 2006-05-10 23:32 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Scott Alfter, v4l-dvb-maintainer, linux-kernel

On Thu, May 11, 2006 at 02:32:12AM +0400, Alexey Dobriyan wrote:
> On Wed, May 10, 2006 at 02:55:28PM -0700, Scott Alfter wrote:
> 
> > +	snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b");
> 
> 	snprintf(buf, sizeof(buf), ...)
> 
> is idiomatic.

better use strlcpy()

Johannes

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-05-10 23:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-05-10 21:55 [PATCH] new driver for TLV320AIC23B Scott Alfter
2006-05-10 22:32 ` Alexey Dobriyan
2006-05-10 23:32   ` [v4l-dvb-maintainer] " Johannes Stezenbach
2006-05-10 22:42 ` [v4l-dvb-maintainer] " Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).