📄 tda7313.c
字号:
/* Driver for the TDA7313 and PT2313L audio processor chips * * Copyright (c) 2003-2006 Mark McClelland <mark@ovcam.org> * * 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. NO WARRANTY OF ANY KIND is expressed or implied. */#define DRIVER_VERSION "1.00"#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/videodev.h>#include <linux/i2c.h>#include "id.h"#include "audiochip.h"#include "compat.h"#define I2C_TDA7313 0x88/* Addresses to scan */static unsigned short normal_i2c[] = {I2C_TDA7313 >> 1, I2C_CLIENT_END};#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};#endifI2C_CLIENT_INSMOD;MODULE_DESCRIPTION("Driver for the TDA7313 and PT2313L audio processor chips");MODULE_AUTHOR("Mark McClelland <mark@ovcam.org>");MODULE_LICENSE("GPL");struct tda7313 { struct i2c_client c; unsigned char volume; /* Range: 0 - 0x3f */};static struct i2c_driver driver;static struct i2c_client client_template;/* ----------------------------------------------------------------------- */static inttda7313_write(struct i2c_client *c, unsigned char val){ int rc; rc = i2c_smbus_write_byte(c, val); if (rc < 0) printk(KERN_ERR "tda7313: I2C write error\n"); return rc;}static inttda7313_set_volume(struct i2c_client *c, unsigned char val){ struct tda7313 *t = i2c_get_clientdata(c); tda7313_write(c, (~val)&0x3f); t->volume = val; return 0;}static voidtda7313_set_defaults(struct i2c_client *c){ tda7313_set_volume(c, 0); /* Disable attenuation */ tda7313_write(c, 0x80); tda7313_write(c, 0xa0); tda7313_write(c, 0xc0); tda7313_write(c, 0xe0); /* Select input 1, loudness enabled (+0dB) */ tda7313_write(c, 0x40); /* Flat EQ */ tda7313_write(c, 0x6f); tda7313_write(c, 0x7f);}/* ----------------------------------------------------------------------- */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 68)static inttda7313_attach(struct i2c_adapter *adap, int addr, int kind)#elsestatic inttda7313_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)#endif{ struct tda7313 *t; struct i2c_client *c; t = kmalloc(sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; memset(t, 0, sizeof(*t)); c = &t->c; memcpy(c, &client_template, sizeof *c); c->adapter = adap; c->addr = addr; i2c_set_clientdata(c, t); tda7313_set_defaults(c);#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) MOD_INC_USE_COUNT;#endif i2c_attach_client(c); return 0;}static inttda7313_detach(struct i2c_client *c){ struct tda7313 *t = i2c_get_clientdata(c); i2c_detach_client(c); kfree(t);#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) MOD_DEC_USE_COUNT;#endif return 0;}static inttda7313_probe(struct i2c_adapter *adap){ switch (adap->id) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511):#else case (I2C_HW_SMBUS_OV511):#endif printk(KERN_INFO "tda7313: probing %s i2c adapter [id=0x%06x]\n", adap->name, adap->id); return i2c_probe(adap, &addr_data, tda7313_attach); default: printk(KERN_INFO "tda7313: ignoring adapter: %s [0x%06x]\n", adap->name, adap->id); return 0; }}static inttda7313_command(struct i2c_client *c, unsigned int cmd, void *arg){ struct tda7313 *t = i2c_get_clientdata(c); switch (cmd) { case VIDIOCGAUDIO: { struct video_audio *va = arg; printk(KERN_DEBUG "tda7313: VIDIOCGAUDIO\n"); va->flags |= VIDEO_AUDIO_VOLUME; va->volume = t->volume*(65535/0x3f); va->balance = 32768; va->bass = 0x8; va->treble = 0x8; va->mode |= VIDEO_SOUND_MONO; return 0; } case VIDIOCSAUDIO: { struct video_audio *va = arg; printk(KERN_DEBUG "tda7313: VIDIOCSAUDIO\n"); tda7313_set_volume(c, va->volume/(65535/0x3f)); return 0; } default: return -ENOIOCTLCMD; }}/* ----------------------------------------------------------------------- */static struct i2c_driver driver = {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) .owner = THIS_MODULE,# endif .name = "i2c tda7313 driver",#else .driver = { .name = "i2c tda7313 driver", },#endif .id = I2C_DRIVERID_TDA7313,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7) .class = I2C_CLASS_TV_ANALOG, /* FIXME: = I2C_CLASS_SOUND? */#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) .flags = I2C_DF_NOTIFY,#endif .attach_adapter = tda7313_probe, .detach_client = tda7313_detach, .command = tda7313_command,};static struct i2c_client client_template = { .name = "tda7313",#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12) .id = -1,#endif .driver = &driver,};static int __inittda7313_init(void){ return i2c_add_driver(&driver);}static void __exittda7313_exit(void){ i2c_del_driver(&driver);}module_init(tda7313_init);module_exit(tda7313_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -