// SPDX-License-Identifier: GPL-2.0-only
/*
* bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
* (derived from bytcr_rt5640.c)
*
* Copyright (C) 2015 Intel Corp
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/input.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include <sound/soc-acpi.h>
#include "../../codecs/rt5651.h"
#include "../atom/sst-atom-controls.h"
#include "../common/soc-intel-quirks.h"
enum {
BYT_RT5651_DMIC_MAP,
BYT_RT5651_IN1_MAP,
BYT_RT5651_IN2_MAP,
BYT_RT5651_IN1_IN2_MAP,
};
enum {
BYT_RT5651_JD_NULL = (RT5651_JD_NULL << 4),
BYT_RT5651_JD1_1 = (RT5651_JD1_1 << 4),
BYT_RT5651_JD1_2 = (RT5651_JD1_2 << 4),
BYT_RT5651_JD2 = (RT5651_JD2 << 4),
};
enum {
BYT_RT5651_OVCD_TH_600UA = (6 << 8),
BYT_RT5651_OVCD_TH_1500UA = (15 << 8),
BYT_RT5651_OVCD_TH_2000UA = (20 << 8),
};
enum {
BYT_RT5651_OVCD_SF_0P5 = (RT5651_OVCD_SF_0P5 << 13),
BYT_RT5651_OVCD_SF_0P75 = (RT5651_OVCD_SF_0P75 << 13),
BYT_RT5651_OVCD_SF_1P0 = (RT5651_OVCD_SF_1P0 << 13),
BYT_RT5651_OVCD_SF_1P5 = (RT5651_OVCD_SF_1P5 << 13),
};
#define BYT_RT5651_MAP(quirk) ((quirk) & GENMASK(3, 0))
#define BYT_RT5651_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4)
#define BYT_RT5651_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8)
#define BYT_RT5651_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13)
#define BYT_RT5651_DMIC_EN BIT(16)
#define BYT_RT5651_MCLK_EN BIT(17)
#define BYT_RT5651_MCLK_25MHZ BIT(18)
#define BYT_RT5651_SSP2_AIF2 BIT(19) /* default is using AIF1 */
#define BYT_RT5651_SSP0_AIF1 BIT(20)
#define BYT_RT5651_SSP0_AIF2 BIT(21)
#define BYT_RT5651_HP_LR_SWAPPED BIT(22)
#define BYT_RT5651_MONO_SPEAKER BIT(23)
#define BYT_RT5651_JD_NOT_INV BIT(24)
#define BYT_RT5651_DEFAULT_QUIRKS (BYT_RT5651_MCLK_EN | \
BYT_RT5651_JD1_1 | \
BYT_RT5651_OVCD_TH_2000UA | \
BYT_RT5651_OVCD_SF_0P75)
/* jack-detect-source + inv + dmic-en + ovcd-th + -sf + terminating entry */
#define MAX_NO_PROPS 6
struct byt_rt5651_private {
struct clk *mclk;
struct gpio_desc *ext_amp_gpio;
struct gpio_desc *hp_detect;
struct snd_soc_jack jack;
};
static const struct acpi_gpio_mapping *byt_rt5651_gpios;
/* Default: jack-detect on JD1_1, internal mic on in2, headsetmic on in3 */
static unsigned long byt_rt5651_quirk = BYT_RT5651_DEFAULT_QUIRKS |
BYT_RT5651_IN2_MAP;
static int quirk_override = -1;
module_param_named(quirk, quirk_override, int, 0444);
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
static void log_quirks(struct device *dev)
{
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP)
dev_info(dev, "quirk DMIC_MAP enabled");
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP)
dev_info(dev, "quirk IN1_MAP enabled");
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP)
dev_info(dev, "quirk IN2_MAP enabled");
if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_IN2_MAP)
dev_info(dev, "quirk IN1_IN2_MAP enabled");
if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
BYT_RT5651_JDSRC(byt_rt5651_quirk));
dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",
BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100);
dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",
BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
}
if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
dev_info(dev, "quirk DMIC enabled");
if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
dev_info(dev, "quirk MCLK_EN enabled");
if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
dev_info(dev, "quirk MCLK_25MHZ enabled");
if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
dev_info(dev, "quirk SSP2_AIF2 enabled\n");
if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
dev_info(dev, "quirk SSP0_AIF1 enabled\n