Files
android/sound/soc/codecs/sia81xx/sia81xx_regmap.c
T
threeeye bc1d038eac REVVL 6 Pro kernel bring-up: full working tree snapshot (2026-09-12)
Squashed backup commit (no shallow-clone history issues) of
xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream
commit 9eece662e) plus all fixes applied to get everpal_defconfig building
clean against a modern (GCC 15.2.0) toolchain -- see the previous commit
message on the lineage-23.2 branch (also in this repo history is not
available here since this is a squashed snapshot; full incremental history
lives in the local DL380 checkout and the upstream GitHub remote).

Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
2026-09-12 13:36:46 +00:00

341 lines
7.9 KiB
C

/*
* Copyright (C) 2018, SI-IN, Yun Shi (yun.shi@si-in.com).
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
//#define DEBUG
#define LOG_FLAG "sia81xx_regmap"
#include <linux/regmap.h>
#include <linux/device.h>
#include "sia81xx_common.h"
#include "sia81xx_regmap.h"
#include "sia8101_regs.h"
#include "sia8108_regs.h"
#include "sia8109_regs.h"
#include "sia8152_regs.h"
#include "sia8152s_regs.h"
#include "sia8159_regs.h"
struct reg_map_info {
const struct regmap_config *config;
const struct sia81xx_reg_default_val *reg_default;
const struct sia81xx_opt_if *opt;
};
static const struct reg_map_info reg_map_info_table[] = {
[CHIP_TYPE_SIA8101] = {
.config = &sia8101_regmap_config,
.reg_default = &sia8101_reg_default_val,
.opt = &sia8101_opt_if
},
[CHIP_TYPE_SIA8108] = {
.config = &sia8108_regmap_config,
.reg_default = &sia8108_reg_default_val,
.opt = &sia8108_opt_if
},
[CHIP_TYPE_SIA8109] = {
.config = &sia8109_regmap_config,
.reg_default = &sia8109_reg_default_val,
.opt = &sia8109_opt_if
},
[CHIP_TYPE_SIA8152] = {
.config = &sia8152_regmap_config,
.reg_default = &sia8152_reg_default_val,
.opt = &sia8152_opt_if
},
[CHIP_TYPE_SIA8152S] = {
.config = &sia8152s_regmap_config,
.reg_default = &sia8152s_reg_default_val,
.opt = &sia8152s_opt_if
},
[CHIP_TYPE_SIA8159] = {
.config = &sia8159_regmap_config,
.reg_default = &sia8159_reg_default_val,
.opt = &sia8159_opt_if
}
};
static int verify_chip_type(
unsigned int type)
{
if (type >= ARRAY_SIZE(reg_map_info_table)) {
//pr_warn("[ warn][%s] %s: chip_type = %u, "
// "ARRAY_SIZE(reg_map_info) = %lu \r\n",
// LOG_FLAG, __func__, type, ARRAY_SIZE(reg_map_info_table));
return -ENODEV;
}
return 0;
}
int sia81xx_regmap_read(
struct regmap *regmap,
unsigned int start_reg,
unsigned int reg_num,
char *buf)
{
if(NULL == regmap) {
pr_warn("[ warn][%s] %s: NULL == regmap \r\n",
LOG_FLAG, __func__);
return -EINVAL;
}
if(NULL == buf) {
pr_err("[ err][%s] %s: NULL == buf \r\n",
LOG_FLAG, __func__);
return -EINVAL;
}
if(1 == reg_num) {
unsigned int val = 0;
int ret = regmap_read(regmap, start_reg, &val);
if (0 == ret)
*buf = (char)val;
return ret;
}
return regmap_bulk_read(regmap, start_reg, buf, reg_num);
}
int sia81xx_regmap_write(
struct regmap *regmap,
unsigned int start_reg,
unsigned int reg_num,
const char *buf)
{
if(NULL == regmap) {
pr_warn("[ warn][%s] %s: NULL == regmap \r\n",
LOG_FLAG, __func__);
return -EINVAL;
}
if(NULL == buf) {
pr_err("[ err][%s] %s: NULL == buf \r\n",
LOG_FLAG, __func__);
return -EINVAL;
}
if(1 == reg_num) {
unsigned int val = (unsigned int)(*buf);
return regmap_write(regmap, start_reg, val);
}
return regmap_bulk_write(regmap, start_reg, buf, reg_num);
}
/*
* Update regmap default register values based on machine id
*/
void sia81xx_regmap_defaults(
struct regmap *regmap,
unsigned int chip_type,
unsigned int scene,
unsigned int channel_num)
{
int ret = -ENOENT;
int i = 0;
pr_debug("[debug][%s] %s: running, chip_type = %u, channel_num = %u \r\n",
LOG_FLAG, __func__, chip_type, channel_num);
if(NULL == regmap) {
pr_warn("[ warn][%s] %s: NULL == regmap \r\n",
LOG_FLAG, __func__);
return ;
}
if(AUDIO_SCENE_NUM <= scene) {
pr_err("[ err][%s] %s: scene = %u, AUDIO_SCENE_NUM = %u \r\n",
LOG_FLAG, __func__, scene, AUDIO_SCENE_NUM);
return ;
}
if(SIA81XX_CHANNEL_NUM <= channel_num) {
pr_err("[ err][%s] %s: channel_num = %u, SIA81XX_CHANNEL_NUM = %u \r\n",
LOG_FLAG, __func__, channel_num, SIA81XX_CHANNEL_NUM);
return ;
}
for (i = 0; i < ARRAY_SIZE(reg_map_info_table); i++) {
if (NULL == reg_map_info_table[i].reg_default)
continue;
if (chip_type == reg_map_info_table[i].reg_default->chip_type) {
ret = sia81xx_regmap_write(
regmap,
reg_map_info_table[i].reg_default->offset,
reg_map_info_table[i].reg_default->reg_defaults[scene].num,
reg_map_info_table[i].reg_default->reg_defaults[scene].vals +
(channel_num * reg_map_info_table[i].reg_default->reg_defaults[scene].num)
);
break;
}
}
if (0 != ret) {
pr_warn("[ warn][%s] %s: ret = %d, chip_type = %u, regmap = %p \r\n",
LOG_FLAG, __func__, ret, chip_type, regmap);
}
}
struct regmap *sia81xx_regmap_init(
struct i2c_client *client,
unsigned int chip_type)
{
if(NULL == client)
return NULL;
if(0 != verify_chip_type(chip_type))
return NULL;
return devm_regmap_init_i2c(client, reg_map_info_table[chip_type].config);
}
void sia81xx_regmap_remove(
struct regmap *regmap)
{
if(!IS_ERR(regmap))
regmap_exit(regmap);
}
/********************************************************************
* sia81xx reg map opt functions
********************************************************************/
int sia81xx_regmap_check_chip_id(
struct regmap *regmap,
unsigned int chip_type)
{
if(NULL == regmap)
return -EPERM;
if(0 != verify_chip_type(chip_type))
return -EPERM;
if(NULL != reg_map_info_table[chip_type].opt->check_chip_id) {
return reg_map_info_table[chip_type].opt->check_chip_id(regmap);
}
/* if no need to check chip id then return "pass" */
return 0;
}
void sia81xx_regmap_set_xfilter(
struct regmap *regmap,
unsigned int chip_type,
unsigned int val)
{
if(NULL == regmap)
return ;
if(0 != verify_chip_type(chip_type))
return ;
if(NULL != reg_map_info_table[chip_type].opt->set_xfilter) {
reg_map_info_table[chip_type].opt->set_xfilter(regmap, val);
}
return ;
}
void sia81xx_regmap_set_chip_on(
struct regmap *regmap,
unsigned int chip_type,
unsigned int scene)
{
if(NULL == regmap)
return ;
if(0 != verify_chip_type(chip_type))
return ;
if(NULL != reg_map_info_table[chip_type].opt->chip_on) {
reg_map_info_table[chip_type].opt->chip_on(regmap, scene);
}
}
void sia81xx_regmap_set_chip_off(
struct regmap *regmap,
unsigned int chip_type)
{
if(NULL == regmap)
return ;
if(0 != verify_chip_type(chip_type))
return ;
if(NULL != reg_map_info_table[chip_type].opt->chip_off) {
reg_map_info_table[chip_type].opt->chip_off(regmap);
}
}
bool sia81xx_regmap_get_chip_en(
struct regmap *regmap,
unsigned int chip_type)
{
if(NULL == regmap)
return false;
if(0 != verify_chip_type(chip_type))
return false;
if(NULL != reg_map_info_table[chip_type].opt->get_chip_en) {
return reg_map_info_table[chip_type].opt->get_chip_en(regmap);
}
return false;
}
void sia81xx_regmap_set_pvdd_limit(
struct regmap *regmap,
unsigned int chip_type,
unsigned int vol)
{
if(NULL == regmap)
return ;
if(0 != verify_chip_type(chip_type))
return ;
if(NULL != reg_map_info_table[chip_type].opt->set_pvdd_limit) {
reg_map_info_table[chip_type].opt->set_pvdd_limit(regmap, vol);
}
}
void sia81xx_regmap_check_trimming(
struct regmap *regmap,
unsigned int chip_type)
{
if(NULL == regmap)
return ;
if(0 != verify_chip_type(chip_type))
return ;
if(NULL != reg_map_info_table[chip_type].opt->check_trimming) {
reg_map_info_table[chip_type].opt->check_trimming(regmap);
}
}
/********************************************************************
* end - sia81xx reg map opt functions
********************************************************************/