Commit 6887b042 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Lee Jones

mfd: arizona: Add support for WM8998 and WM1814

Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.wolfsonmicro.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent bc00d68f
...@@ -1379,6 +1379,12 @@ config MFD_WM8997 ...@@ -1379,6 +1379,12 @@ config MFD_WM8997
help help
Support for Wolfson Microelectronics WM8997 low power audio SoC Support for Wolfson Microelectronics WM8997 low power audio SoC
config MFD_WM8998
bool "Wolfson Microelectronics WM8998"
depends on MFD_ARIZONA
help
Support for Wolfson Microelectronics WM8998 low power audio SoC
config MFD_WM8400 config MFD_WM8400
bool "Wolfson Microelectronics WM8400" bool "Wolfson Microelectronics WM8400"
select MFD_CORE select MFD_CORE
......
...@@ -48,6 +48,9 @@ endif ...@@ -48,6 +48,9 @@ endif
ifeq ($(CONFIG_MFD_WM8997),y) ifeq ($(CONFIG_MFD_WM8997),y)
obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o
endif endif
ifeq ($(CONFIG_MFD_WM8998),y)
obj-$(CONFIG_MFD_ARIZONA) += wm8998-tables.o
endif
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
wm831x-objs += wm831x-auxadc.o wm831x-objs += wm831x-auxadc.o
......
...@@ -146,17 +146,31 @@ static irqreturn_t arizona_underclocked(int irq, void *data) ...@@ -146,17 +146,31 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
static irqreturn_t arizona_overclocked(int irq, void *data) static irqreturn_t arizona_overclocked(int irq, void *data)
{ {
struct arizona *arizona = data; struct arizona *arizona = data;
unsigned int val[2]; unsigned int val[3];
int ret; int ret;
ret = regmap_bulk_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_6, ret = regmap_bulk_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_6,
&val[0], 2); &val[0], 3);
if (ret != 0) { if (ret != 0) {
dev_err(arizona->dev, "Failed to read overclock status: %d\n", dev_err(arizona->dev, "Failed to read overclock status: %d\n",
ret); ret);
return IRQ_NONE; return IRQ_NONE;
} }
switch (arizona->type) {
case WM8998:
case WM1814:
/* Some bits are shifted on WM8998,
* rearrange to match the standard bit layout
*/
val[0] = ((val[0] & 0x60e0) >> 1) |
((val[0] & 0x1e00) >> 2) |
(val[0] & 0x000f);
break;
default:
break;
}
if (val[0] & ARIZONA_PWM_OVERCLOCKED_STS) if (val[0] & ARIZONA_PWM_OVERCLOCKED_STS)
dev_err(arizona->dev, "PWM overclocked\n"); dev_err(arizona->dev, "PWM overclocked\n");
if (val[0] & ARIZONA_FX_CORE_OVERCLOCKED_STS) if (val[0] & ARIZONA_FX_CORE_OVERCLOCKED_STS)
...@@ -201,6 +215,9 @@ static irqreturn_t arizona_overclocked(int irq, void *data) ...@@ -201,6 +215,9 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS) if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
dev_err(arizona->dev, "ISRC1 overclocked\n"); dev_err(arizona->dev, "ISRC1 overclocked\n");
if (val[2] & ARIZONA_SPDIF_OVERCLOCKED_STS)
dev_err(arizona->dev, "SPDIF overclocked\n");
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -806,6 +823,8 @@ const struct of_device_id arizona_of_match[] = { ...@@ -806,6 +823,8 @@ const struct of_device_id arizona_of_match[] = {
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 }, { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 }, { .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 }, { .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{ .compatible = "wlf,wm8998", .data = (void *)WM8998 },
{ .compatible = "wlf,wm1814", .data = (void *)WM1814 },
{}, {},
}; };
EXPORT_SYMBOL_GPL(arizona_of_match); EXPORT_SYMBOL_GPL(arizona_of_match);
...@@ -887,11 +906,28 @@ static const struct mfd_cell wm8997_devs[] = { ...@@ -887,11 +906,28 @@ static const struct mfd_cell wm8997_devs[] = {
}, },
}; };
static const struct mfd_cell wm8998_devs[] = {
{
.name = "arizona-extcon",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{
.name = "wm8998-codec",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
},
{ .name = "arizona-micsupp" },
};
int arizona_dev_init(struct arizona *arizona) int arizona_dev_init(struct arizona *arizona)
{ {
struct device *dev = arizona->dev; struct device *dev = arizona->dev;
const char *type_name; const char *type_name;
unsigned int reg, val; unsigned int reg, val, mask;
int (*apply_patch)(struct arizona *) = NULL; int (*apply_patch)(struct arizona *) = NULL;
int ret, i; int ret, i;
...@@ -911,6 +947,8 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -911,6 +947,8 @@ int arizona_dev_init(struct arizona *arizona)
case WM5110: case WM5110:
case WM8280: case WM8280:
case WM8997: case WM8997:
case WM8998:
case WM1814:
for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++) for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
arizona->core_supplies[i].supply arizona->core_supplies[i].supply
= wm5102_core_supplies[i]; = wm5102_core_supplies[i];
...@@ -992,6 +1030,7 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -992,6 +1030,7 @@ int arizona_dev_init(struct arizona *arizona)
switch (reg) { switch (reg) {
case 0x5102: case 0x5102:
case 0x5110: case 0x5110:
case 0x6349:
case 0x8997: case 0x8997:
break; break;
default: default:
...@@ -1092,6 +1131,27 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -1092,6 +1131,27 @@ int arizona_dev_init(struct arizona *arizona)
} }
apply_patch = wm8997_patch; apply_patch = wm8997_patch;
break; break;
#endif
#ifdef CONFIG_MFD_WM8998
case 0x6349:
switch (arizona->type) {
case WM8998:
type_name = "WM8998";
break;
case WM1814:
type_name = "WM1814";
break;
default:
type_name = "WM8998";
dev_err(arizona->dev, "WM8998 registered as %d\n",
arizona->type);
arizona->type = WM8998;
}
apply_patch = wm8998_patch;
break;
#endif #endif
default: default:
dev_err(arizona->dev, "Unknown device ID %x\n", reg); dev_err(arizona->dev, "Unknown device ID %x\n", reg);
...@@ -1208,14 +1268,38 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -1208,14 +1268,38 @@ int arizona_dev_init(struct arizona *arizona)
<< ARIZONA_IN1_DMIC_SUP_SHIFT; << ARIZONA_IN1_DMIC_SUP_SHIFT;
if (arizona->pdata.inmode[i] & ARIZONA_INMODE_DMIC) if (arizona->pdata.inmode[i] & ARIZONA_INMODE_DMIC)
val |= 1 << ARIZONA_IN1_MODE_SHIFT; val |= 1 << ARIZONA_IN1_MODE_SHIFT;
switch (arizona->type) {
case WM8998:
case WM1814:
regmap_update_bits(arizona->regmap,
ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 8),
ARIZONA_IN1L_SRC_SE_MASK,
(arizona->pdata.inmode[i] & ARIZONA_INMODE_SE)
<< ARIZONA_IN1L_SRC_SE_SHIFT);
regmap_update_bits(arizona->regmap,
ARIZONA_ADC_DIGITAL_VOLUME_1R + (i * 8),
ARIZONA_IN1R_SRC_SE_MASK,
(arizona->pdata.inmode[i] & ARIZONA_INMODE_SE)
<< ARIZONA_IN1R_SRC_SE_SHIFT);
mask = ARIZONA_IN1_DMIC_SUP_MASK |
ARIZONA_IN1_MODE_MASK;
break;
default:
if (arizona->pdata.inmode[i] & ARIZONA_INMODE_SE) if (arizona->pdata.inmode[i] & ARIZONA_INMODE_SE)
val |= 1 << ARIZONA_IN1_SINGLE_ENDED_SHIFT; val |= 1 << ARIZONA_IN1_SINGLE_ENDED_SHIFT;
mask = ARIZONA_IN1_DMIC_SUP_MASK |
ARIZONA_IN1_MODE_MASK |
ARIZONA_IN1_SINGLE_ENDED_MASK;
break;
}
regmap_update_bits(arizona->regmap, regmap_update_bits(arizona->regmap,
ARIZONA_IN1L_CONTROL + (i * 8), ARIZONA_IN1L_CONTROL + (i * 8),
ARIZONA_IN1_DMIC_SUP_MASK | mask, val);
ARIZONA_IN1_MODE_MASK |
ARIZONA_IN1_SINGLE_ENDED_MASK, val);
} }
for (i = 0; i < ARIZONA_MAX_OUTPUT; i++) { for (i = 0; i < ARIZONA_MAX_OUTPUT; i++) {
...@@ -1271,6 +1355,11 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -1271,6 +1355,11 @@ int arizona_dev_init(struct arizona *arizona)
ret = mfd_add_devices(arizona->dev, -1, wm8997_devs, ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
ARRAY_SIZE(wm8997_devs), NULL, 0, NULL); ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
break; break;
case WM8998:
case WM1814:
ret = mfd_add_devices(arizona->dev, -1, wm8998_devs,
ARRAY_SIZE(wm8998_devs), NULL, 0, NULL);
break;
} }
if (ret != 0) { if (ret != 0) {
......
...@@ -52,6 +52,12 @@ static int arizona_i2c_probe(struct i2c_client *i2c, ...@@ -52,6 +52,12 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
case WM8997: case WM8997:
regmap_config = &wm8997_i2c_regmap; regmap_config = &wm8997_i2c_regmap;
break; break;
#endif
#ifdef CONFIG_MFD_WM8998
case WM8998:
case WM1814:
regmap_config = &wm8998_i2c_regmap;
break;
#endif #endif
default: default:
dev_err(&i2c->dev, "Unknown device type %ld\n", dev_err(&i2c->dev, "Unknown device type %ld\n",
...@@ -90,6 +96,8 @@ static const struct i2c_device_id arizona_i2c_id[] = { ...@@ -90,6 +96,8 @@ static const struct i2c_device_id arizona_i2c_id[] = {
{ "wm5110", WM5110 }, { "wm5110", WM5110 },
{ "wm8280", WM8280 }, { "wm8280", WM8280 },
{ "wm8997", WM8997 }, { "wm8997", WM8997 },
{ "wm8998", WM8998 },
{ "wm1814", WM1814 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, arizona_i2c_id); MODULE_DEVICE_TABLE(i2c, arizona_i2c_id);
......
...@@ -234,6 +234,15 @@ int arizona_irq_init(struct arizona *arizona) ...@@ -234,6 +234,15 @@ int arizona_irq_init(struct arizona *arizona)
arizona->ctrlif_error = false; arizona->ctrlif_error = false;
break; break;
#endif #endif
#ifdef CONFIG_MFD_WM8998
case WM8998:
case WM1814:
aod = &wm8998_aod;
irq = &wm8998_irq;
arizona->ctrlif_error = false;
break;
#endif
default: default:
BUG_ON("Unknown Arizona class device" == NULL); BUG_ON("Unknown Arizona class device" == NULL);
return -EINVAL; return -EINVAL;
......
...@@ -27,6 +27,8 @@ extern const struct regmap_config wm5110_spi_regmap; ...@@ -27,6 +27,8 @@ extern const struct regmap_config wm5110_spi_regmap;
extern const struct regmap_config wm8997_i2c_regmap; extern const struct regmap_config wm8997_i2c_regmap;
extern const struct regmap_config wm8998_i2c_regmap;
extern const struct dev_pm_ops arizona_pm_ops; extern const struct dev_pm_ops arizona_pm_ops;
extern const struct of_device_id arizona_of_match[]; extern const struct of_device_id arizona_of_match[];
...@@ -41,6 +43,9 @@ extern const struct regmap_irq_chip wm5110_revd_irq; ...@@ -41,6 +43,9 @@ extern const struct regmap_irq_chip wm5110_revd_irq;
extern const struct regmap_irq_chip wm8997_aod; extern const struct regmap_irq_chip wm8997_aod;
extern const struct regmap_irq_chip wm8997_irq; extern const struct regmap_irq_chip wm8997_irq;
extern struct regmap_irq_chip wm8998_aod;
extern struct regmap_irq_chip wm8998_irq;
int arizona_dev_init(struct arizona *arizona); int arizona_dev_init(struct arizona *arizona);
int arizona_dev_exit(struct arizona *arizona); int arizona_dev_exit(struct arizona *arizona);
int arizona_irq_init(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona);
......
This diff is collapsed.
...@@ -25,6 +25,8 @@ enum arizona_type { ...@@ -25,6 +25,8 @@ enum arizona_type {
WM5110 = 2, WM5110 = 2,
WM8997 = 3, WM8997 = 3,
WM8280 = 4, WM8280 = 4,
WM8998 = 5,
WM1814 = 6,
}; };
#define ARIZONA_IRQ_GP1 0 #define ARIZONA_IRQ_GP1 0
...@@ -165,6 +167,7 @@ static inline int wm5102_patch(struct arizona *arizona) ...@@ -165,6 +167,7 @@ static inline int wm5102_patch(struct arizona *arizona)
int wm5110_patch(struct arizona *arizona); int wm5110_patch(struct arizona *arizona);
int wm8997_patch(struct arizona *arizona); int wm8997_patch(struct arizona *arizona);
int wm8998_patch(struct arizona *arizona);
extern int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop, extern int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop,
bool mandatory); bool mandatory);
......
...@@ -162,6 +162,8 @@ struct arizona_pdata { ...@@ -162,6 +162,8 @@ struct arizona_pdata {
/** /**
* Mode of input structures * Mode of input structures
* One of the ARIZONA_INMODE_xxx values * One of the ARIZONA_INMODE_xxx values
* wm5102/wm5110/wm8280/wm8997: [0]=IN1 [1]=IN2 [2]=IN3 [3]=IN4
* wm8998: [0]=IN1A [1]=IN2A [2]=IN1B [3]=IN2B
*/ */
int inmode[ARIZONA_MAX_INPUT]; int inmode[ARIZONA_MAX_INPUT];
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment