* [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).