// SPDX-License-Identifier: GPL-2.0-or-later
/*
* wm8753.c -- WM8753 ALSA Soc Audio driver
*
* Copyright 2003-11 Wolfson Microelectronics PLC.
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
*
* Notes:
* The WM8753 is a low power, high quality stereo codec with integrated PCM
* codec designed for portable digital telephony applications.
*
* Dual DAI:-
*
* This driver support 2 DAI PCM's. This makes the default PCM available for
* HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for
* voice.
*
* Please note that the voice PCM can be connected directly to a Bluetooth
* codec or GSM modem and thus cannot be read or written to, although it is
* available to be configured with snd_hw_params(), etc and kcontrols in the
* normal alsa manner.
*
* Fast DAI switching:-
*
* The driver can now fast switch between the DAI configurations via a
* an alsa kcontrol. This allows the PCM to remain open.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <asm/div64.h>
#include "wm8753.h"
static int caps_charge = 2000;
module_param(caps_charge, int, 0);
MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
static int wm8753_hifi_write_dai_fmt(struct snd_soc_component *component,
unsigned int fmt);
static int wm8753_voice_write_dai_fmt(struct snd_soc_component *component,
unsigned int fmt);
/*
* wm8753 register cache
* We can't read the WM8753 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
static const struct reg_default wm8753_reg_defaults[] = {
{ 0x00, 0x0000 },
{ 0x01, 0x0008 },
{ 0x02, 0x0000 },
{ 0x03, 0x000a },
{ 0x04, 0x000a },
{ 0x05, 0x0033 },
{ 0x06, 0x0000 },
{ 0x07, 0x0007 },
{ 0x08, 0x00ff },
{ 0x09, 0x00ff },
{ 0x0a, 0x000f },
{ 0x0b, 0x000f },
{ 0x0c, 0x007b },
{ 0x0d, 0x0000 },
{ 0x0e, 0x0032 },
{ 0x0f, 0x0000 },
{ 0x10, 0x00c3 },
{ 0x11, 0x00c3 },
{ 0x12, 0x00c0 },
{ 0x13, 0x0000 },
{ 0x14, 0x0000 },
{ 0x15, 0x0000 },
{ 0x16, 0x0000 },
{ 0x17, 0x0000 },
{ 0x18, 0x0000 },
{ 0x19, 0x0000 },
{ 0x1a, 0x0000 },
{ 0x1b, 0x0000 },
{ 0x1c, 0x0000 },
{ 0x1d, 0x0000 },
{ 0x1e, 0x0000 },
{ 0x1f, 0x0000 },
{ 0x20, 0x0055 },
{ 0x21, 0x0005 },
{ 0x22, 0x0050 },
{ 0x23, 0x0055 },
{ 0x24, 0x0050 },
{ 0x25, 0x0055 },
{ 0x26, 0x0050 },
{ 0x27, 0x0055 },
{ 0x28, 0x0079 },
{ 0x29, 0x0079 },
{ 0x2a, 0x0079 },
{ 0x2b, 0x0079 },
{ 0x2c, 0x0079 },
{ 0x2d, 0x0000 },
{ 0x2e, 0x0000 },
{ 0x2f, 0x0000 },
{ 0x30, 0x0000 },
{ 0x31, 0x0097 },
{ 0x32, 0x0097 },
{ 0x33, 0x0000 },
{ 0x34, 0x0004 },
{ 0x35, 0x0000 },
{ 0x36, 0x0083 },
{ 0x37, 0x0024 },
{ 0x38, 0x01ba },
{ 0x39, 0x0000 },
{ 0x3a, 0x0083 },
{ 0x3b, 0x0024 },
{ 0x3c, 0x01ba },
{ 0x3d, 0x0000 },
{ 0x3e, 0x0000 },
{ 0x3f, 0x0000 },
};
static bool wm8753_volatile(struct device *dev, unsigned int reg)
{
return reg == WM8753_RESET;
}
/* codec private data */
struct wm8753_priv {
struct regmap *regmap;
unsigned int sysclk;
unsigned int pcmclk;
unsigned int voice_fmt;
unsigned int hifi_fmt;
int dai_func;
struct delayed_work charge_work;
};
#define wm8753_reset(c) snd_soc_component_write(c, WM8753_RESET, 0)
/*
* WM8753 Controls
|