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 + * + * Based on wm8775 driver + * + * Copyright (C) 2004 Ulf Eklund + * Copyright (C) 2005 Hans Verkuil + * - 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 +#include +#include +#include +#include +#include +#include +#include + +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 +#include +#include + +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");