Skip to content

Commit

Permalink
Merge remote-tracking branches 'asoc/topic/qcom', 'asoc/topic/rcar', …
Browse files Browse the repository at this point in the history
…'asoc/topic/rt286' and 'asoc/topic/rt5640' into asoc-next
  • Loading branch information
Mark Brown committed Jun 22, 2015
5 parents 861fe71 + bdb052e + 8a4e379 + bc08f96 + b895dc2 commit 71d8c2d
Showing 18 changed files with 1,010 additions and 575 deletions.
60 changes: 60 additions & 0 deletions Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
* Qualcomm Technologies APQ8016 SBC ASoC machine driver

This node models the Qualcomm Technologies APQ8016 SBC ASoC machine driver

Required properties:

- compatible : "qcom,apq8016-sbc-sndcard"

- pinctrl-N : One property must exist for each entry in
pinctrl-names. See ../pinctrl/pinctrl-bindings.txt
for details of the property values.
- pinctrl-names : Must contain a "default" entry.
- reg : Must contain an address for each entry in reg-names.
- reg-names : A list which must include the following entries:
* "mic-iomux"
* "spkr-iomux"
- qcom,model : Name of the sound card.

Dai-link subnode properties and subnodes:

Required dai-link subnodes:

- cpu : CPU sub-node
- codec : CODEC sub-node

Required CPU/CODEC subnodes properties:

-link-name : Name of the dai link.
-sound-dai : phandle and port of CPU/CODEC
-capture-dai : phandle and port of CPU/CODEC

Example:

sound: sound {
compatible = "qcom,apq8016-sbc-sndcard";
reg = <0x07702000 0x4>, <0x07702004 0x4>;
reg-names = "mic-iomux", "spkr-iomux";
qcom,model = "DB410c";

/* I2S - Internal codec */
internal-dai-link@0 {
cpu { /* PRIMARY */
sound-dai = <&lpass MI2S_PRIMARY>;
};
codec {
sound-dai = <&wcd_codec 0>;
};
};

/* External Primary or External Secondary -ADV7533 HDMI */
external-dai-link@0 {
link-name = "ADV7533";
cpu { /* QUAT */
sound-dai = <&lpass MI2S_QUATERNARY>;
};
codec {
sound-dai = <&adv_bridge 0>;
};
};
};
5 changes: 5 additions & 0 deletions sound/soc/codecs/Kconfig
Original file line number Diff line number Diff line change
@@ -509,6 +509,11 @@ config SND_SOC_RL6231
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m

config SND_SOC_RL6347A
tristate
default y if SND_SOC_RT286=y
default m if SND_SOC_RT286=m

config SND_SOC_RT286
tristate
depends on I2C
2 changes: 2 additions & 0 deletions sound/soc/codecs/Makefile
Original file line number Diff line number Diff line change
@@ -77,6 +77,7 @@ snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rl6231-objs := rl6231.o
snd-soc-rl6347a-objs := rl6347a.o
snd-soc-rt286-objs := rt286.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o
@@ -263,6 +264,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o
obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
128 changes: 128 additions & 0 deletions sound/soc/codecs/rl6347a.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* rl6347a.c - RL6347A class device shared support
*
* Copyright 2015 Realtek Semiconductor Corp.
*
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/jack.h>
#include <linux/workqueue.h>
#include <sound/hda_verbs.h>

#include "rl6347a.h"

int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value)
{
struct i2c_client *client = context;
struct rl6347a_priv *rl6347a = i2c_get_clientdata(client);
u8 data[4];
int ret, i;

/* handle index registers */
if (reg <= 0xff) {
rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
for (i = 0; i < rl6347a->index_cache_size; i++) {
if (reg == rl6347a->index_cache[i].reg) {
rl6347a->index_cache[i].def = value;
break;
}

}
reg = RL6347A_PROC_COEF;
}

data[0] = (reg >> 24) & 0xff;
data[1] = (reg >> 16) & 0xff;
/*
* 4 bit VID: reg should be 0
* 12 bit VID: value should be 0
* So we use an OR operator to handle it rather than use if condition.
*/
data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
data[3] = value & 0xff;

ret = i2c_master_send(client, data, 4);

if (ret == 4)
return 0;
else
pr_err("ret=%d\n", ret);
if (ret < 0)
return ret;
else
return -EIO;
}
EXPORT_SYMBOL_GPL(rl6347a_hw_write);

int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value)
{
struct i2c_client *client = context;
struct i2c_msg xfer[2];
int ret;
__be32 be_reg;
unsigned int index, vid, buf = 0x0;

/* handle index registers */
if (reg <= 0xff) {
rl6347a_hw_write(client, RL6347A_COEF_INDEX, reg);
reg = RL6347A_PROC_COEF;
}

reg = reg | 0x80000;
vid = (reg >> 8) & 0xfff;

if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
index = (reg >> 8) & 0xf;
reg = (reg & ~0xf0f) | index;
}
be_reg = cpu_to_be32(reg);

/* Write register */
xfer[0].addr = client->addr;
xfer[0].flags = 0;
xfer[0].len = 4;
xfer[0].buf = (u8 *)&be_reg;

/* Read data */
xfer[1].addr = client->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = 4;
xfer[1].buf = (u8 *)&buf;

ret = i2c_transfer(client->adapter, xfer, 2);
if (ret < 0)
return ret;
else if (ret != 2)
return -EIO;

*value = be32_to_cpu(buf);

return 0;
}
EXPORT_SYMBOL_GPL(rl6347a_hw_read);

MODULE_DESCRIPTION("RL6347A class device shared support");
MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
MODULE_LICENSE("GPL v2");
32 changes: 32 additions & 0 deletions sound/soc/codecs/rl6347a.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* rl6347a.h - RL6347A class device shared support
*
* Copyright 2015 Realtek Semiconductor Corp.
*
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __RL6347A_H__
#define __RL6347A_H__

#define VERB_CMD(V, N, D) ((N << 20) | (V << 8) | D)

#define RL6347A_VENDOR_REGISTERS 0x20

#define RL6347A_COEF_INDEX\
VERB_CMD(AC_VERB_SET_COEF_INDEX, RL6347A_VENDOR_REGISTERS, 0)
#define RL6347A_PROC_COEF\
VERB_CMD(AC_VERB_SET_PROC_COEF, RL6347A_VENDOR_REGISTERS, 0)

struct rl6347a_priv {
struct reg_default *index_cache;
int index_cache_size;
};

int rl6347a_hw_write(void *context, unsigned int reg, unsigned int value);
int rl6347a_hw_read(void *context, unsigned int reg, unsigned int *value);

#endif /* __RL6347A_H__ */
97 changes: 6 additions & 91 deletions sound/soc/codecs/rt286.c
Original file line number Diff line number Diff line change
@@ -31,12 +31,15 @@
#include <sound/rt286.h>
#include <sound/hda_verbs.h>

#include "rl6347a.h"
#include "rt286.h"

#define RT286_VENDOR_ID 0x10ec0286
#define RT288_VENDOR_ID 0x10ec0288

struct rt286_priv {
struct reg_default *index_cache;
int index_cache_size;
struct regmap *regmap;
struct snd_soc_codec *codec;
struct rt286_platform_data pdata;
@@ -45,7 +48,6 @@ struct rt286_priv {
struct delayed_work jack_detect_work;
int sys_clk;
int clk_id;
struct reg_default *index_cache;
};

static struct reg_default rt286_index_def[] = {
@@ -185,94 +187,6 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg)
}
}

static int rt286_hw_write(void *context, unsigned int reg, unsigned int value)
{
struct i2c_client *client = context;
struct rt286_priv *rt286 = i2c_get_clientdata(client);
u8 data[4];
int ret, i;

/* handle index registers */
if (reg <= 0xff) {
rt286_hw_write(client, RT286_COEF_INDEX, reg);
for (i = 0; i < INDEX_CACHE_SIZE; i++) {
if (reg == rt286->index_cache[i].reg) {
rt286->index_cache[i].def = value;
break;
}

}
reg = RT286_PROC_COEF;
}

data[0] = (reg >> 24) & 0xff;
data[1] = (reg >> 16) & 0xff;
/*
* 4 bit VID: reg should be 0
* 12 bit VID: value should be 0
* So we use an OR operator to handle it rather than use if condition.
*/
data[2] = ((reg >> 8) & 0xff) | ((value >> 8) & 0xff);
data[3] = value & 0xff;

ret = i2c_master_send(client, data, 4);

if (ret == 4)
return 0;
else
pr_err("ret=%d\n", ret);
if (ret < 0)
return ret;
else
return -EIO;
}

static int rt286_hw_read(void *context, unsigned int reg, unsigned int *value)
{
struct i2c_client *client = context;
struct i2c_msg xfer[2];
int ret;
__be32 be_reg;
unsigned int index, vid, buf = 0x0;

/* handle index registers */
if (reg <= 0xff) {
rt286_hw_write(client, RT286_COEF_INDEX, reg);
reg = RT286_PROC_COEF;
}

reg = reg | 0x80000;
vid = (reg >> 8) & 0xfff;

if (AC_VERB_GET_AMP_GAIN_MUTE == (vid & 0xf00)) {
index = (reg >> 8) & 0xf;
reg = (reg & ~0xf0f) | index;
}
be_reg = cpu_to_be32(reg);

/* Write register */
xfer[0].addr = client->addr;
xfer[0].flags = 0;
xfer[0].len = 4;
xfer[0].buf = (u8 *)&be_reg;

/* Read data */
xfer[1].addr = client->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = 4;
xfer[1].buf = (u8 *)&buf;

ret = i2c_transfer(client->adapter, xfer, 2);
if (ret < 0)
return ret;
else if (ret != 2)
return -EIO;

*value = be32_to_cpu(buf);

return 0;
}

#ifdef CONFIG_PM
static void rt286_index_sync(struct snd_soc_codec *codec)
{
@@ -1174,8 +1088,8 @@ static const struct regmap_config rt286_regmap = {
.max_register = 0x02370100,
.volatile_reg = rt286_volatile_register,
.readable_reg = rt286_readable_register,
.reg_write = rt286_hw_write,
.reg_read = rt286_hw_read,
.reg_write = rl6347a_hw_write,
.reg_read = rl6347a_hw_read,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt286_reg,
.num_reg_defaults = ARRAY_SIZE(rt286_reg),
@@ -1248,6 +1162,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
}

rt286->index_cache = rt286_index_def;
rt286->index_cache_size = INDEX_CACHE_SIZE;
rt286->i2c = i2c;
i2c_set_clientdata(i2c, rt286);

Loading

0 comments on commit 71d8c2d

Please sign in to comment.