mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +02:00
ASoC: codecs: Add support for FourSemi FS2104/5S
Merge series from Nick Li <nick.li@foursemi.com>: The FS2104/5S are Inductor-Less, Stereo, Closed-Loop, Digital Input Class-D Power Amplifiers with Enhanced Signal Processing. FS2104 can deliver 2x15W into 4ohm BTL speaker loads, FS2105S can deliver 2x30W into 8ohm BTL speaker loads. Most functions have been built and tested on EVB boards: ARMv8-A, Linux version 6.16.0-rc6-v8
This commit is contained in:
commit
54401b5d9f
101
Documentation/devicetree/bindings/sound/foursemi,fs2105s.yaml
Normal file
101
Documentation/devicetree/bindings/sound/foursemi,fs2105s.yaml
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/foursemi,fs2105s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: FourSemi FS2104/5S Digital Audio Amplifier
|
||||
|
||||
maintainers:
|
||||
- Nick Li <nick.li@foursemi.com>
|
||||
|
||||
description:
|
||||
The FS2104 is a 15W Inductor-Less, Stereo, Closed-Loop,
|
||||
Digital Input Class-D Power Amplifier with Enhanced Signal Processing.
|
||||
The FS2105S is a 30W Inductor-Less, Stereo, Closed-Loop,
|
||||
Digital Input Class-D Power Amplifier with Enhanced Signal Processing.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- foursemi,fs2104
|
||||
- const: foursemi,fs2105s
|
||||
- enum:
|
||||
- foursemi,fs2105s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The clock of I2S BCLK
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bclk
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
pvdd-supply:
|
||||
description:
|
||||
Regulator for power supply(PVDD in datasheet).
|
||||
|
||||
dvdd-supply:
|
||||
description:
|
||||
Regulator for digital supply(DVDD in datasheet).
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
It's the SDZ pin in datasheet, the pin is active low,
|
||||
it will power down and reset the chip to shut down state.
|
||||
|
||||
firmware-name:
|
||||
maxItems: 1
|
||||
description: |
|
||||
The firmware(*.bin) contains:
|
||||
a. Register initialization settings
|
||||
b. DSP effect parameters
|
||||
c. Multi-scene sound effect configurations(optional)
|
||||
It's gernerated by FourSemi's tuning tool.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#sound-dai-cells'
|
||||
- pvdd-supply
|
||||
- dvdd-supply
|
||||
- reset-gpios
|
||||
- firmware-name
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
audio-codec@68 {
|
||||
compatible = "foursemi,fs2105s";
|
||||
reg = <0x68>;
|
||||
clocks = <&clocks 18>;
|
||||
clock-names = "bclk";
|
||||
#sound-dai-cells = <0>;
|
||||
pvdd-supply = <&pvdd_supply>;
|
||||
dvdd-supply = <&dvdd_supply>;
|
||||
reset-gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
|
||||
firmware-name = "fs2105s-btl-2p0-0s.bin";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&fs210x_pins_default>;
|
||||
};
|
||||
};
|
||||
|
|
@ -552,6 +552,8 @@ patternProperties:
|
|||
description: FocalTech Systems Co.,Ltd
|
||||
"^forlinx,.*":
|
||||
description: Baoding Forlinx Embedded Technology Co., Ltd.
|
||||
"^foursemi,.*":
|
||||
description: Shanghai FourSemi Semiconductor Co.,Ltd.
|
||||
"^freebox,.*":
|
||||
description: Freebox SAS
|
||||
"^freecom,.*":
|
||||
|
|
|
|||
|
|
@ -9573,6 +9573,14 @@ F: lib/tests/memcpy_kunit.c
|
|||
K: \bunsafe_memcpy\b
|
||||
K: \b__NO_FORTIFY\b
|
||||
|
||||
FOURSEMI AUDIO AMPLIFIER DRIVER
|
||||
M: Nick Li <nick.li@foursemi.com>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/foursemi,fs2105s.yaml
|
||||
F: sound/soc/codecs/fs-amp-lib.*
|
||||
F: sound/soc/codecs/fs210x.*
|
||||
|
||||
FPGA DFL DRIVERS
|
||||
M: Xu Yilun <yilun.xu@intel.com>
|
||||
R: Tom Rix <trix@redhat.com>
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ config SND_SOC_ALL_CODECS
|
|||
imply SND_SOC_ES7134
|
||||
imply SND_SOC_ES7241
|
||||
imply SND_SOC_FRAMER
|
||||
imply SND_SOC_FS210X
|
||||
imply SND_SOC_GTM601
|
||||
imply SND_SOC_HDAC_HDMI
|
||||
imply SND_SOC_HDAC_HDA
|
||||
|
|
@ -1232,6 +1233,21 @@ config SND_SOC_FRAMER
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-soc-framer.
|
||||
|
||||
config SND_SOC_FS_AMP_LIB
|
||||
select CRC16
|
||||
tristate
|
||||
|
||||
config SND_SOC_FS210X
|
||||
tristate 'FourSemi FS2104/5S digital audio amplifier'
|
||||
depends on I2C
|
||||
select GPIOLIB
|
||||
select REGMAP_I2C
|
||||
select SND_SOC_FS_AMP_LIB
|
||||
help
|
||||
Enable support for FourSemi FS2104/5S digital audio amplifier.
|
||||
The FS2104/5S are Inductor-Less, Stereo, Closed-Loop,
|
||||
Digital Input Class-D Power Amplifiers with Enhanced Signal Processing.
|
||||
The amplifiers support I2C and I2S/TDM.
|
||||
|
||||
config SND_SOC_GTM601
|
||||
tristate 'GTM601 UMTS modem audio codec'
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@ snd-soc-es8328-spi-y := es8328-spi.o
|
|||
snd-soc-es8375-y := es8375.o
|
||||
snd-soc-es8389-y := es8389.o
|
||||
snd-soc-framer-y := framer-codec.o
|
||||
snd-soc-fs-amp-lib-y := fs-amp-lib.o
|
||||
snd-soc-fs210x-y := fs210x.o
|
||||
snd-soc-gtm601-y := gtm601.o
|
||||
snd-soc-hdac-hdmi-y := hdac_hdmi.o
|
||||
snd-soc-hdac-hda-y := hdac_hda.o
|
||||
|
|
@ -562,6 +564,8 @@ obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
|
|||
obj-$(CONFIG_SND_SOC_ES8375) += snd-soc-es8375.o
|
||||
obj-$(CONFIG_SND_SOC_ES8389) += snd-soc-es8389.o
|
||||
obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o
|
||||
obj-$(CONFIG_SND_SOC_FS_AMP_LIB)+= snd-soc-fs-amp-lib.o
|
||||
obj-$(CONFIG_SND_SOC_FS210X) += snd-soc-fs210x.o
|
||||
obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o
|
||||
obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
|
||||
obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o
|
||||
|
|
|
|||
265
sound/soc/codecs/fs-amp-lib.c
Normal file
265
sound/soc/codecs/fs-amp-lib.c
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// fs-amp-lib.c --- Common library for FourSemi Audio Amplifiers
|
||||
//
|
||||
// Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd.
|
||||
|
||||
#include <linux/crc16.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "fs-amp-lib.h"
|
||||
|
||||
static int fs_get_scene_count(struct fs_amp_lib *amp_lib)
|
||||
{
|
||||
const struct fs_fwm_table *table;
|
||||
int count;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev)
|
||||
return -EINVAL;
|
||||
|
||||
table = amp_lib->table[FS_INDEX_SCENE];
|
||||
if (!table)
|
||||
return -EFAULT;
|
||||
|
||||
count = table->size / sizeof(struct fs_scene_index);
|
||||
if (count < 1 || count > FS_SCENE_COUNT_MAX) {
|
||||
dev_err(amp_lib->dev, "Invalid scene count: %d\n", count);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void fs_get_fwm_string(struct fs_amp_lib *amp_lib,
|
||||
int offset, const char **pstr)
|
||||
{
|
||||
const struct fs_fwm_table *table;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !pstr)
|
||||
return;
|
||||
|
||||
table = amp_lib->table[FS_INDEX_STRING];
|
||||
if (table && offset > 0 && offset < table->size + sizeof(*table))
|
||||
*pstr = (char *)table + offset;
|
||||
else
|
||||
*pstr = NULL;
|
||||
}
|
||||
|
||||
static void fs_get_scene_reg(struct fs_amp_lib *amp_lib,
|
||||
int offset, struct fs_amp_scene *scene)
|
||||
{
|
||||
const struct fs_fwm_table *table;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !scene)
|
||||
return;
|
||||
|
||||
table = amp_lib->table[FS_INDEX_REG];
|
||||
if (table && offset > 0 && offset < table->size + sizeof(*table))
|
||||
scene->reg = (struct fs_reg_table *)((char *)table + offset);
|
||||
else
|
||||
scene->reg = NULL;
|
||||
}
|
||||
|
||||
static void fs_get_scene_model(struct fs_amp_lib *amp_lib,
|
||||
int offset, struct fs_amp_scene *scene)
|
||||
{
|
||||
const struct fs_fwm_table *table;
|
||||
const char *ptr;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !scene)
|
||||
return;
|
||||
|
||||
table = amp_lib->table[FS_INDEX_MODEL];
|
||||
ptr = (char *)table;
|
||||
if (table && offset > 0 && offset < table->size + sizeof(*table))
|
||||
scene->model = (struct fs_file_table *)(ptr + offset);
|
||||
else
|
||||
scene->model = NULL;
|
||||
}
|
||||
|
||||
static void fs_get_scene_effect(struct fs_amp_lib *amp_lib,
|
||||
int offset, struct fs_amp_scene *scene)
|
||||
{
|
||||
const struct fs_fwm_table *table;
|
||||
const char *ptr;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !scene)
|
||||
return;
|
||||
|
||||
table = amp_lib->table[FS_INDEX_EFFECT];
|
||||
ptr = (char *)table;
|
||||
if (table && offset > 0 && offset < table->size + sizeof(*table))
|
||||
scene->effect = (struct fs_file_table *)(ptr + offset);
|
||||
else
|
||||
scene->effect = NULL;
|
||||
}
|
||||
|
||||
static int fs_parse_scene_tables(struct fs_amp_lib *amp_lib)
|
||||
{
|
||||
const struct fs_scene_index *scene_index;
|
||||
const struct fs_fwm_table *table;
|
||||
struct fs_amp_scene *scene;
|
||||
int idx, count;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev)
|
||||
return -EINVAL;
|
||||
|
||||
count = fs_get_scene_count(amp_lib);
|
||||
if (count <= 0)
|
||||
return -EFAULT;
|
||||
|
||||
scene = devm_kzalloc(amp_lib->dev, count * sizeof(*scene), GFP_KERNEL);
|
||||
if (!scene)
|
||||
return -ENOMEM;
|
||||
|
||||
amp_lib->scene_count = count;
|
||||
amp_lib->scene = scene;
|
||||
|
||||
table = amp_lib->table[FS_INDEX_SCENE];
|
||||
scene_index = (struct fs_scene_index *)table->buf;
|
||||
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
fs_get_fwm_string(amp_lib, scene_index->name, &scene->name);
|
||||
if (!scene->name)
|
||||
scene->name = devm_kasprintf(amp_lib->dev,
|
||||
GFP_KERNEL, "S%d", idx);
|
||||
dev_dbg(amp_lib->dev, "scene.%d name: %s\n", idx, scene->name);
|
||||
fs_get_scene_reg(amp_lib, scene_index->reg, scene);
|
||||
fs_get_scene_model(amp_lib, scene_index->model, scene);
|
||||
fs_get_scene_effect(amp_lib, scene_index->effect, scene);
|
||||
scene++;
|
||||
scene_index++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fs_parse_all_tables(struct fs_amp_lib *amp_lib)
|
||||
{
|
||||
const struct fs_fwm_table *table;
|
||||
const struct fs_fwm_index *index;
|
||||
const char *ptr;
|
||||
int idx, count;
|
||||
int ret;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !amp_lib->hdr)
|
||||
return -EINVAL;
|
||||
|
||||
/* Parse all fwm tables */
|
||||
table = (struct fs_fwm_table *)amp_lib->hdr->params;
|
||||
index = (struct fs_fwm_index *)table->buf;
|
||||
count = table->size / sizeof(*index);
|
||||
|
||||
for (idx = 0; idx < count; idx++, index++) {
|
||||
if (index->type >= FS_INDEX_MAX)
|
||||
return -ERANGE;
|
||||
ptr = (char *)table + (int)index->offset;
|
||||
amp_lib->table[index->type] = (struct fs_fwm_table *)ptr;
|
||||
}
|
||||
|
||||
/* Parse all scene tables */
|
||||
ret = fs_parse_scene_tables(amp_lib);
|
||||
if (ret)
|
||||
dev_err(amp_lib->dev, "Failed to parse scene: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fs_verify_firmware(struct fs_amp_lib *amp_lib)
|
||||
{
|
||||
const struct fs_fwm_header *hdr;
|
||||
int crcsum;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !amp_lib->hdr)
|
||||
return -EINVAL;
|
||||
|
||||
hdr = amp_lib->hdr;
|
||||
|
||||
/* Verify the crcsum code */
|
||||
crcsum = crc16(0x0000, (const char *)&hdr->crc_size, hdr->crc_size);
|
||||
if (crcsum != hdr->crc16) {
|
||||
dev_err(amp_lib->dev, "Failed to checksum: %x-%x\n",
|
||||
crcsum, hdr->crc16);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Verify the devid(chip_type) */
|
||||
if (amp_lib->devid != LO_U16(hdr->chip_type)) {
|
||||
dev_err(amp_lib->dev, "DEVID dismatch: %04X#%04X\n",
|
||||
amp_lib->devid, hdr->chip_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fs_print_firmware_info(struct fs_amp_lib *amp_lib)
|
||||
{
|
||||
const struct fs_fwm_header *hdr;
|
||||
const char *pro_name = NULL;
|
||||
const char *dev_name = NULL;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !amp_lib->hdr)
|
||||
return;
|
||||
|
||||
hdr = amp_lib->hdr;
|
||||
|
||||
fs_get_fwm_string(amp_lib, hdr->project, &pro_name);
|
||||
fs_get_fwm_string(amp_lib, hdr->device, &dev_name);
|
||||
|
||||
dev_info(amp_lib->dev, "Project: %s Device: %s\n",
|
||||
pro_name ? pro_name : "null",
|
||||
dev_name ? dev_name : "null");
|
||||
|
||||
dev_info(amp_lib->dev, "Date: %04d%02d%02d-%02d%02d\n",
|
||||
hdr->date.year, hdr->date.month, hdr->date.day,
|
||||
hdr->date.hour, hdr->date.minute);
|
||||
}
|
||||
|
||||
int fs_amp_load_firmware(struct fs_amp_lib *amp_lib, const char *name)
|
||||
{
|
||||
const struct firmware *cont;
|
||||
struct fs_fwm_header *hdr;
|
||||
int ret;
|
||||
|
||||
if (!amp_lib || !amp_lib->dev || !name)
|
||||
return -EINVAL;
|
||||
|
||||
ret = request_firmware(&cont, name, amp_lib->dev);
|
||||
if (ret) {
|
||||
dev_err(amp_lib->dev, "Failed to request %s: %d\n", name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(amp_lib->dev, "Loading %s - size: %zu\n", name, cont->size);
|
||||
|
||||
hdr = devm_kmemdup(amp_lib->dev, cont->data, cont->size, GFP_KERNEL);
|
||||
release_firmware(cont);
|
||||
if (!hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
amp_lib->hdr = hdr;
|
||||
ret = fs_verify_firmware(amp_lib);
|
||||
if (ret) {
|
||||
amp_lib->hdr = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fs_parse_all_tables(amp_lib);
|
||||
if (ret) {
|
||||
amp_lib->hdr = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
fs_print_firmware_info(amp_lib);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fs_amp_load_firmware);
|
||||
|
||||
MODULE_AUTHOR("Nick Li <nick.li@foursemi.com>");
|
||||
MODULE_DESCRIPTION("FourSemi audio amplifier library");
|
||||
MODULE_LICENSE("GPL");
|
||||
150
sound/soc/codecs/fs-amp-lib.h
Normal file
150
sound/soc/codecs/fs-amp-lib.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* fs-amp-lib.h --- Common library for FourSemi Audio Amplifiers
|
||||
*
|
||||
* Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __FS_AMP_LIB_H__
|
||||
#define __FS_AMP_LIB_H__
|
||||
|
||||
#define HI_U16(a) (((a) >> 8) & 0xFF)
|
||||
#define LO_U16(a) ((a) & 0xFF)
|
||||
#define FS_TABLE_NAME_LEN (4)
|
||||
#define FS_SCENE_COUNT_MAX (16)
|
||||
#define FS_CMD_DELAY_MS_MAX (100) /* 100ms */
|
||||
|
||||
#define FS_CMD_DELAY (0xFF)
|
||||
#define FS_CMD_BURST (0xFE)
|
||||
#define FS_CMD_UPDATE (0xFD)
|
||||
|
||||
#define FS_SOC_ENUM_EXT(xname, xhandler_info, xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = xhandler_info, \
|
||||
.get = xhandler_get, .put = xhandler_put \
|
||||
}
|
||||
|
||||
enum fs_index_type {
|
||||
FS_INDEX_INFO = 0,
|
||||
FS_INDEX_STCOEF,
|
||||
FS_INDEX_SCENE,
|
||||
FS_INDEX_MODEL,
|
||||
FS_INDEX_REG,
|
||||
FS_INDEX_EFFECT,
|
||||
FS_INDEX_STRING,
|
||||
FS_INDEX_WOOFER,
|
||||
FS_INDEX_MAX,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct fs_reg_val {
|
||||
u8 reg;
|
||||
u16 val;
|
||||
};
|
||||
|
||||
struct fs_reg_bits {
|
||||
u8 cmd; /* FS_CMD_UPDATE */
|
||||
u8 reg;
|
||||
u16 val;
|
||||
u16 mask;
|
||||
};
|
||||
|
||||
struct fs_cmd_pkg {
|
||||
union {
|
||||
u8 cmd;
|
||||
struct fs_reg_val regv;
|
||||
struct fs_reg_bits regb;
|
||||
};
|
||||
};
|
||||
|
||||
struct fs_fwm_index {
|
||||
/* Index type */
|
||||
u16 type;
|
||||
/* Offset address starting from the end of header */
|
||||
u16 offset;
|
||||
};
|
||||
|
||||
struct fs_fwm_table {
|
||||
char name[FS_TABLE_NAME_LEN];
|
||||
u16 size; /* size of buf */
|
||||
u8 buf[];
|
||||
};
|
||||
|
||||
struct fs_scene_index {
|
||||
/* Offset address(scene name) in string table */
|
||||
u16 name;
|
||||
/* Offset address(scene reg) in register table */
|
||||
u16 reg;
|
||||
/* Offset address(scene model) in model table */
|
||||
u16 model;
|
||||
/* Offset address(scene effect) in effect table */
|
||||
u16 effect;
|
||||
};
|
||||
|
||||
struct fs_reg_table {
|
||||
u16 size; /* size of buf */
|
||||
u8 buf[];
|
||||
};
|
||||
|
||||
struct fs_file_table {
|
||||
u16 name;
|
||||
u16 size; /* size of buf */
|
||||
u8 buf[];
|
||||
};
|
||||
|
||||
struct fs_fwm_date {
|
||||
u32 year:12;
|
||||
u32 month:4;
|
||||
u32 day:5;
|
||||
u32 hour:5;
|
||||
u32 minute:6;
|
||||
};
|
||||
|
||||
struct fs_fwm_header {
|
||||
u16 version;
|
||||
u16 project; /* Offset address(project name) in string table */
|
||||
u16 device; /* Offset address(device name) in string table */
|
||||
struct fs_fwm_date date;
|
||||
u16 crc16;
|
||||
u16 crc_size; /* Starting position for CRC checking */
|
||||
u16 chip_type;
|
||||
u16 addr; /* 7-bit i2c address */
|
||||
u16 spkid;
|
||||
u16 rsvd[6];
|
||||
u8 params[];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
struct fs_i2s_srate {
|
||||
u32 srate; /* Sample rate */
|
||||
u16 i2ssr; /* Value of Bit field[I2SSR] */
|
||||
};
|
||||
|
||||
struct fs_pll_div {
|
||||
unsigned int bclk; /* Rate of bit clock */
|
||||
u16 pll1;
|
||||
u16 pll2;
|
||||
u16 pll3;
|
||||
};
|
||||
|
||||
struct fs_amp_scene {
|
||||
const char *name;
|
||||
const struct fs_reg_table *reg;
|
||||
const struct fs_file_table *model;
|
||||
const struct fs_file_table *effect;
|
||||
};
|
||||
|
||||
struct fs_amp_lib {
|
||||
const struct fs_fwm_header *hdr;
|
||||
const struct fs_fwm_table *table[FS_INDEX_MAX];
|
||||
struct fs_amp_scene *scene;
|
||||
struct device *dev;
|
||||
int scene_count;
|
||||
u16 devid;
|
||||
};
|
||||
|
||||
int fs_amp_load_firmware(struct fs_amp_lib *amp_lib, const char *name);
|
||||
|
||||
#endif // __FS_AMP_LIB_H__
|
||||
1583
sound/soc/codecs/fs210x.c
Normal file
1583
sound/soc/codecs/fs210x.c
Normal file
File diff suppressed because it is too large
Load Diff
75
sound/soc/codecs/fs210x.h
Normal file
75
sound/soc/codecs/fs210x.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* fs210x.h -- Driver for the FS2104/5S Audio Amplifier
|
||||
*
|
||||
* Copyright (C) 2016-2025 Shanghai FourSemi Semiconductor Co.,Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __FS210X_H__
|
||||
#define __FS210X_H__
|
||||
|
||||
#define FS210X_00H_STATUS 0x00
|
||||
#define FS210X_03H_DEVID 0x03
|
||||
#define FS210X_05H_ANASTAT 0x05
|
||||
#define FS210X_06H_DIGSTAT 0x06
|
||||
#define FS210X_0BH_ACCKEY 0x0B
|
||||
#define FS210X_0FH_I2CADDR 0x0F
|
||||
#define FS210X_10H_PWRCTRL 0x10
|
||||
#define FS210X_11H_SYSCTRL 0x11
|
||||
#define FS210X_17H_I2SCTRL 0x17
|
||||
#define FS210X_30H_DACCTRL 0x30
|
||||
#define FS210X_39H_LVOLCTRL 0x39
|
||||
#define FS210X_3AH_RVOLCTRL 0x3A
|
||||
#define FS210X_42H_DACEQWL 0x42
|
||||
#define FS210X_46H_DACEQA 0x46
|
||||
#define FS210X_A1H_PLLCTRL1 0xA1
|
||||
#define FS210X_A2H_PLLCTRL2 0xA2
|
||||
#define FS210X_A3H_PLLCTRL3 0xA3
|
||||
#define FS210X_ABH_INTSTAT 0xAB
|
||||
#define FS210X_ACH_INTSTATR 0xAC
|
||||
|
||||
#define FS210X_05H_PVDD_SHIFT 14
|
||||
#define FS210X_05H_PVDD_MASK BIT(14)
|
||||
#define FS210X_05H_OCDL_SHIFT 13
|
||||
#define FS210X_05H_OCDL_MASK BIT(13)
|
||||
#define FS210X_05H_UVDL_SHIFT 12
|
||||
#define FS210X_05H_UVDL_MASK BIT(12)
|
||||
#define FS210X_05H_OVDL_SHIFT 11
|
||||
#define FS210X_05H_OVDL_MASK BIT(11)
|
||||
#define FS210X_05H_OTPDL_SHIFT 10
|
||||
#define FS210X_05H_OTPDL_MASK BIT(10)
|
||||
#define FS210X_05H_OCRDL_SHIFT 9
|
||||
#define FS210X_05H_OCRDL_MASK BIT(9)
|
||||
#define FS210X_05H_OCLDL_SHIFT 8
|
||||
#define FS210X_05H_OCLDL_MASK BIT(8)
|
||||
#define FS210X_05H_DCRDL_SHIFT 7
|
||||
#define FS210X_05H_DCRDL_MASK BIT(7)
|
||||
#define FS210X_05H_DCLDL_SHIFT 6
|
||||
#define FS210X_05H_DCLDL_MASK BIT(6)
|
||||
#define FS210X_05H_SRDL_SHIFT 5
|
||||
#define FS210X_05H_SRDL_MASK BIT(5)
|
||||
#define FS210X_05H_OTWDL_SHIFT 4
|
||||
#define FS210X_05H_OTWDL_MASK BIT(4)
|
||||
#define FS210X_05H_AMPS_SHIFT 3
|
||||
#define FS210X_05H_AMPS_MASK BIT(3)
|
||||
#define FS210X_05H_PLLS_SHIFT 1
|
||||
#define FS210X_05H_PLLS_MASK BIT(1)
|
||||
#define FS210X_05H_ANAS_SHIFT 0
|
||||
#define FS210X_05H_ANAS_MASK BIT(0)
|
||||
#define FS210X_17H_I2SSR_SHIFT 12
|
||||
#define FS210X_17H_I2SSR_MASK GENMASK(15, 12)
|
||||
#define FS210X_30H_RMUTE_SHIFT 8
|
||||
#define FS210X_30H_LMUTE_SHIFT 4
|
||||
|
||||
#define FS210X_0BH_ACCKEY_ON 0x0091
|
||||
#define FS210X_0BH_ACCKEY_OFF 0x0000
|
||||
#define FS210X_10H_I2C_RESET 0x0002
|
||||
#define FS210X_11H_DPS_HIZ 0x0100
|
||||
#define FS210X_11H_DPS_PWDN 0x0000
|
||||
#define FS210X_11H_DPS_PLAY 0x0300
|
||||
#define FS210X_46H_CAM_BURST_L 0x8000
|
||||
#define FS210X_46H_CAM_BURST_R 0x8200
|
||||
#define FS2105S_46H_CAM_BURST_W 0x8400
|
||||
#define FS210X_46H_CAM_CLEAR 0x0000
|
||||
|
||||
#endif /* __FS210X_H__ */
|
||||
Loading…
Reference in New Issue
Block a user