2012-02-10 10:00:44

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

Hello,

Changes since v2:
- soc/codec/Kconfig: make twl6040 depend on I2C
- Regulator related patches has been removed (to be sent as separate series)

------
Intro mail from the original series:

This series will convert the twl6040 MFD driver to an i2c driver.
Compared to older twl4030/5030/TPS the twl6040 is a standalone audio IC. It is
better if the twl6040-core (and all of it's child devices) does not depend on
the twl-core since it has nothing to with it.

With this conversion the dependency on twl can be dropped from the twl6040
driver stack (core, vibra, audio).

Between the first and second patch the audio will not probe on OMAP4, but I felt
it is better this way at least for the first RFC series to not have too big
change within one patch. The two patch can be squashed together later if no
objections.

Regards,
Peter
---
Peter Ujfalusi (3):
MFD: twl-core: Detach twl6040 from the pmic mfd driver
MFD: twl6040: Convert to i2c driver, and separate it from twl core
ASoC: twl6040: Remove dependency on twl4030 from Kconfig

arch/arm/mach-omap2/board-4430sdp.c | 12 ++--
arch/arm/mach-omap2/board-generic.c | 2 +-
arch/arm/mach-omap2/board-omap4panda.c | 13 ++--
arch/arm/mach-omap2/twl-common.c | 37 +++++++++--
arch/arm/mach-omap2/twl-common.h | 10 +--
drivers/input/misc/Kconfig | 1 -
drivers/input/misc/twl6040-vibra.c | 4 +-
drivers/mfd/Kconfig | 2 +-
drivers/mfd/twl-core.c | 58 +++++++++-------
drivers/mfd/twl6040-core.c | 114 +++++++++++++++++++-------------
include/linux/i2c/twl.h | 12 ----
include/linux/mfd/twl6040.h | 27 ++++++++
sound/soc/codecs/Kconfig | 2 +-
sound/soc/codecs/twl6040.c | 3 +-
14 files changed, 182 insertions(+), 115 deletions(-)

--
1.7.8.4


2012-02-10 10:00:40

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH v3 1/3] MFD: twl-core: Detach twl6040 from the pmic mfd driver

On OMAP4 platform audio has separate IC, it is no longer part
of the pmic chip.
Prevent twl-core to claim the 0x4b address, which belongs to
the twl6040 audio IC.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 58 +++++++++++++++++++++++++++--------------------
1 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e04e04d..ac6fdd93 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -115,8 +115,8 @@
#define twl_has_watchdog() false
#endif

-#if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\
- defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
+#if defined(CONFIG_MFD_TWL4030_AUDIO) || \
+ defined(CONFIG_MFD_TWL4030_AUDIO_MODULE)
#define twl_has_codec() true
#else
#define twl_has_codec() false
@@ -146,6 +146,7 @@
#define SUB_CHIP_ID1 1
#define SUB_CHIP_ID2 2
#define SUB_CHIP_ID3 3
+#define SUB_CHIP_ID_INVAL 0xff

#define TWL_MODULE_LAST TWL4030_MODULE_LAST

@@ -315,7 +316,7 @@ static struct twl_mapping twl6030_map[] = {
* so they continue to match the order in this table.
*/
{ SUB_CHIP_ID1, TWL6030_BASEADD_USB },
- { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO },
+ { SUB_CHIP_ID_INVAL, TWL6030_BASEADD_AUDIO },
{ SUB_CHIP_ID2, TWL6030_BASEADD_DIEID },
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
{ SUB_CHIP_ID1, TWL6030_BASEADD_PIH },
@@ -377,6 +378,11 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
return -EPERM;
}
sid = twl_map[mod_no].sid;
+ if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
+ pr_err("%s: module %d is not part of the pmic\n",
+ DRIVER_NAME, mod_no);
+ return -EINVAL;
+ }
twl = &twl_modules[sid];

mutex_lock(&twl->xfer_lock);
@@ -434,6 +440,11 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
return -EPERM;
}
sid = twl_map[mod_no].sid;
+ if (unlikely(sid == SUB_CHIP_ID_INVAL)) {
+ pr_err("%s: module %d is not part of the pmic\n",
+ DRIVER_NAME, mod_no);
+ return -EINVAL;
+ }
twl = &twl_modules[sid];

mutex_lock(&twl->xfer_lock);
@@ -834,15 +845,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
return PTR_ERR(child);
}

- if (twl_has_codec() && pdata->audio && twl_class_is_6030()) {
- sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
- child = add_child(sub_chip_id, "twl6040",
- pdata->audio, sizeof(*pdata->audio),
- false, 0, 0);
- if (IS_ERR(child))
- return PTR_ERR(child);
- }
-
/* twl4030 regulators */
if (twl_has_regulator() && twl_class_is_4030()) {
child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
@@ -1163,18 +1165,21 @@ int twl6030_exit_irq(void);

static int twl_remove(struct i2c_client *client)
{
- unsigned i;
+ unsigned i, num_slaves;
int status;

- if (twl_class_is_4030())
+ if (twl_class_is_4030()) {
status = twl4030_exit_irq();
- else
+ num_slaves = TWL_NUM_SLAVES;
+ } else {
status = twl6030_exit_irq();
+ num_slaves = TWL_NUM_SLAVES - 1;
+ }

if (status < 0)
return status;

- for (i = 0; i < TWL_NUM_SLAVES; i++) {
+ for (i = 0; i < num_slaves; i++) {
struct twl_client *twl = &twl_modules[i];

if (twl->client && twl->client != client)
@@ -1190,7 +1195,7 @@ static int __devinit
twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int status;
- unsigned i;
+ unsigned i, num_slaves;
struct twl4030_platform_data *pdata = client->dev.platform_data;
struct device_node *node = client->dev.of_node;
u8 temp;
@@ -1244,7 +1249,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -EBUSY;
}

- for (i = 0; i < TWL_NUM_SLAVES; i++) {
+ if ((id->driver_data) & TWL6030_CLASS) {
+ twl_id = TWL6030_CLASS_ID;
+ twl_map = &twl6030_map[0];
+ num_slaves = TWL_NUM_SLAVES - 1;
+ } else {
+ twl_id = TWL4030_CLASS_ID;
+ twl_map = &twl4030_map[0];
+ num_slaves = TWL_NUM_SLAVES;
+ }
+
+ for (i = 0; i < num_slaves; i++) {
struct twl_client *twl = &twl_modules[i];

twl->address = client->addr + i;
@@ -1263,13 +1278,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
mutex_init(&twl->xfer_lock);
}
inuse = true;
- if ((id->driver_data) & TWL6030_CLASS) {
- twl_id = TWL6030_CLASS_ID;
- twl_map = &twl6030_map[0];
- } else {
- twl_id = TWL4030_CLASS_ID;
- twl_map = &twl4030_map[0];
- }

/* setup clock framework */
clocks_init(&client->dev, pdata->clock);
--
1.7.8.4

2012-02-10 10:00:54

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH v3 3/3] ASoC: twl6040: Remove dependency on twl4030 from Kconfig

twl6040 no longer needs twl4030.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
sound/soc/codecs/Kconfig | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7c205e7..f1a1197 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -56,7 +56,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C
select SND_SOC_TWL4030 if TWL4030_CORE
- select SND_SOC_TWL6040 if TWL4030_CORE
+ select SND_SOC_TWL6040 if I2C
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
select SND_SOC_WL1273 if MFD_WL1273_CORE
--
1.7.8.4

2012-02-10 10:01:20

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH v3 2/3] MFD: twl6040: Convert to i2c driver, and separate it from twl core

Complete the separation of the twl6040 from the twl core since
it is a separate chip, not part of the twl6030 PMIC.

Signed-off-by: Peter Ujfalusi <[email protected]>
Reviewed-by: Mark Brown <[email protected]>
---
arch/arm/mach-omap2/board-4430sdp.c | 12 ++--
arch/arm/mach-omap2/board-generic.c | 2 +-
arch/arm/mach-omap2/board-omap4panda.c | 13 ++--
arch/arm/mach-omap2/twl-common.c | 37 +++++++++--
arch/arm/mach-omap2/twl-common.h | 10 +--
drivers/input/misc/Kconfig | 1 -
drivers/input/misc/twl6040-vibra.c | 4 +-
drivers/mfd/Kconfig | 2 +-
drivers/mfd/twl6040-core.c | 114 +++++++++++++++++++-------------
include/linux/i2c/twl.h | 12 ----
include/linux/mfd/twl6040.h | 27 ++++++++
sound/soc/codecs/twl6040.c | 3 +-
12 files changed, 148 insertions(+), 89 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 7eaeb08..f4ac553 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -20,6 +20,7 @@
#include <linux/usb/otg.h>
#include <linux/spi/spi.h>
#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
#include <linux/gpio_keys.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
@@ -554,7 +555,7 @@ static struct regulator_init_data sdp4430_vusim = {
},
};

-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
/* single-step ramp for headset and handsfree */
.hs_left_step = 0x0f,
.hs_right_step = 0x0f,
@@ -562,7 +563,7 @@ static struct twl4030_codec_data twl6040_codec = {
.hf_right_step = 0x1d,
};

-static struct twl4030_vibra_data twl6040_vibra = {
+static struct twl6040_vibra_data twl6040_vibra = {
.vibldrv_res = 8,
.vibrdrv_res = 3,
.viblmotor_res = 10,
@@ -571,16 +572,14 @@ static struct twl4030_vibra_data twl6040_vibra = {
.vddvibr_uV = 0, /* fixed volt supply - VBAT */
};

-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
.codec = &twl6040_codec,
.vibra = &twl6040_vibra,
.audpwron_gpio = 127,
- .naudint_irq = OMAP44XX_IRQ_SYS_2N,
.irq_base = TWL6040_CODEC_IRQ_BASE,
};

static struct twl4030_platform_data sdp4430_twldata = {
- .audio = &twl6040_audio,
/* Regulators */
.vusim = &sdp4430_vusim,
.vaux1 = &sdp4430_vaux1,
@@ -611,7 +610,8 @@ static int __init omap4_i2c_init(void)
TWL_COMMON_REGULATOR_VCXIO |
TWL_COMMON_REGULATOR_VUSB |
TWL_COMMON_REGULATOR_CLK32KG);
- omap4_pmic_init("twl6030", &sdp4430_twldata);
+ omap4_pmic_init("twl6030", &sdp4430_twldata,
+ &twl6040_data, OMAP44XX_IRQ_SYS_2N);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index d587560..68b9d8a 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -35,7 +35,7 @@ static struct twl4030_platform_data sdp4430_twldata = {

static void __init omap4_i2c_init(void)
{
- omap4_pmic_init("twl6030", &sdp4430_twldata);
+ omap4_pmic_init("twl6030", &sdp4430_twldata, NULL, 0);
}
#endif

diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index eada955..da31a72 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -25,6 +25,7 @@
#include <linux/gpio.h>
#include <linux/usb/otg.h>
#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/wl12xx.h>
@@ -277,7 +278,7 @@ static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
return 0;
}

-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
/* single-step ramp for headset and handsfree */
.hs_left_step = 0x0f,
.hs_right_step = 0x0f,
@@ -285,17 +286,14 @@ static struct twl4030_codec_data twl6040_codec = {
.hf_right_step = 0x1d,
};

-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
.codec = &twl6040_codec,
.audpwron_gpio = 127,
- .naudint_irq = OMAP44XX_IRQ_SYS_2N,
.irq_base = TWL6040_CODEC_IRQ_BASE,
};

/* Panda board uses the common PMIC configuration */
-static struct twl4030_platform_data omap4_panda_twldata = {
- .audio = &twl6040_audio,
-};
+static struct twl4030_platform_data omap4_panda_twldata;

/*
* Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -319,7 +317,8 @@ static int __init omap4_panda_i2c_init(void)
TWL_COMMON_REGULATOR_VCXIO |
TWL_COMMON_REGULATOR_VUSB |
TWL_COMMON_REGULATOR_CLK32KG);
- omap4_pmic_init("twl6030", &omap4_panda_twldata);
+ omap4_pmic_init("twl6030", &omap4_panda_twldata,
+ &twl6040_data, OMAP44XX_IRQ_SYS_2N);
omap_register_i2c_bus(2, 400, NULL, 0);
/*
* Bus 3 is attached to the DVI port where devices like the pico DLP
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 10b20c6..bc03154 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -37,6 +37,16 @@ static struct i2c_board_info __initdata pmic_i2c_board_info = {
.flags = I2C_CLIENT_WAKE,
};

+static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
+ {
+ .addr = 0x48,
+ .flags = I2C_CLIENT_WAKE,
+ },
+ {
+ I2C_BOARD_INFO("twl6040", 0x4b),
+ },
+};
+
void __init omap_pmic_init(int bus, u32 clkrate,
const char *pmic_type, int pmic_irq,
struct twl4030_platform_data *pmic_data)
@@ -49,14 +59,31 @@ void __init omap_pmic_init(int bus, u32 clkrate,
omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
}

+void omap4_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data,
+ struct twl6040_platform_data *twl6040_data, int twl6040_irq)
+{
+ /* PMIC part*/
+ strncpy(omap4_i2c1_board_info[0].type, pmic_type,
+ sizeof(omap4_i2c1_board_info[0].type));
+ omap4_i2c1_board_info[0].irq = OMAP44XX_IRQ_SYS_1N;
+ omap4_i2c1_board_info[0].platform_data = pmic_data;
+
+ /* TWL6040 audio IC part */
+ omap4_i2c1_board_info[1].irq = twl6040_irq;
+ omap4_i2c1_board_info[1].platform_data = twl6040_data;
+
+ omap_register_i2c_bus(1, 400, omap4_i2c1_board_info, 2);
+
+}
+
void __init omap_pmic_late_init(void)
{
/* Init the OMAP TWL parameters (if PMIC has been registerd) */
- if (!pmic_i2c_board_info.irq)
- return;
-
- omap3_twl_init();
- omap4_twl_init();
+ if (pmic_i2c_board_info.irq)
+ omap3_twl_init();
+ if (omap4_i2c1_board_info[0].irq)
+ omap4_twl_init();
}

#if defined(CONFIG_ARCH_OMAP3)
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
index 275dde8..0962748 100644
--- a/arch/arm/mach-omap2/twl-common.h
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -29,6 +29,7 @@


struct twl4030_platform_data;
+struct twl6040_platform_data;

void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
struct twl4030_platform_data *pmic_data);
@@ -46,12 +47,9 @@ static inline void omap3_pmic_init(const char *pmic_type,
omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
}

-static inline void omap4_pmic_init(const char *pmic_type,
- struct twl4030_platform_data *pmic_data)
-{
- /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
- omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
-}
+void omap4_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data,
+ struct twl6040_platform_data *audio_data, int twl6040_irq);

void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
u32 pdata_flags, u32 regulators_flags);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 7b46781..6a9ee24 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -368,7 +368,6 @@ config INPUT_TWL4030_VIBRA

config INPUT_TWL6040_VIBRA
tristate "Support for TWL6040 Vibrator"
- depends on TWL4030_CORE
select TWL6040_CORE
select INPUT_FF_MEMLESS
help
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 45874fe..14e94f5 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -28,7 +28,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
-#include <linux/i2c/twl.h>
+#include <linux/input.h>
#include <linux/mfd/twl6040.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -257,7 +257,7 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL);

static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
{
- struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+ struct twl6040_vibra_data *pdata = pdev->dev.platform_data;
struct vibra_info *info;
int ret;

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index cd13e9f..203e9bc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -252,7 +252,7 @@ config TWL6030_PWM

config TWL6040_CORE
bool
- depends on TWL4030_CORE && GENERIC_HARDIRQS
+ depends on I2C && GENERIC_HARDIRQS
select MFD_CORE
default n

diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index dda8629..ea00c69 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -30,7 +30,9 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/delay.h>
-#include <linux/i2c/twl.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
#include <linux/mfd/core.h>
#include <linux/mfd/twl6040.h>

@@ -39,7 +41,7 @@
int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
{
int ret;
- u8 val = 0;
+ unsigned int val;

mutex_lock(&twl6040->io_mutex);
/* Vibra control registers from cache */
@@ -47,7 +49,7 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
reg == TWL6040_REG_VIBCTLR)) {
val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
} else {
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+ ret = regmap_read(twl6040->regmap, reg, &val);
if (ret < 0) {
mutex_unlock(&twl6040->io_mutex);
return ret;
@@ -64,7 +66,7 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
int ret;

mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+ ret = regmap_write(twl6040->regmap, reg, val);
/* Cache the vibra control registers */
if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
@@ -77,16 +79,9 @@ EXPORT_SYMBOL(twl6040_reg_write);
int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
{
int ret;
- u8 val;

mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret)
- goto out;
-
- val |= mask;
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
+ ret = regmap_update_bits(twl6040->regmap, reg, mask, mask);
mutex_unlock(&twl6040->io_mutex);
return ret;
}
@@ -95,16 +90,9 @@ EXPORT_SYMBOL(twl6040_set_bits);
int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
{
int ret;
- u8 val;

mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret)
- goto out;
-
- val &= ~mask;
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
+ ret = regmap_update_bits(twl6040->regmap, reg, mask, 0);
mutex_unlock(&twl6040->io_mutex);
return ret;
}
@@ -468,32 +456,58 @@ static struct resource twl6040_codec_rsrc[] = {
},
};

-static int __devinit twl6040_probe(struct platform_device *pdev)
+static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
{
- struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+ /* Register 0 is not readable */
+ if (!reg)
+ return false;
+ return true;
+}
+
+static struct regmap_config twl6040_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TWL6040_REG_STATUS, /* 0x2e */
+
+ .readable_reg = twl6040_readable_reg,
+};
+
+static int __devinit twl6040_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct twl6040_platform_data *pdata = client->dev.platform_data;
struct twl6040 *twl6040;
struct mfd_cell *cell = NULL;
int ret, children = 0;

if (!pdata) {
- dev_err(&pdev->dev, "Platform data is missing\n");
+ dev_err(&client->dev, "Platform data is missing\n");
return -EINVAL;
}

/* In order to operate correctly we need valid interrupt config */
- if (!pdata->naudint_irq || !pdata->irq_base) {
- dev_err(&pdev->dev, "Invalid IRQ configuration\n");
+ if (!client->irq || !pdata->irq_base) {
+ dev_err(&client->dev, "Invalid IRQ configuration\n");
return -EINVAL;
}

- twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
- if (!twl6040)
- return -ENOMEM;
+ twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
+ GFP_KERNEL);
+ if (!twl6040) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ twl6040->regmap = regmap_init_i2c(client, &twl6040_regmap_config);
+ if (IS_ERR(twl6040->regmap)) {
+ ret = PTR_ERR(twl6040->regmap);
+ goto err;
+ }

- platform_set_drvdata(pdev, twl6040);
+ i2c_set_clientdata(client, twl6040);

- twl6040->dev = &pdev->dev;
- twl6040->irq = pdata->naudint_irq;
+ twl6040->dev = &client->dev;
+ twl6040->irq = client->irq;
twl6040->irq_base = pdata->irq_base;

mutex_init(&twl6040->mutex);
@@ -562,12 +576,12 @@ static int __devinit twl6040_probe(struct platform_device *pdev)
}

if (children) {
- ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
+ ret = mfd_add_devices(&client->dev, -1, twl6040->cells,
children, NULL, 0);
if (ret)
goto mfd_err;
} else {
- dev_err(&pdev->dev, "No platform data found for children\n");
+ dev_err(&client->dev, "No platform data found for children\n");
ret = -ENODEV;
goto mfd_err;
}
@@ -582,14 +596,15 @@ gpio2_err:
if (gpio_is_valid(twl6040->audpwron))
gpio_free(twl6040->audpwron);
gpio1_err:
- platform_set_drvdata(pdev, NULL);
- kfree(twl6040);
+ i2c_set_clientdata(client, NULL);
+ regmap_exit(twl6040->regmap);
+err:
return ret;
}

-static int __devexit twl6040_remove(struct platform_device *pdev)
+static int __devexit twl6040_remove(struct i2c_client *client)
{
- struct twl6040 *twl6040 = platform_get_drvdata(pdev);
+ struct twl6040 *twl6040 = i2c_get_clientdata(client);

if (twl6040->power_count)
twl6040_power(twl6040, 0);
@@ -600,23 +615,30 @@ static int __devexit twl6040_remove(struct platform_device *pdev)
free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
twl6040_irq_exit(twl6040);

- mfd_remove_devices(&pdev->dev);
- platform_set_drvdata(pdev, NULL);
- kfree(twl6040);
+ mfd_remove_devices(&client->dev);
+ i2c_set_clientdata(client, NULL);
+ regmap_exit(twl6040->regmap);

return 0;
}

-static struct platform_driver twl6040_driver = {
+static const struct i2c_device_id twl6040_i2c_id[] = {
+ { "twl6040", 0, },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id);
+
+static struct i2c_driver twl6040_driver = {
+ .driver = {
+ .name = "twl6040",
+ .owner = THIS_MODULE,
+ },
.probe = twl6040_probe,
.remove = __devexit_p(twl6040_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "twl6040",
- },
+ .id_table = twl6040_i2c_id,
};

-module_platform_driver(twl6040_driver);
+module_i2c_driver(twl6040_driver);

MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <[email protected]>");
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 78d3465..3826a53 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -666,23 +666,11 @@ struct twl4030_codec_data {
unsigned int check_defaults:1;
unsigned int reset_registers:1;
unsigned int hs_extmute:1;
- u16 hs_left_step;
- u16 hs_right_step;
- u16 hf_left_step;
- u16 hf_right_step;
void (*set_hs_extmute)(int mute);
};

struct twl4030_vibra_data {
unsigned int coexist;
-
- /* twl6040 */
- unsigned int vibldrv_res; /* left driver resistance */
- unsigned int vibrdrv_res; /* right driver resistance */
- unsigned int viblmotor_res; /* left motor resistance */
- unsigned int vibrmotor_res; /* right motor resistance */
- int vddvibl_uV; /* VDDVIBL volt, set 0 for fixed reg */
- int vddvibr_uV; /* VDDVIBR volt, set 0 for fixed reg */
};

struct twl4030_audio_data {
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 2463c261..e3ff28d 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -174,8 +174,35 @@
#define TWL6040_SYSCLK_SEL_LPPLL 0
#define TWL6040_SYSCLK_SEL_HPPLL 1

+struct twl6040_codec_data {
+ u16 hs_left_step;
+ u16 hs_right_step;
+ u16 hf_left_step;
+ u16 hf_right_step;
+};
+
+struct twl6040_vibra_data {
+ unsigned int vibldrv_res; /* left driver resistance */
+ unsigned int vibrdrv_res; /* right driver resistance */
+ unsigned int viblmotor_res; /* left motor resistance */
+ unsigned int vibrmotor_res; /* right motor resistance */
+ int vddvibl_uV; /* VDDVIBL volt, set 0 for fixed reg */
+ int vddvibr_uV; /* VDDVIBR volt, set 0 for fixed reg */
+};
+
+struct twl6040_platform_data {
+ int audpwron_gpio; /* audio power-on gpio */
+ unsigned int irq_base;
+
+ struct twl6040_codec_data *codec;
+ struct twl6040_vibra_data *vibra;
+};
+
+struct regmap;
+
struct twl6040 {
struct device *dev;
+ struct regmap *regmap;
struct mutex mutex;
struct mutex io_mutex;
struct mutex irq_mutex;
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index ece47ed..3694e9f 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -26,7 +26,6 @@
#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/i2c/twl.h>
#include <linux/mfd/twl6040.h>

#include <sound/core.h>
@@ -1515,7 +1514,7 @@ static int twl6040_resume(struct snd_soc_codec *codec)
static int twl6040_probe(struct snd_soc_codec *codec)
{
struct twl6040_data *priv;
- struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
+ struct twl6040_codec_data *pdata = dev_get_platdata(codec->dev);
struct platform_device *pdev = container_of(codec->dev,
struct platform_device, dev);
int ret = 0;
--
1.7.8.4

2012-02-10 11:10:39

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v3 3/3] ASoC: twl6040: Remove dependency on twl4030 from Kconfig

On Fri, Feb 10, 2012 at 12:00:18PM +0200, Peter Ujfalusi wrote:
> twl6040 no longer needs twl4030.
>
> Signed-off-by: Peter Ujfalusi <[email protected]>

Reviewed-by: Mark Brown <[email protected]>

This should go via whatever path the first two patches go.


Attachments:
(No filename) (281.00 B)
signature.asc (836.00 B)
Digital signature
Download all attachments

2012-02-17 11:47:32

by Peter Ujfalusi

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

Hi,

On 02/10/2012 12:00 PM, Peter Ujfalusi wrote:
> Hello,
>
> Changes since v2:
> - soc/codec/Kconfig: make twl6040 depend on I2C
> - Regulator related patches has been removed (to be sent as separate series)
>
> ------
> Intro mail from the original series:
>
> This series will convert the twl6040 MFD driver to an i2c driver.
> Compared to older twl4030/5030/TPS the twl6040 is a standalone audio IC. It is
> better if the twl6040-core (and all of it's child devices) does not depend on
> the twl-core since it has nothing to with it.
>
> With this conversion the dependency on twl can be dropped from the twl6040
> driver stack (core, vibra, audio).
>
> Between the first and second patch the audio will not probe on OMAP4, but I felt
> it is better this way at least for the first RFC series to not have too big
> change within one patch. The two patch can be squashed together later if no
> objections.
>
> Regards,
> Peter
> ---
> Peter Ujfalusi (3):
> MFD: twl-core: Detach twl6040 from the pmic mfd driver
> MFD: twl6040: Convert to i2c driver, and separate it from twl core
> ASoC: twl6040: Remove dependency on twl4030 from Kconfig
>
> arch/arm/mach-omap2/board-4430sdp.c | 12 ++--
> arch/arm/mach-omap2/board-generic.c | 2 +-
> arch/arm/mach-omap2/board-omap4panda.c | 13 ++--
> arch/arm/mach-omap2/twl-common.c | 37 +++++++++--
> arch/arm/mach-omap2/twl-common.h | 10 +--
> drivers/input/misc/Kconfig | 1 -
> drivers/input/misc/twl6040-vibra.c | 4 +-
> drivers/mfd/Kconfig | 2 +-
> drivers/mfd/twl-core.c | 58 +++++++++-------
> drivers/mfd/twl6040-core.c | 114 +++++++++++++++++++-------------
> include/linux/i2c/twl.h | 12 ----
> include/linux/mfd/twl6040.h | 27 ++++++++
> sound/soc/codecs/Kconfig | 2 +-
> sound/soc/codecs/twl6040.c | 3 +-
> 14 files changed, 182 insertions(+), 115 deletions(-)

It has been a week since I have sent this series. It would be great if
this be on time for 3.4 merge window.

Thank you,
P?ter

2012-02-20 19:40:30

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

Hi Peter,

On Fri, Feb 10, 2012 at 12:00:15PM +0200, Peter Ujfalusi wrote:
> Hello,
>
> Changes since v2:
> - soc/codec/Kconfig: make twl6040 depend on I2C
> - Regulator related patches has been removed (to be sent as separate series)
I applied all 3 patches. Patch #2 did not apply cleanly, due to the fact that
several struct twl4030_codec_data omap4panda.c references are not upstream
yet. This is my .rej:

--- arch/arm/mach-omap2/board-omap4panda.c
+++ arch/arm/mach-omap2/board-omap4panda.c
@@ -278,7 +279,7 @@
return 0;
}

-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
/* single-step ramp for headset and handsfree */
.hs_left_step = 0x0f,
.hs_right_step = 0x0f,
@@ -286,17 +287,14 @@
.hf_right_step = 0x1d,
};

-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
.codec = &twl6040_codec,
.audpwron_gpio = 127,
- .naudint_irq = OMAP44XX_IRQ_SYS_2N,
.irq_base = TWL6040_CODEC_IRQ_BASE,
};

/* Panda board uses the common PMIC configuration */
-static struct twl4030_platform_data omap4_panda_twldata = {
- .audio = &twl6040_audio,
-};
+static struct twl4030_platform_data omap4_panda_twldata;

I'm not sure hwo we could handle that properly. Either by letting Tony
carrying this patchset, or by sending me the panda patch that adds those
structures. As you prefer.

Cheers,
Samuel.

--
Intel Open Source Technology Centre
http://oss.intel.com/

2012-02-21 10:33:06

by Peter Ujfalusi

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

Hi Samuel,

On 02/20/2012 09:47 PM, Samuel Ortiz wrote:
> Hi Peter,
>
> On Fri, Feb 10, 2012 at 12:00:15PM +0200, Peter Ujfalusi wrote:
>> Hello,
>>
>> Changes since v2:
>> - soc/codec/Kconfig: make twl6040 depend on I2C
>> - Regulator related patches has been removed (to be sent as separate series)
> I applied all 3 patches. Patch #2 did not apply cleanly, due to the fact that
> several struct twl4030_codec_data omap4panda.c references are not upstream
> yet. This is my .rej:

The Panda audio support is going via sound tree. It is in linux-next
already for couple of weeks now. The reason you have this reject is that
you don't have the audio support for Panda series, and a such upstream
does not have it either :( It is for 3.4 also.

> --- arch/arm/mach-omap2/board-omap4panda.c
> +++ arch/arm/mach-omap2/board-omap4panda.c
> @@ -278,7 +279,7 @@
> return 0;
> }
>
> -static struct twl4030_codec_data twl6040_codec = {
> +static struct twl6040_codec_data twl6040_codec = {
> /* single-step ramp for headset and handsfree */
> .hs_left_step = 0x0f,
> .hs_right_step = 0x0f,
> @@ -286,17 +287,14 @@
> .hf_right_step = 0x1d,
> };
>
> -static struct twl4030_audio_data twl6040_audio = {
> +static struct twl6040_platform_data twl6040_data = {
> .codec = &twl6040_codec,
> .audpwron_gpio = 127,
> - .naudint_irq = OMAP44XX_IRQ_SYS_2N,
> .irq_base = TWL6040_CODEC_IRQ_BASE,
> };
>
> /* Panda board uses the common PMIC configuration */
> -static struct twl4030_platform_data omap4_panda_twldata = {
> - .audio = &twl6040_audio,
> -};
> +static struct twl4030_platform_data omap4_panda_twldata;
>
> I'm not sure hwo we could handle that properly. Either by letting Tony
> carrying this patchset, or by sending me the panda patch that adds those
> structures. As you prefer.

If Liam would take this series that would be probably the way forward.
If he does not have objections.
Liam: I can create a branch for you to pull from as soon as all other
patch receives the needed acks...

Samuel: if Liam agrees is it possible for you to drop the twl6040
related patches from your for-next branch?

Thank you,
P?ter

2012-02-21 11:05:39

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

Hi Peter,

On Tue, Feb 21, 2012 at 12:33:07PM +0200, Peter Ujfalusi wrote:
> > I'm not sure hwo we could handle that properly. Either by letting Tony
> > carrying this patchset, or by sending me the panda patch that adds those
> > structures. As you prefer.
>
> If Liam would take this series that would be probably the way forward.
> If he does not have objections.
> Liam: I can create a branch for you to pull from as soon as all other
> patch receives the needed acks...
>
> Samuel: if Liam agrees is it possible for you to drop the twl6040
> related patches from your for-next branch?
That would make sense to me, yes.
Liam, if you're ok with taking it, please add my:

Acked-by: Samuel Ortiz <[email protected]>

to this patchset.

Cheers,
Samuel.

--
Intel Open Source Technology Centre
http://oss.intel.com/

2012-02-21 17:52:42

by Liam Girdwood

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

On Tue, 2012-02-21 at 12:05 +0100, Samuel Ortiz wrote:
> Hi Peter,
>
> On Tue, Feb 21, 2012 at 12:33:07PM +0200, Peter Ujfalusi wrote:
> > > I'm not sure hwo we could handle that properly. Either by letting Tony
> > > carrying this patchset, or by sending me the panda patch that adds those
> > > structures. As you prefer.
> >
> > If Liam would take this series that would be probably the way forward.
> > If he does not have objections.
> > Liam: I can create a branch for you to pull from as soon as all other
> > patch receives the needed acks...
> >
> > Samuel: if Liam agrees is it possible for you to drop the twl6040
> > related patches from your for-next branch?
> That would make sense to me, yes.
> Liam, if you're ok with taking it, please add my:
>
> Acked-by: Samuel Ortiz <[email protected]>
>

Ok, sounds fine by me. Tony is this fine wrt the OMAP board file
updates ?

Thanks

Liam

2012-02-21 18:44:05

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH v3 2/3] MFD: twl6040: Convert to i2c driver, and separate it from twl core

* Peter Ujfalusi <[email protected]> [120210 01:29]:
> Complete the separation of the twl6040 from the twl core since
> it is a separate chip, not part of the twl6030 PMIC.
>
> Signed-off-by: Peter Ujfalusi <[email protected]>
> Reviewed-by: Mark Brown <[email protected]>

This should be OK to merge via the ASoC tree:

Acked-by: Tony Lindgren <[email protected]>

2012-02-21 18:44:33

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

* Liam Girdwood <[email protected]> [120221 09:21]:
> On Tue, 2012-02-21 at 12:05 +0100, Samuel Ortiz wrote:
> > Hi Peter,
> >
> > On Tue, Feb 21, 2012 at 12:33:07PM +0200, Peter Ujfalusi wrote:
> > > > I'm not sure hwo we could handle that properly. Either by letting Tony
> > > > carrying this patchset, or by sending me the panda patch that adds those
> > > > structures. As you prefer.
> > >
> > > If Liam would take this series that would be probably the way forward.
> > > If he does not have objections.
> > > Liam: I can create a branch for you to pull from as soon as all other
> > > patch receives the needed acks...
> > >
> > > Samuel: if Liam agrees is it possible for you to drop the twl6040
> > > related patches from your for-next branch?
> > That would make sense to me, yes.
> > Liam, if you're ok with taking it, please add my:
> >
> > Acked-by: Samuel Ortiz <[email protected]>
> >
>
> Ok, sounds fine by me. Tony is this fine wrt the OMAP board file
> updates ?

Yeah looks OK to me, acked that patch. Let me know if there are
others I should look.

Thanks,

Tony

2012-02-22 07:34:53

by Peter Ujfalusi

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] MFD: twl6040: Conversion to i2c driver

Hi Tony,

On 02/21/2012 08:44 PM, Tony Lindgren wrote:
> Yeah looks OK to me, acked that patch. Let me know if there are
> others I should look.

I would appreciate if you could take a look at this series as well:
TWL6040: Regulator support
http://marc.info/?l=linux-omap&m=132947934522602&w=2

I have separated the twl6040 i2c driver conversion, and regulator
support since they are dealing with different issues.
If you know who should look at the drivers/regulator/twl-regulator.c,
drivers/mfd/twl.c changes could you CC them as well?

Regards,
P?ter