ASoC: wcd9xxx: Add wcd9320 codec slimbus slave support

Update slimbus slave driver to use updated address depending on discovered
The wcd9320 Taiko codec introduced a new register address map to configure
slimbus slave device.

Change-Id: I41e9ebabd1d375a1904b6033e46736b2fb6365f9
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
This commit is contained in:
Joonwoo Park
2012-07-23 16:03:49 -07:00
committed by Stephen Boyd
parent a9f7f0ea55
commit 7ad053abe0
3 changed files with 259 additions and 130 deletions

View File

@@ -246,6 +246,12 @@ static struct mfd_cell sitar_devs[] = {
}, },
}; };
static struct mfd_cell taiko_devs[] = {
{
.name = "taiko_codec",
},
};
static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx) static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
{ {
wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4); wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
@@ -336,13 +342,16 @@ static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
} else if (wcd9xxx->idbyte_0 == 0x1) { } else if (wcd9xxx->idbyte_0 == 0x1) {
wcd9xxx_dev = tabla1x_devs; wcd9xxx_dev = tabla1x_devs;
wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs); wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
} else if (wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
wcd9xxx->idbyte_2 == 0x2 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = taiko_devs;
wcd9xxx_dev_size = ARRAY_SIZE(taiko_devs);
} else if (wcd9xxx->idbyte_0 == 0x0) { } else if (wcd9xxx->idbyte_0 == 0x0) {
wcd9xxx_dev = sitar_devs; wcd9xxx_dev = sitar_devs;
wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs); wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
} }
ret = mfd_add_devices(wcd9xxx->dev, -1, ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
wcd9xxx_dev, wcd9xxx_dev_size, NULL, 0);
NULL, 0);
if (ret != 0) { if (ret != 0) {
dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret); dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
goto err_irq; goto err_irq;
@@ -883,7 +892,9 @@ static int wcd9xxx_slim_probe(struct slim_device *slim)
pr_err("%s: error, initializing device failed\n", __func__); pr_err("%s: error, initializing device failed\n", __func__);
goto err_slim_add; goto err_slim_add;
} }
wcd9xxx_init_slimslave(wcd9xxx, wcd9xxx_pgd_la); wcd9xxx_init_slimslave(wcd9xxx, wcd9xxx_pgd_la);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
debugCodec = wcd9xxx; debugCodec = wcd9xxx;
@@ -1091,6 +1102,23 @@ static struct slim_driver tabla2x_slim_driver = {
.suspend = wcd9xxx_slim_suspend, .suspend = wcd9xxx_slim_suspend,
}; };
static const struct slim_device_id taiko_slimtest_id[] = {
{"taiko-slim", 0},
{}
};
static struct slim_driver taiko_slim_driver = {
.driver = {
.name = "taiko-slim",
.owner = THIS_MODULE,
},
.probe = wcd9xxx_slim_probe,
.remove = wcd9xxx_slim_remove,
.id_table = taiko_slimtest_id,
.resume = wcd9xxx_slim_resume,
.suspend = wcd9xxx_slim_suspend,
};
#define WCD9XXX_I2C_TOP_LEVEL 0 #define WCD9XXX_I2C_TOP_LEVEL 0
#define WCD9XXX_I2C_ANALOG 1 #define WCD9XXX_I2C_ANALOG 1
#define WCD9XXX_I2C_DIGITAL_1 2 #define WCD9XXX_I2C_DIGITAL_1 2
@@ -1119,7 +1147,7 @@ static struct i2c_driver tabla_i2c_driver = {
static int __init wcd9xxx_init(void) static int __init wcd9xxx_init(void)
{ {
int ret1, ret2, ret3, ret4, ret5; int ret1, ret2, ret3, ret4, ret5, ret6;
ret1 = slim_driver_register(&tabla_slim_driver); ret1 = slim_driver_register(&tabla_slim_driver);
if (ret1 != 0) if (ret1 != 0)
@@ -1141,7 +1169,11 @@ static int __init wcd9xxx_init(void)
if (ret5 != 0) if (ret5 != 0)
pr_err("Failed to register sitar SB driver: %d\n", ret5); pr_err("Failed to register sitar SB driver: %d\n", ret5);
return (ret1 && ret2 && ret3 && ret4 && ret5) ? -1 : 0; ret6 = slim_driver_register(&taiko_slim_driver);
if (ret6 != 0)
pr_err("Failed to register taiko SB driver: %d\n", ret6);
return (ret1 && ret2 && ret3 && ret4 && ret5 && ret6) ? -1 : 0;
} }
module_init(wcd9xxx_init); module_init(wcd9xxx_init);

View File

@@ -12,6 +12,9 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h> #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
#define WCD9XXX_CHIP_ID_TAIKO 0x00000201
struct wcd9xxx_slim_sch_rx { struct wcd9xxx_slim_sch_rx {
u32 sph; u32 sph;
@@ -30,37 +33,111 @@ struct wcd9xxx_slim_sch_tx {
struct wcd9xxx_slim_sch { struct wcd9xxx_slim_sch {
struct wcd9xxx_slim_sch_rx rx[SLIM_MAX_RX_PORTS]; struct wcd9xxx_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
struct wcd9xxx_slim_sch_tx tx[SLIM_MAX_TX_PORTS]; struct wcd9xxx_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
u16 rx_port_start_offset;
u16 num_rx_slave_port;
u16 port_ch_0_start_port_id;
u16 port_ch_0_end_port_id;
u16 pgd_tx_port_ch_1_end_port_id;
u16 rx_port_ch_reg_base;
u16 port_tx_cfg_reg_base;
u16 port_rx_cfg_reg_base;
int number_of_tx_slave_dev_ports;
int number_of_rx_slave_dev_ports;
}; };
static struct wcd9xxx_slim_sch sh_ch; static struct wcd9xxx_slim_sch sh_ch;
static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx, static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
u8 wcd9xxx_pgd_la); u8 wcd9xxx_pgd_la);
static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx, static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
u8 wcd9xxx_pgd_la); u8 wcd9xxx_pgd_la);
static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx); static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx);
static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx); static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx);
static int wcd9xxx_configure_ports(struct wcd9xxx *wcd9xxx)
{
int i;
u32 id;
for (i = 0; i < 4; i++)
((u8 *)&id)[i] = wcd9xxx_reg_read(wcd9xxx,
WCD9XXX_A_CHIP_ID_BYTE_0 + i);
id = cpu_to_be32(id);
pr_debug("%s: chip id 0x%08x\n", __func__, id);
if (id != WCD9XXX_CHIP_ID_TAIKO) {
sh_ch.rx_port_start_offset =
TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
sh_ch.num_rx_slave_port =
TABLA_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS;
sh_ch.port_ch_0_start_port_id =
TABLA_SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID;
sh_ch.port_ch_0_end_port_id =
TABLA_SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID;
sh_ch.pgd_tx_port_ch_1_end_port_id =
TABLA_SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID;
sh_ch.rx_port_ch_reg_base =
0x180 + (TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS * 4);
sh_ch.port_rx_cfg_reg_base =
0x040 + (TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS);
sh_ch.port_tx_cfg_reg_base = 0x040;
sh_ch.number_of_tx_slave_dev_ports =
TABLA_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS;
sh_ch.number_of_rx_slave_dev_ports =
TABLA_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS;
} else {
sh_ch.rx_port_start_offset =
TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS;
sh_ch.num_rx_slave_port =
TAIKO_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS;
sh_ch.port_ch_0_start_port_id =
TAIKO_SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID;
sh_ch.port_ch_0_end_port_id =
TAIKO_SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID;
sh_ch.pgd_tx_port_ch_1_end_port_id =
TAIKO_SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID;
sh_ch.rx_port_ch_reg_base = 0x180;
sh_ch.port_rx_cfg_reg_base = 0x040;
sh_ch.port_tx_cfg_reg_base = 0x050;
sh_ch.number_of_tx_slave_dev_ports =
TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS;
sh_ch.number_of_rx_slave_dev_ports =
TAIKO_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS;
}
return 0;
}
int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la) int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la)
{ {
int ret = 0; int ret = 0;
ret = wcd9xxx_configure_ports(wcd9xxx);
if (ret) {
pr_err("%s: Failed to configure register address offset\n",
__func__);
goto err;
}
ret = wcd9xxx_alloc_slim_sh_ch_rx(wcd9xxx, wcd9xxx_pgd_la); ret = wcd9xxx_alloc_slim_sh_ch_rx(wcd9xxx, wcd9xxx_pgd_la);
if (ret) { if (ret) {
pr_err("%s: Failed to alloc rx slimbus shared channels\n", pr_err("%s: Failed to alloc rx slimbus shared channels\n",
__func__); __func__);
goto rx_err; goto err;
} }
ret = wcd9xxx_alloc_slim_sh_ch_tx(wcd9xxx, wcd9xxx_pgd_la); ret = wcd9xxx_alloc_slim_sh_ch_tx(wcd9xxx, wcd9xxx_pgd_la);
if (ret) { if (ret) {
pr_err("%s: Failed to alloc tx slimbus shared channels\n", pr_err("%s: Failed to alloc tx slimbus shared channels\n",
__func__); __func__);
goto tx_err; goto tx_err;
} }
return 0; return 0;
tx_err: tx_err:
wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx); wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
rx_err: err:
return ret; return ret;
} }
@@ -82,23 +159,22 @@ err:
return ret; return ret;
} }
int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx, int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx, unsigned int *rx_ch,
unsigned int *rx_ch, unsigned int *tx_ch)
unsigned int *tx_ch)
{ {
int ch_idx = 0; int ch_idx = 0;
struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx; struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx; struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) for (ch_idx = 0; ch_idx < sh_ch.number_of_rx_slave_dev_ports; ch_idx++)
rx_ch[ch_idx] = rx[ch_idx].ch_num; rx_ch[ch_idx] = rx[ch_idx].ch_num;
for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) for (ch_idx = 0; ch_idx < sh_ch.number_of_tx_slave_dev_ports; ch_idx++)
tx_ch[ch_idx] = tx[ch_idx].ch_num; tx_ch[ch_idx] = tx[ch_idx].ch_num;
return 0; return 0;
} }
static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx, static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
u8 wcd9xxx_pgd_la) u8 wcd9xxx_pgd_la)
{ {
int ret = 0; int ret = 0;
u8 ch_idx ; u8 ch_idx ;
@@ -109,35 +185,38 @@ static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
* DSP requires channel number to be between 128 and 255. * DSP requires channel number to be between 128 and 255.
*/ */
pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la); pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) { for (ch_idx = 0; ch_idx < sh_ch.number_of_rx_slave_dev_ports;
slave_port_id = (ch_idx + 1 + ch_idx++) {
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS); slave_port_id = (ch_idx + sh_ch.rx_port_start_offset);
rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM; rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id, ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
&rx[ch_idx].sph, SLIM_SINK); &rx[ch_idx].sph, SLIM_SINK);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slave port failure id[%d] ret[%d]\n", pr_err("%s: slave port failure id[%d] ret[%d]\n",
__func__, slave_port_id, ret); __func__, slave_port_id, ret);
goto err; goto err;
} }
ret = slim_query_ch(wcd9xxx->slim, rx[ch_idx].ch_num, ret = slim_query_ch(wcd9xxx->slim, rx[ch_idx].ch_num,
&rx[ch_idx].ch_h); &rx[ch_idx].ch_h);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n", pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
__func__, rx[ch_idx].ch_num, ret); __func__, rx[ch_idx].ch_num, ret);
goto err; goto err;
} }
pr_debug("%s:ch_num=%d ch_h=%d sph=%d la=%d slave_port_id %d\n",
__func__, rx[ch_idx].ch_num, rx[ch_idx].ch_h,
rx[ch_idx].sph, wcd9xxx_pgd_la, slave_port_id);
} }
err: err:
return ret; return ret;
} }
static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx, static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
u8 wcd9xxx_pgd_la) u8 wcd9xxx_pgd_la)
{ {
int ret = 0; int ret = 0;
u8 ch_idx ; u8 ch_idx;
struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx; struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
u16 slave_port_id = 0; u16 slave_port_id = 0;
@@ -146,21 +225,22 @@ static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
* use channel numbers from 138 to 144, for TX port * use channel numbers from 138 to 144, for TX port
* use channel numbers from 128 to 137 * use channel numbers from 128 to 137
*/ */
for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) { for (ch_idx = 0; ch_idx < sh_ch.number_of_tx_slave_dev_ports;
ch_idx++) {
slave_port_id = ch_idx; slave_port_id = ch_idx;
tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM; tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id, ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
&tx[ch_idx].sph, SLIM_SRC); &tx[ch_idx].sph, SLIM_SRC);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slave port failure id[%d] ret[%d]\n", pr_err("%s: slave port failure id[%d] ret[%d]\n",
__func__, slave_port_id, ret); __func__, slave_port_id, ret);
goto err; goto err;
} }
ret = slim_query_ch(wcd9xxx->slim, tx[ch_idx].ch_num, ret = slim_query_ch(wcd9xxx->slim, tx[ch_idx].ch_num,
&tx[ch_idx].ch_h); &tx[ch_idx].ch_h);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n", pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
__func__, tx[ch_idx].ch_num, ret); __func__, tx[ch_idx].ch_num, ret);
goto err; goto err;
} }
} }
@@ -174,7 +254,7 @@ static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx)
int ret = 0; int ret = 0;
struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx; struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
/* slim_dealloc_ch */ /* slim_dealloc_ch */
for (idx = 0; idx < SLIM_MAX_RX_PORTS; idx++) { for (idx = 0; idx < sh_ch.number_of_rx_slave_dev_ports; idx++) {
ret = slim_dealloc_ch(wcd9xxx->slim, rx[idx].ch_h); ret = slim_dealloc_ch(wcd9xxx->slim, rx[idx].ch_h);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n", pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
@@ -191,7 +271,7 @@ static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx)
int ret = 0; int ret = 0;
struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx; struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
/* slim_dealloc_ch */ /* slim_dealloc_ch */
for (idx = 0; idx < SLIM_MAX_TX_PORTS; idx++) { for (idx = 0; idx < sh_ch.number_of_tx_slave_dev_ports; idx++) {
ret = slim_dealloc_ch(wcd9xxx->slim, tx[idx].ch_h); ret = slim_dealloc_ch(wcd9xxx->slim, tx[idx].ch_h);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n", pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
@@ -204,9 +284,9 @@ static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx)
/* Enable slimbus slave device for RX path */ /* Enable slimbus slave device for RX path */
int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num, int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt, unsigned int rate) unsigned int ch_cnt, unsigned int rate)
{ {
u8 i = 0; u8 i;
u16 grph; u16 grph;
u32 sph[SLIM_MAX_RX_PORTS] = {0}; u32 sph[SLIM_MAX_RX_PORTS] = {0};
u16 ch_h[SLIM_MAX_RX_PORTS] = {0}; u16 ch_h[SLIM_MAX_RX_PORTS] = {0};
@@ -221,53 +301,56 @@ int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate); pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
for (i = 0; i < ch_cnt; i++) { for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
ch_h[i] = rx[idx].ch_h; ch_h[i] = rx[idx].ch_h;
sph[i] = rx[idx].sph; sph[i] = rx[idx].sph;
slave_port_id = idx + 1; slave_port_id = idx;
if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS) || pr_debug("%s: idx %d, ch_h %d, sph %d\n",
(slave_port_id == 0)) { __func__, idx, ch_h[i], sph[i]);
if ((slave_port_id > sh_ch.num_rx_slave_port)) {
pr_err("Slimbus: invalid slave port id: %d", pr_err("Slimbus: invalid slave port id: %d",
slave_port_id); slave_port_id);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
slave_port_id += SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS; slave_port_id += sh_ch.rx_port_start_offset;
pr_debug("%s: slave_port_id %d\n", __func__, slave_port_id);
/* look for the valid port range and chose the /* look for the valid port range and chose the
* payload accordingly * payload accordingly
*/ */
if ((slave_port_id > if ((slave_port_id > sh_ch.pgd_tx_port_ch_1_end_port_id) &&
SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) && (slave_port_id <= sh_ch.port_ch_0_end_port_id)) {
(slave_port_id <= payload_rx = payload_rx |
SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID)) { (1 << (slave_port_id -
payload_rx = payload_rx | sh_ch.port_ch_0_start_port_id));
(1 <<
(slave_port_id -
SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID));
} else { } else {
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
multi_chan_cfg_reg_addr = multi_chan_cfg_reg_addr =
SB_PGD_RX_PORT_MULTI_CHANNEL_0(slave_port_id); SB_PGD_RX_PORT_MULTI_CHANNEL_0(sh_ch.rx_port_ch_reg_base,
idx);
pr_debug("%s: multi_chan_cfg_reg_addr 0x%x\n", __func__,
multi_chan_cfg_reg_addr);
/* write to interface device */ /* write to interface device */
ret = wcd9xxx_interface_reg_write(wcd9xxx, ret = wcd9xxx_interface_reg_write(wcd9xxx,
multi_chan_cfg_reg_addr, multi_chan_cfg_reg_addr,
payload_rx); payload_rx);
if (ret < 0) { if (ret < 0) {
pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n", pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
__func__, __func__, multi_chan_cfg_reg_addr,
multi_chan_cfg_reg_addr, payload_rx, ret);
payload_rx, ret);
goto err; goto err;
} }
/* configure the slave port for water mark and enable*/ /* configure the slave port for water mark and enable*/
wm_payload = (SLAVE_PORT_WATER_MARK_VALUE << wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
SLAVE_PORT_WATER_MARK_SHIFT) + SLAVE_PORT_WATER_MARK_SHIFT) + SLAVE_PORT_ENABLE;
SLAVE_PORT_ENABLE; ret = wcd9xxx_interface_reg_write(
ret = wcd9xxx_interface_reg_write(wcd9xxx, wcd9xxx,
SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id), SB_PGD_PORT_CFG_BYTE_ADDR(
sh_ch.port_rx_cfg_reg_base, idx),
wm_payload); wm_payload);
if (ret < 0) { if (ret < 0) {
pr_err("%s:watermark set failure for port[%d] ret[%d]", pr_err("%s:watermark set failure for port[%d] ret[%d]",
@@ -283,16 +366,14 @@ int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
prop.ratem = (rate/4000); prop.ratem = (rate/4000);
prop.sampleszbits = 16; prop.sampleszbits = 16;
ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt, ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt, true, &grph);
true, &grph);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_define_ch failed ret[%d]\n", pr_err("%s: slim_define_ch failed ret[%d]\n",
__func__, ret); __func__, ret);
goto err; goto err;
} }
for (i = 0; i < ch_cnt; i++) { for (i = 0; i < ch_cnt; i++) {
ret = slim_connect_sink(wcd9xxx->slim, &sph[i], ret = slim_connect_sink(wcd9xxx->slim, &sph[i], 1, ch_h[i]);
1, ch_h[i]);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_connect_sink failed ret[%d]\n", pr_err("%s: slim_connect_sink failed ret[%d]\n",
__func__, ret); __func__, ret);
@@ -300,16 +381,14 @@ int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
} }
} }
/* slim_control_ch */ /* slim_control_ch */
ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE, ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE, true);
true);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n", pr_err("%s: slim_control_ch failed ret[%d]\n",
__func__, ret); __func__, ret);
goto err_close_slim_sch; goto err_close_slim_sch;
} }
for (i = 0; i < ch_cnt; i++) { for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
rx[idx].grph = grph; rx[idx].grph = grph;
} }
return 0; return 0;
@@ -324,7 +403,7 @@ EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_rx);
/* Enable slimbus slave device for RX path */ /* Enable slimbus slave device for RX path */
int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num, int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt, unsigned int rate) unsigned int ch_cnt, unsigned int rate)
{ {
u8 i = 0; u8 i = 0;
u8 payload_tx_0 = 0, payload_tx_1 = 0, wm_payload = 0; u8 payload_tx_0 = 0, payload_tx_1 = 0, wm_payload = 0;
@@ -333,7 +412,7 @@ int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
u16 ch_h[SLIM_MAX_TX_PORTS] = {0}; u16 ch_h[SLIM_MAX_TX_PORTS] = {0};
u16 idx = 0, slave_port_id; u16 idx = 0, slave_port_id;
int ret = 0; int ret = 0;
unsigned short multi_chan_cfg_reg_addr; unsigned short multi_chan_cfg_reg_addr;
struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx; struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
struct slim_ch prop; struct slim_ch prop;
@@ -343,10 +422,12 @@ int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
idx = (ch_num[i] - BASE_CH_NUM); idx = (ch_num[i] - BASE_CH_NUM);
ch_h[i] = tx[idx].ch_h; ch_h[i] = tx[idx].ch_h;
sph[i] = tx[idx].sph; sph[i] = tx[idx].sph;
slave_port_id = idx ; slave_port_id = idx;
if (slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) { pr_debug("%s: idx %d, ch_h %d, sph %d, slave_port_id %d\n",
__func__, idx, ch_h[i], sph[i], slave_port_id);
if (slave_port_id > sh_ch.number_of_tx_slave_dev_ports) {
pr_err("SLIMbus: invalid slave port id: %d", pr_err("SLIMbus: invalid slave port id: %d",
slave_port_id); slave_port_id);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
@@ -354,55 +435,60 @@ int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
* payload accordingly * payload accordingly
*/ */
if (slave_port_id <= if (slave_port_id <=
SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) { SB_PGD_TX_PORT_MULTI_CHANNEL_0_END_PORT_ID) {
payload_tx_0 = payload_tx_0 | (1 << slave_port_id); payload_tx_0 = payload_tx_0 | (1 << slave_port_id);
} else if (slave_port_id <= } else if (slave_port_id <=
SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID) { sh_ch.pgd_tx_port_ch_1_end_port_id) {
payload_tx_1 = payload_tx_1 | payload_tx_1 = payload_tx_1 |
(1 << (1 << (slave_port_id -
(slave_port_id - SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID));
} else { } else {
pr_err("%s: slave port id %d error\n", __func__,
slave_port_id);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
multi_chan_cfg_reg_addr = multi_chan_cfg_reg_addr =
SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id); SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
pr_debug("%s: multi_chan_cfg_reg_addr 0x%x\n", __func__,
multi_chan_cfg_reg_addr);
/* write to interface device */ /* write to interface device */
ret = wcd9xxx_interface_reg_write(wcd9xxx, ret = wcd9xxx_interface_reg_write(wcd9xxx,
multi_chan_cfg_reg_addr, multi_chan_cfg_reg_addr,
payload_tx_0); payload_tx_0);
if (ret < 0) { if (ret < 0) {
pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n", pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
__func__, __func__, multi_chan_cfg_reg_addr, payload_tx_0,
multi_chan_cfg_reg_addr, ret);
payload_tx_0, ret);
goto err; goto err;
} }
multi_chan_cfg_reg_addr = multi_chan_cfg_reg_addr =
SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id); SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
/* ports 8,9 */ /* ports 8,9 */
ret = wcd9xxx_interface_reg_write(wcd9xxx, ret = wcd9xxx_interface_reg_write(wcd9xxx,
multi_chan_cfg_reg_addr, multi_chan_cfg_reg_addr,
payload_tx_1); payload_tx_1);
if (ret < 0) { if (ret < 0) {
pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n", pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
__func__, __func__, multi_chan_cfg_reg_addr,
multi_chan_cfg_reg_addr, payload_tx_1, ret);
payload_tx_1, ret);
goto err; goto err;
} }
/* configure the slave port for water mark and enable*/ /* configure the slave port for water mark and enable*/
wm_payload = (SLAVE_PORT_WATER_MARK_VALUE << wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
SLAVE_PORT_WATER_MARK_SHIFT) + SLAVE_PORT_WATER_MARK_SHIFT) + SLAVE_PORT_ENABLE;
SLAVE_PORT_ENABLE; pr_debug("%s: tx_cfg_reg 0x%x wm 0x%x\n", __func__,
ret = wcd9xxx_interface_reg_write(wcd9xxx, SB_PGD_PORT_CFG_BYTE_ADDR(sh_ch.port_tx_cfg_reg_base,
SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id), slave_port_id), wm_payload);
wm_payload); ret = wcd9xxx_interface_reg_write(
wcd9xxx,
SB_PGD_PORT_CFG_BYTE_ADDR(
sh_ch.port_tx_cfg_reg_base,
slave_port_id),
wm_payload);
if (ret < 0) { if (ret < 0) {
pr_err("%s:watermark set failure for port[%d] ret[%d]", pr_err("%s: watermark set failure for port[%d] ret[%d]",
__func__, __func__, slave_port_id, ret);
slave_port_id, ret);
} }
} }
@@ -413,25 +499,21 @@ int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE; prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
prop.ratem = (rate/4000); prop.ratem = (rate/4000);
prop.sampleszbits = 16; prop.sampleszbits = 16;
ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt, ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt, true, &grph);
true, &grph);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_define_ch failed ret[%d]\n", pr_err("%s: slim_define_ch failed ret[%d]\n", __func__, ret);
__func__, ret);
goto err; goto err;
} }
for (i = 0; i < ch_cnt; i++) { for (i = 0; i < ch_cnt; i++) {
ret = slim_connect_src(wcd9xxx->slim, sph[i], ret = slim_connect_src(wcd9xxx->slim, sph[i], ch_h[i]);
ch_h[i]);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_connect_src failed ret[%d]\n", pr_err("%s: slim_connect_src failed ret[%d]\n",
__func__, ret); __func__, ret);
goto err; goto err;
} }
} }
/* slim_control_ch */ /* slim_control_ch */
ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE, ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE, true);
true);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n", pr_err("%s: slim_control_ch failed ret[%d]\n",
__func__, ret); __func__, ret);
@@ -460,34 +542,33 @@ int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt); pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
for (i = 0; i < ch_cnt; i++) { for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
if (idx < 0) { if (idx < 0) {
pr_err("%s: Error:-Invalid index found = %d\n", pr_err("%s: Error:-Invalid index found = %d\n",
__func__, idx); __func__, idx);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
sph[i] = rx[idx].sph; sph[i] = rx[idx].sph;
grph = rx[idx].grph; grph = rx[idx].grph;
pr_debug("%s: ch_num[%d] %d, idx %d, sph[%d] %x, grph %x\n",
__func__, i, ch_num[i], idx, i, sph[i], grph);
} }
/* slim_disconnect_port */ /* slim_disconnect_port */
ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt); ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_disconnect_ports failed ret[%d]\n", pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
__func__, ret); __func__, ret);
} }
/* slim_control_ch (REMOVE) */ /* slim_control_ch (REMOVE) */
ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true); ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
if (ret < 0) { if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n", pr_err("%s: slim_control_ch failed ret[%d]\n", __func__, ret);
__func__, ret);
goto err; goto err;
} }
for (i = 0; i < ch_cnt; i++) { for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
rx[idx].grph = 0; rx[idx].grph = 0;
} }
err: err:
@@ -496,7 +577,7 @@ err:
EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_rx); EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_rx);
int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num, int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt) unsigned int ch_cnt)
{ {
u16 grph = 0; u16 grph = 0;
u32 sph[SLIM_MAX_TX_PORTS] = {0}; u32 sph[SLIM_MAX_TX_PORTS] = {0};

View File

@@ -16,10 +16,6 @@
#include <linux/slimbus/slimbus.h> #include <linux/slimbus/slimbus.h>
#include <linux/mfd/wcd9xxx/core.h> #include <linux/mfd/wcd9xxx/core.h>
/* Local to the core only */
#define SLIM_MAX_RX_PORTS 7
#define SLIM_MAX_TX_PORTS 10
/* Channel numbers to be used for each port */ /* Channel numbers to be used for each port */
enum { enum {
SLIM_TX_1 = 128, SLIM_TX_1 = 128,
@@ -43,20 +39,43 @@ enum {
}; };
/* /*
* client is expected to give port ids in the range of 1-10 for Tx ports and * client is expected to give port ids in the range of
* 1-7 for Rx ports, we need to add offset for getting the absolute slave * 1-10 for pre Taiko Tx ports and 1-16 for Taiko
* 1-7 for pre Taiko Rx ports and 1-16 for Tako,
* we need to add offset for getting the absolute slave
* port id before configuring the HW * port id before configuring the HW
*/ */
#define SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 10 #define TABLA_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 10
#define SB_PGD_OFFSET_OF_TX_SLAVE_DEV_PORTS -1 #define TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS 16
#define SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 7
#define SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS 9 #define SLIM_MAX_TX_PORTS TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS
#define TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS \
TABLA_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS
#define TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS \
TAIKO_SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS
#define TABLA_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 7
#define TAIKO_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS 13
#define SLIM_MAX_RX_PORTS TAIKO_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS
#define TABLA_SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID \
TABLA_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS
#define TAIKO_SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID \
TAIKO_SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS
#define TABLA_SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID 16
#define TAIKO_SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID 31
#define TABLA_SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID 9
#define TAIKO_SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID 15
/* below details are taken from SLIMBUS slave SWI */ /* below details are taken from SLIMBUS slave SWI */
#define SB_PGD_PORT_BASE 0x000 #define SB_PGD_PORT_BASE 0x000
#define SB_PGD_PORT_CFG_BYTE_ADDR(port_num) \ #define SB_PGD_PORT_CFG_BYTE_ADDR(offset, port_num) \
(SB_PGD_PORT_BASE + 0x040 + 1*port_num) (SB_PGD_PORT_BASE + offset + (1 * port_num))
#define SB_PGD_TX_PORT_MULTI_CHANNEL_0(port_num) \ #define SB_PGD_TX_PORT_MULTI_CHANNEL_0(port_num) \
(SB_PGD_PORT_BASE + 0x100 + 4*port_num) (SB_PGD_PORT_BASE + 0x100 + 4*port_num)
@@ -66,12 +85,9 @@ enum {
#define SB_PGD_TX_PORT_MULTI_CHANNEL_1(port_num) \ #define SB_PGD_TX_PORT_MULTI_CHANNEL_1(port_num) \
(SB_PGD_PORT_BASE + 0x101 + 4*port_num) (SB_PGD_PORT_BASE + 0x101 + 4*port_num)
#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID 8 #define SB_PGD_TX_PORT_MULTI_CHANNEL_1_START_PORT_ID 8
#define SB_PGD_TX_PORT_MULTI_CHANNEL_1_END_PORT_ID 9
#define SB_PGD_RX_PORT_MULTI_CHANNEL_0(port_num) \ #define SB_PGD_RX_PORT_MULTI_CHANNEL_0(offset, port_num) \
(SB_PGD_PORT_BASE + 0x180 + 4*port_num) (SB_PGD_PORT_BASE + offset + (4 * port_num))
#define SB_PGD_RX_PORT_MULTI_CHANNEL_0_START_PORT_ID 10
#define SB_PGD_RX_PORT_MULTI_CHANNEL_0_END_PORT_ID 16
/* slave port water mark level /* slave port water mark level
* (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes) * (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes)