RK系列(RK3568) tda7313音频 i2c驱动

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信号

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hmbbPdx_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值