tda7313是一款立体声音频处理器件,支持3路输入通道和i2c串行总线支持。
I2C命令:

我们可以看到该芯片i2c命令是由 start信号+地址+ N个DATA + STOP信号组成
DATA:
例1.Volume control -45db组成是:00100100

例2.Audio switch stereo2(输入端口2) LOUDNESS ON +7.5db组成是:01001001

由于我得板子是i2s1接 RK809 ,输出spkout接 tda7313的 L1 R1
i2s1接 RK809的spkout 可以参考官方的
记得屏蔽ucart3 ucart5不然跟i2s1会冲突
Linux i2C driver:
tda7313挂载在i2c5下,地址为0x88 但是i2c只支持7bit的地址所以要右移一位得0x44
设备树描述:
#if 1
&i2c5 {
status = "okay";
tda7313: tda7313@44 {
status = "okay";
compatible = "st,tda7313";
reg = <0x44>;
tda7313pwr-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
pwr2-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_LOW>;
#sound-dai-cells = <0>;
};
};
#endif
tda7313pwr-gpios是板子上得电源引脚,没有得话可以不写
测试驱动代码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/uaccess.h>
#include <linux/delay.h> // mdelay()
#define MYMA 300
#define COUNT 1
static struct device_node *work_device_node;
static int gpio_0;
static int gpio_1;
static int gpio_fm;
static int value = 0;
static int bassvalue = 0;
static int audioSwitch = 0;
#define VOLUME_2BIT 0
#define AUDIO_SWITCH_3BIT 2
#define SPEAKER_LF_3BIT 4
#define SPEAKER_RF_3BIT 5
#define SPEAKER_LR_3BIT 6
#define SPEAKER_RR_3BIT 7
#define STEREO_1 0
#define STEREO_2 1
#define STEREO_3 2
#define STEREO_ALL 3
#define STEREO_VALUE STEREO_2
#define BASS_4BIT 6
#define TEBLE_4BIT 7
#define OFFSET_3BIT 5
#define OFFSET_4BIT 4
#define LOUDNESS 0 // 0x4
typedef struct
{
struct mutex mutex;
struct cdev cdev;
struct i2c_client *cli;
struct class *cls;
} dht12_data_t;
struct file_operations fops = {
.owner = THIS_MODULE,
};
int myprobe(struct i2c_client *cli, const struct i2c_device_id *id)
{
struct device_node *np;
struct device *dev;
static int mi = 0; // 记录次设备号
dht12_data_t *data;
dev_t devid;
int ret;
// 注册设备号
devid = MKDEV(MYMA, mi);
ret = register_chrdev_region(devid, COUNT, cli->name);
if (ret < 0)
goto err0;
// 准备每个匹配设备的数据
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (NULL == data)
{
ret = -ENOMEM;
goto err1;
}
// 字符设备初始化
cdev_init(&data->cdev, &fops);
data->cdev.owner = THIS_MODULE;
ret = cdev_add(&data->cdev, devid, COUNT);
if (ret < 0)
goto err2;
// 初始化互斥锁
mutex_init(&data->mutex);
// 创建设备文件
data->cls = class_create(THIS_MODULE, cli->name);
device_create(data->cls, NULL, devid, NULL, "%s.%d", cli->name, mi++);
data->cli = cli;
i2c_set_clientdata(cli, data);
dev = &cli->dev;
if (!dev)
return -ENODEV;
np = dev->of_node;
gpio_0 = of_get_named_gpio(np, "tda7313pwr-gpios", 0);
if (gpio_0 < 0)
{
printk("0 of_get_namd_gpio is error \n");
return -1;
}
gpio_1 = of_get_named_gpio(np, "pwr2-gpios", 0);
if (gpio_1 < 0)
{
printk("1 of_get_namd_gpio is error \n");
return -1;
}
gpio_fm = of_get_named_gpio(np, "fm-gpios", 0);
if (gpio_fm < 0)
{
printk("fm of_get_namd_gpio is error \n");
return -1;
}
gpio_direction_output(gpio_0, 1);
gpio_direction_output(gpio_1, 1);
gpio_direction_output(gpio_fm, 1);
mdelay(100);
struct i2c_msg msgs[2];
char data_rcv[5], addr[2] = {0x24 , // volue -45db
0x48, // .Audio switch stereo1(输入端口2) LOUDNESS ON +7.5db组成是:01001001
}
// 上锁,防止重入
mutex_lock(&data->mutex);
msgs[0].addr = cli->addr;
msgs[0].flags = 0;
msgs[0].len = 2;
msgs[0].buf = addr;
ret = i2c_transfer(cli->adapter, msgs, 1);
if (ret != 1)
{
printk("error %d\n", ret);
// goto out;
}
printk("ret %d\n", ret);
mutex_unlock(&data->mutex);
printk("myprobe--------------------------------------------------------------n\n");
return 0;
err2:
kfree(data);
err1:
unregister_chrdev_region(devid, COUNT);
err0:
return ret;
}
int myremove(struct i2c_client *cli)
{
dht12_data_t *data = i2c_get_clientdata(cli); // dev_get_drvdata(&cli->dev);
// 移除设备文件
device_destroy(data->cls, data->cdev.dev);
class_destroy(data->cls);
cdev_del(&data->cdev);
unregister_chrdev_region(data->cdev.dev, COUNT);
kfree(data);
return 0;
}
struct i2c_device_id ids[] = {
{"st,tda7313", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, ids);
static const struct of_device_id tda7313_of_match[] = {
{.compatible = "st,tda7313"},
{},
};
struct i2c_driver mydrv = {
.probe = myprobe,
.remove = myremove,
.driver = {
.name = "tda7313",
.of_match_table = tda7313_of_match,
.owner = THIS_MODULE,
},
.id_table = ids,
};
module_i2c_driver(mydrv);
MODULE_LICENSE("GPL");
struct i2c_msg msgs[2];
char data_rcv[5], addr[2] = {0x24 , // volue -45db
0x4a, // .Audio switch stereo2(输入端口2) LOUDNESS ON +7.5db组成是:01001001
}
msgs[0].addr = cli->addr;//设备地址
msgs[0].flags = 0;//0为写
msgs[0].len = 2;//2个DATA数据
msgs[0].buf = addr;//DATA数据地址
ret = i2c_transfer(cli->adapter, msgs, 1) 执行一次会发出start信号+设备地址+len个数据+stop信号