mfd: arizona: Add support for WM8998 and WM1814
Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index e60bcd9..bc814b0 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -146,17 +146,31 @@
static irqreturn_t arizona_overclocked(int irq, void *data)
{
struct arizona *arizona = data;
- unsigned int val[2];
+ unsigned int val[3];
int ret;
ret = regmap_bulk_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_6,
- &val[0], 2);
+ &val[0], 3);
if (ret != 0) {
dev_err(arizona->dev, "Failed to read overclock status: %d\n",
ret);
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)
dev_err(arizona->dev, "PWM overclocked\n");
if (val[0] & ARIZONA_FX_CORE_OVERCLOCKED_STS)
@@ -201,6 +215,9 @@
if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
dev_err(arizona->dev, "ISRC1 overclocked\n");
+ if (val[2] & ARIZONA_SPDIF_OVERCLOCKED_STS)
+ dev_err(arizona->dev, "SPDIF overclocked\n");
+
return IRQ_HANDLED;
}
@@ -806,6 +823,8 @@
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
+ { .compatible = "wlf,wm8998", .data = (void *)WM8998 },
+ { .compatible = "wlf,wm1814", .data = (void *)WM1814 },
{},
};
EXPORT_SYMBOL_GPL(arizona_of_match);
@@ -887,11 +906,28 @@
},
};
+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)
{
struct device *dev = arizona->dev;
const char *type_name;
- unsigned int reg, val;
+ unsigned int reg, val, mask;
int (*apply_patch)(struct arizona *) = NULL;
int ret, i;
@@ -911,6 +947,8 @@
case WM5110:
case WM8280:
case WM8997:
+ case WM8998:
+ case WM1814:
for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
arizona->core_supplies[i].supply
= wm5102_core_supplies[i];
@@ -992,6 +1030,7 @@
switch (reg) {
case 0x5102:
case 0x5110:
+ case 0x6349:
case 0x8997:
break;
default:
@@ -1093,6 +1132,27 @@
apply_patch = wm8997_patch;
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
default:
dev_err(arizona->dev, "Unknown device ID %x\n", reg);
goto err_reset;
@@ -1208,14 +1268,38 @@
<< ARIZONA_IN1_DMIC_SUP_SHIFT;
if (arizona->pdata.inmode[i] & ARIZONA_INMODE_DMIC)
val |= 1 << ARIZONA_IN1_MODE_SHIFT;
- if (arizona->pdata.inmode[i] & ARIZONA_INMODE_SE)
- val |= 1 << ARIZONA_IN1_SINGLE_ENDED_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)
+ 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,
ARIZONA_IN1L_CONTROL + (i * 8),
- ARIZONA_IN1_DMIC_SUP_MASK |
- ARIZONA_IN1_MODE_MASK |
- ARIZONA_IN1_SINGLE_ENDED_MASK, val);
+ mask, val);
}
for (i = 0; i < ARIZONA_MAX_OUTPUT; i++) {
@@ -1271,6 +1355,11 @@
ret = mfd_add_devices(arizona->dev, -1, wm8997_devs,
ARRAY_SIZE(wm8997_devs), NULL, 0, NULL);
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) {