Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * arizona-spi.c  --  Arizona SPI bus interface
0004  *
0005  * Copyright 2012 Wolfson Microelectronics plc
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0008  */
0009 
0010 #include <linux/acpi.h>
0011 #include <linux/err.h>
0012 #include <linux/gpio/consumer.h>
0013 #include <linux/gpio/machine.h>
0014 #include <linux/module.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/regmap.h>
0017 #include <linux/regulator/consumer.h>
0018 #include <linux/slab.h>
0019 #include <linux/spi/spi.h>
0020 #include <linux/of.h>
0021 #include <uapi/linux/input-event-codes.h>
0022 
0023 #include <linux/mfd/arizona/core.h>
0024 
0025 #include "arizona.h"
0026 
0027 #ifdef CONFIG_ACPI
0028 static const struct acpi_gpio_params reset_gpios = { 1, 0, false };
0029 static const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
0030 
0031 static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
0032     { "reset-gpios", &reset_gpios, 1, },
0033     { "wlf,ldoena-gpios", &ldoena_gpios, 1 },
0034     { }
0035 };
0036 
0037 /*
0038  * The ACPI resources for the device only describe external GPIO-s. They do
0039  * not provide mappings for the GPIO-s coming from the Arizona codec itself.
0040  */
0041 static const struct gpiod_lookup arizona_soc_gpios[] = {
0042     { "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
0043     { "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
0044 };
0045 
0046 static void arizona_spi_acpi_remove_lookup(void *lookup)
0047 {
0048     gpiod_remove_lookup_table(lookup);
0049 }
0050 
0051 /* For ACPI tables from boards which ship with Windows as factory OS */
0052 static int arizona_spi_acpi_windows_probe(struct arizona *arizona)
0053 {
0054     struct gpiod_lookup_table *lookup;
0055     acpi_status status;
0056     int ret;
0057 
0058     /* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
0059     devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
0060 
0061     /* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
0062     lookup = devm_kzalloc(arizona->dev,
0063                   struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
0064                   GFP_KERNEL);
0065     if (!lookup)
0066         return -ENOMEM;
0067 
0068     lookup->dev_id = dev_name(arizona->dev);
0069     memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
0070 
0071     gpiod_add_lookup_table(lookup);
0072     ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
0073     if (ret)
0074         return ret;
0075 
0076     /* Enable 32KHz clock from SoC to codec for jack-detect */
0077     status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
0078     if (ACPI_FAILURE(status))
0079         dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
0080 
0081     return 0;
0082 }
0083 
0084 /* For ACPI tables from boards which ship with Android as factory OS */
0085 static int arizona_spi_acpi_android_probe(struct arizona *arizona)
0086 {
0087     int ret;
0088 
0089     /*
0090      * Get the reset GPIO, treating -ENOENT as -EPROBE_DEFER to wait for
0091      * the x86-android-tablets module to register the board specific GPIO
0092      * lookup table.
0093      */
0094     arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset", GPIOD_OUT_LOW);
0095     if (IS_ERR(arizona->pdata.reset)) {
0096         ret = PTR_ERR(arizona->pdata.reset);
0097         if (ret == -ENOENT) {
0098             dev_info_once(arizona->dev,
0099                       "Deferring probe till GPIO lookup is registered\n");
0100             ret = -EPROBE_DEFER;
0101         }
0102         return dev_err_probe(arizona->dev, ret, "getting reset GPIO\n");
0103     }
0104 
0105     return 0;
0106 }
0107 
0108 /*
0109  * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
0110  * Function A Play/Pause:           0 ohm
0111  * Function D Voice assistant:    135 ohm
0112  * Function B Volume Up           240 ohm
0113  * Function C Volume Down         470 ohm
0114  * Minimum Mic DC resistance     1000 ohm
0115  * Minimum Ear speaker impedance   16 ohm
0116  * Note the first max value below must be less then the min. speaker impedance,
0117  * to allow CTIA/OMTP detection to work. The other max values are the closest
0118  * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
0119  */
0120 static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
0121     { .max =  11, .key = KEY_PLAYPAUSE },
0122     { .max = 186, .key = KEY_VOICECOMMAND },
0123     { .max = 348, .key = KEY_VOLUMEUP },
0124     { .max = 752, .key = KEY_VOLUMEDOWN },
0125 };
0126 
0127 static int arizona_spi_acpi_probe(struct arizona *arizona)
0128 {
0129     struct acpi_device *adev = ACPI_COMPANION(arizona->dev);
0130     int ret;
0131 
0132     if (acpi_dev_hid_uid_match(adev, "10WM5102", NULL))
0133         ret = arizona_spi_acpi_android_probe(arizona);
0134     else
0135         ret = arizona_spi_acpi_windows_probe(arizona);
0136 
0137     if (ret)
0138         return ret;
0139 
0140     /*
0141      * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
0142      * The IRQ line will stay low when a new IRQ event happens between reading
0143      * the IRQ status flags and acknowledging them. When the IRQ line stays
0144      * low like this the IRQ will never trigger again when its type is set
0145      * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
0146      *
0147      * Note theoretically it is possible that some boards are not capable
0148      * of handling active low level interrupts. In that case setting the
0149      * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
0150      * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
0151      * are a bug in the board's DSDT.
0152      */
0153     arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
0154 
0155     /* Wait 200 ms after jack insertion */
0156     arizona->pdata.micd_detect_debounce = 200;
0157 
0158     /* Use standard AOSP values for headset-button mappings */
0159     arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
0160     arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
0161 
0162     return 0;
0163 }
0164 
0165 static const struct acpi_device_id arizona_acpi_match[] = {
0166     {
0167         .id = "WM510204",
0168         .driver_data = WM5102,
0169     },
0170     {
0171         .id = "WM510205",
0172         .driver_data = WM5102,
0173     },
0174     {
0175         .id = "10WM5102",
0176         .driver_data = WM5102,
0177     },
0178     { }
0179 };
0180 MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
0181 #else
0182 static int arizona_spi_acpi_probe(struct arizona *arizona)
0183 {
0184     return -ENODEV;
0185 }
0186 #endif
0187 
0188 static int arizona_spi_probe(struct spi_device *spi)
0189 {
0190     const struct spi_device_id *id = spi_get_device_id(spi);
0191     const void *match_data;
0192     struct arizona *arizona;
0193     const struct regmap_config *regmap_config = NULL;
0194     unsigned long type = 0;
0195     int ret;
0196 
0197     match_data = device_get_match_data(&spi->dev);
0198     if (match_data)
0199         type = (unsigned long)match_data;
0200     else if (id)
0201         type = id->driver_data;
0202 
0203     switch (type) {
0204     case WM5102:
0205         if (IS_ENABLED(CONFIG_MFD_WM5102))
0206             regmap_config = &wm5102_spi_regmap;
0207         break;
0208     case WM5110:
0209     case WM8280:
0210         if (IS_ENABLED(CONFIG_MFD_WM5110))
0211             regmap_config = &wm5110_spi_regmap;
0212         break;
0213     case WM1831:
0214     case CS47L24:
0215         if (IS_ENABLED(CONFIG_MFD_CS47L24))
0216             regmap_config = &cs47l24_spi_regmap;
0217         break;
0218     default:
0219         dev_err(&spi->dev, "Unknown device type %ld\n", type);
0220         return -EINVAL;
0221     }
0222 
0223     if (!regmap_config) {
0224         dev_err(&spi->dev,
0225             "No kernel support for device type %ld\n", type);
0226         return -EINVAL;
0227     }
0228 
0229     arizona = devm_kzalloc(&spi->dev, sizeof(*arizona), GFP_KERNEL);
0230     if (arizona == NULL)
0231         return -ENOMEM;
0232 
0233     arizona->regmap = devm_regmap_init_spi(spi, regmap_config);
0234     if (IS_ERR(arizona->regmap)) {
0235         ret = PTR_ERR(arizona->regmap);
0236         dev_err(&spi->dev, "Failed to allocate register map: %d\n",
0237             ret);
0238         return ret;
0239     }
0240 
0241     arizona->type = type;
0242     arizona->dev = &spi->dev;
0243     arizona->irq = spi->irq;
0244 
0245     if (has_acpi_companion(&spi->dev)) {
0246         ret = arizona_spi_acpi_probe(arizona);
0247         if (ret)
0248             return ret;
0249     }
0250 
0251     return arizona_dev_init(arizona);
0252 }
0253 
0254 static void arizona_spi_remove(struct spi_device *spi)
0255 {
0256     struct arizona *arizona = spi_get_drvdata(spi);
0257 
0258     arizona_dev_exit(arizona);
0259 }
0260 
0261 static const struct spi_device_id arizona_spi_ids[] = {
0262     { "wm5102", WM5102 },
0263     { "wm5110", WM5110 },
0264     { "wm8280", WM8280 },
0265     { "wm1831", WM1831 },
0266     { "cs47l24", CS47L24 },
0267     { },
0268 };
0269 MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
0270 
0271 #ifdef CONFIG_OF
0272 static const struct of_device_id arizona_spi_of_match[] = {
0273     { .compatible = "wlf,wm5102", .data = (void *)WM5102 },
0274     { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
0275     { .compatible = "wlf,wm8280", .data = (void *)WM8280 },
0276     { .compatible = "wlf,wm1831", .data = (void *)WM1831 },
0277     { .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
0278     {},
0279 };
0280 #endif
0281 
0282 static struct spi_driver arizona_spi_driver = {
0283     .driver = {
0284         .name   = "arizona",
0285         .pm = &arizona_pm_ops,
0286         .of_match_table = of_match_ptr(arizona_spi_of_match),
0287         .acpi_match_table = ACPI_PTR(arizona_acpi_match),
0288     },
0289     .probe      = arizona_spi_probe,
0290     .remove     = arizona_spi_remove,
0291     .id_table   = arizona_spi_ids,
0292 };
0293 
0294 module_spi_driver(arizona_spi_driver);
0295 
0296 MODULE_SOFTDEP("pre: arizona_ldo1");
0297 MODULE_DESCRIPTION("Arizona SPI bus interface");
0298 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0299 MODULE_LICENSE("GPL");