Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
473e8b32
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
473e8b32
编写于
12月 10, 2012
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/max98090' into asoc-next
上级
29998eb6
83f7cbc4
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
583 addition
and
0 deletion
+583
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+4
-0
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+2
-0
sound/soc/codecs/max98090.c
sound/soc/codecs/max98090.c
+577
-0
未找到文件。
sound/soc/codecs/Kconfig
浏览文件 @
473e8b32
...
...
@@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_LM4857 if I2C
select SND_SOC_LM49453 if I2C
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX98090 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
select SND_SOC_MAX9768 if I2C
...
...
@@ -266,6 +267,9 @@ config SND_SOC_LM49453
config SND_SOC_MAX98088
tristate
config SND_SOC_MAX98090
tristate
config SND_SOC_MAX98095
tristate
...
...
sound/soc/codecs/Makefile
浏览文件 @
473e8b32
...
...
@@ -34,6 +34,7 @@ snd-soc-lm4857-objs := lm4857.o
snd-soc-lm49453-objs
:=
lm49453.o
snd-soc-max9768-objs
:=
max9768.o
snd-soc-max98088-objs
:=
max98088.o
snd-soc-max98090-objs
:=
max98090.o
snd-soc-max98095-objs
:=
max98095.o
snd-soc-max9850-objs
:=
max9850.o
snd-soc-mc13783-objs
:=
mc13783.o
...
...
@@ -156,6 +157,7 @@ obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_LM49453)
+=
snd-soc-lm49453.o
obj-$(CONFIG_SND_SOC_MAX9768)
+=
snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088)
+=
snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX98090)
+=
snd-soc-max98090.o
obj-$(CONFIG_SND_SOC_MAX98095)
+=
snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850)
+=
snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_MC13783)
+=
snd-soc-mc13783.o
...
...
sound/soc/codecs/max98090.c
0 → 100644
浏览文件 @
473e8b32
/*
* max98090.c -- MAX98090 ALSA SoC Audio driver
* based on Rev0p8 datasheet
*
* Copyright (C) 2012 Renesas Solutions Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* Based on
*
* max98095.c
* Copyright 2011 Maxim Integrated Products
*
* https://github.com/hardkernel/linux/commit/\
* 3417d7166b17113b3b33b0a337c74d1c7cc313df#sound/soc/codecs/max98090.c
* Copyright 2011 Maxim Integrated Products
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/tlv.h>
/*
*
* MAX98090 Registers Definition
*
*/
/* RESET / STATUS / INTERRUPT REGISTERS */
#define MAX98090_0x00_SW_RESET 0x00
#define MAX98090_0x01_INT_STS 0x01
#define MAX98090_0x02_JACK_STS 0x02
#define MAX98090_0x03_INT_MASK 0x03
/* QUICK SETUP REGISTERS */
#define MAX98090_0x04_SYS_CLK 0x04
#define MAX98090_0x05_SAMPLE_RATE 0x05
#define MAX98090_0x06_DAI_IF 0x06
#define MAX98090_0x07_DAC_PATH 0x07
#define MAX98090_0x08_MIC_TO_ADC 0x08
#define MAX98090_0x09_LINE_TO_ADC 0x09
#define MAX98090_0x0A_ANALOG_MIC_LOOP 0x0A
#define MAX98090_0x0B_ANALOG_LINE_LOOP 0x0B
/* ANALOG INPUT CONFIGURATION REGISTERS */
#define MAX98090_0x0D_INPUT_CONFIG 0x0D
#define MAX98090_0x0E_LINE_IN_LVL 0x0E
#define MAX98090_0x0F_LINI_IN_CFG 0x0F
#define MAX98090_0x10_MIC1_IN_LVL 0x10
#define MAX98090_0x11_MIC2_IN_LVL 0x11
/* MICROPHONE CONFIGURATION REGISTERS */
#define MAX98090_0x12_MIC_BIAS_VOL 0x12
#define MAX98090_0x13_DIGITAL_MIC_CFG 0x13
#define MAX98090_0x14_DIGITAL_MIC_MODE 0x14
/* ADC PATH AND CONFIGURATION REGISTERS */
#define MAX98090_0x15_L_ADC_MIX 0x15
#define MAX98090_0x16_R_ADC_MIX 0x16
#define MAX98090_0x17_L_ADC_LVL 0x17
#define MAX98090_0x18_R_ADC_LVL 0x18
#define MAX98090_0x19_ADC_BIQUAD_LVL 0x19
#define MAX98090_0x1A_ADC_SIDETONE 0x1A
/* CLOCK CONFIGURATION REGISTERS */
#define MAX98090_0x1B_SYS_CLK 0x1B
#define MAX98090_0x1C_CLK_MODE 0x1C
#define MAX98090_0x1D_ANY_CLK1 0x1D
#define MAX98090_0x1E_ANY_CLK2 0x1E
#define MAX98090_0x1F_ANY_CLK3 0x1F
#define MAX98090_0x20_ANY_CLK4 0x20
#define MAX98090_0x21_MASTER_MODE 0x21
/* INTERFACE CONTROL REGISTERS */
#define MAX98090_0x22_DAI_IF_FMT 0x22
#define MAX98090_0x23_DAI_TDM_FMT1 0x23
#define MAX98090_0x24_DAI_TDM_FMT2 0x24
#define MAX98090_0x25_DAI_IO_CFG 0x25
#define MAX98090_0x26_FILTER_CFG 0x26
#define MAX98090_0x27_DAI_PLAYBACK_LVL 0x27
#define MAX98090_0x28_EQ_PLAYBACK_LVL 0x28
/* HEADPHONE CONTROL REGISTERS */
#define MAX98090_0x29_L_HP_MIX 0x29
#define MAX98090_0x2A_R_HP_MIX 0x2A
#define MAX98090_0x2B_HP_CTR 0x2B
#define MAX98090_0x2C_L_HP_VOL 0x2C
#define MAX98090_0x2D_R_HP_VOL 0x2D
/* SPEAKER CONFIGURATION REGISTERS */
#define MAX98090_0x2E_L_SPK_MIX 0x2E
#define MAX98090_0x2F_R_SPK_MIX 0x2F
#define MAX98090_0x30_SPK_CTR 0x30
#define MAX98090_0x31_L_SPK_VOL 0x31
#define MAX98090_0x32_R_SPK_VOL 0x32
/* ALC CONFIGURATION REGISTERS */
#define MAX98090_0x33_ALC_TIMING 0x33
#define MAX98090_0x34_ALC_COMPRESSOR 0x34
#define MAX98090_0x35_ALC_EXPANDER 0x35
#define MAX98090_0x36_ALC_GAIN 0x36
/* RECEIVER AND LINE_OUTPUT REGISTERS */
#define MAX98090_0x37_RCV_LOUT_L_MIX 0x37
#define MAX98090_0x38_RCV_LOUT_L_CNTL 0x38
#define MAX98090_0x39_RCV_LOUT_L_VOL 0x39
#define MAX98090_0x3A_LOUT_R_MIX 0x3A
#define MAX98090_0x3B_LOUT_R_CNTL 0x3B
#define MAX98090_0x3C_LOUT_R_VOL 0x3C
/* JACK DETECT AND ENABLE REGISTERS */
#define MAX98090_0x3D_JACK_DETECT 0x3D
#define MAX98090_0x3E_IN_ENABLE 0x3E
#define MAX98090_0x3F_OUT_ENABLE 0x3F
#define MAX98090_0x40_LVL_CTR 0x40
#define MAX98090_0x41_DSP_FILTER_ENABLE 0x41
/* BIAS AND POWER MODE CONFIGURATION REGISTERS */
#define MAX98090_0x42_BIAS_CTR 0x42
#define MAX98090_0x43_DAC_CTR 0x43
#define MAX98090_0x44_ADC_CTR 0x44
#define MAX98090_0x45_DEV_SHUTDOWN 0x45
/* REVISION ID REGISTER */
#define MAX98090_0xFF_REV_ID 0xFF
#define MAX98090_REG_MAX_CACHED 0x45
#define MAX98090_REG_END 0xFF
/*
*
* MAX98090 Registers Bit Fields
*
*/
/* MAX98090_0x06_DAI_IF */
#define MAX98090_DAI_IF_MASK 0x3F
#define MAX98090_RJ_M (1 << 5)
#define MAX98090_RJ_S (1 << 4)
#define MAX98090_LJ_M (1 << 3)
#define MAX98090_LJ_S (1 << 2)
#define MAX98090_I2S_M (1 << 1)
#define MAX98090_I2S_S (1 << 0)
/* MAX98090_0x45_DEV_SHUTDOWN */
#define MAX98090_SHDNRUN (1 << 7)
/* codec private data */
struct
max98090_priv
{
struct
regmap
*
regmap
;
};
static
const
struct
reg_default
max98090_reg_defaults
[]
=
{
/* RESET / STATUS / INTERRUPT REGISTERS */
{
MAX98090_0x00_SW_RESET
,
0x00
},
{
MAX98090_0x01_INT_STS
,
0x00
},
{
MAX98090_0x02_JACK_STS
,
0x00
},
{
MAX98090_0x03_INT_MASK
,
0x04
},
/* QUICK SETUP REGISTERS */
{
MAX98090_0x04_SYS_CLK
,
0x00
},
{
MAX98090_0x05_SAMPLE_RATE
,
0x00
},
{
MAX98090_0x06_DAI_IF
,
0x00
},
{
MAX98090_0x07_DAC_PATH
,
0x00
},
{
MAX98090_0x08_MIC_TO_ADC
,
0x00
},
{
MAX98090_0x09_LINE_TO_ADC
,
0x00
},
{
MAX98090_0x0A_ANALOG_MIC_LOOP
,
0x00
},
{
MAX98090_0x0B_ANALOG_LINE_LOOP
,
0x00
},
/* ANALOG INPUT CONFIGURATION REGISTERS */
{
MAX98090_0x0D_INPUT_CONFIG
,
0x00
},
{
MAX98090_0x0E_LINE_IN_LVL
,
0x1B
},
{
MAX98090_0x0F_LINI_IN_CFG
,
0x00
},
{
MAX98090_0x10_MIC1_IN_LVL
,
0x11
},
{
MAX98090_0x11_MIC2_IN_LVL
,
0x11
},
/* MICROPHONE CONFIGURATION REGISTERS */
{
MAX98090_0x12_MIC_BIAS_VOL
,
0x00
},
{
MAX98090_0x13_DIGITAL_MIC_CFG
,
0x00
},
{
MAX98090_0x14_DIGITAL_MIC_MODE
,
0x00
},
/* ADC PATH AND CONFIGURATION REGISTERS */
{
MAX98090_0x15_L_ADC_MIX
,
0x00
},
{
MAX98090_0x16_R_ADC_MIX
,
0x00
},
{
MAX98090_0x17_L_ADC_LVL
,
0x03
},
{
MAX98090_0x18_R_ADC_LVL
,
0x03
},
{
MAX98090_0x19_ADC_BIQUAD_LVL
,
0x00
},
{
MAX98090_0x1A_ADC_SIDETONE
,
0x00
},
/* CLOCK CONFIGURATION REGISTERS */
{
MAX98090_0x1B_SYS_CLK
,
0x00
},
{
MAX98090_0x1C_CLK_MODE
,
0x00
},
{
MAX98090_0x1D_ANY_CLK1
,
0x00
},
{
MAX98090_0x1E_ANY_CLK2
,
0x00
},
{
MAX98090_0x1F_ANY_CLK3
,
0x00
},
{
MAX98090_0x20_ANY_CLK4
,
0x00
},
{
MAX98090_0x21_MASTER_MODE
,
0x00
},
/* INTERFACE CONTROL REGISTERS */
{
MAX98090_0x22_DAI_IF_FMT
,
0x00
},
{
MAX98090_0x23_DAI_TDM_FMT1
,
0x00
},
{
MAX98090_0x24_DAI_TDM_FMT2
,
0x00
},
{
MAX98090_0x25_DAI_IO_CFG
,
0x00
},
{
MAX98090_0x26_FILTER_CFG
,
0x80
},
{
MAX98090_0x27_DAI_PLAYBACK_LVL
,
0x00
},
{
MAX98090_0x28_EQ_PLAYBACK_LVL
,
0x00
},
/* HEADPHONE CONTROL REGISTERS */
{
MAX98090_0x29_L_HP_MIX
,
0x00
},
{
MAX98090_0x2A_R_HP_MIX
,
0x00
},
{
MAX98090_0x2B_HP_CTR
,
0x00
},
{
MAX98090_0x2C_L_HP_VOL
,
0x1A
},
{
MAX98090_0x2D_R_HP_VOL
,
0x1A
},
/* SPEAKER CONFIGURATION REGISTERS */
{
MAX98090_0x2E_L_SPK_MIX
,
0x00
},
{
MAX98090_0x2F_R_SPK_MIX
,
0x00
},
{
MAX98090_0x30_SPK_CTR
,
0x00
},
{
MAX98090_0x31_L_SPK_VOL
,
0x2C
},
{
MAX98090_0x32_R_SPK_VOL
,
0x2C
},
/* ALC CONFIGURATION REGISTERS */
{
MAX98090_0x33_ALC_TIMING
,
0x00
},
{
MAX98090_0x34_ALC_COMPRESSOR
,
0x00
},
{
MAX98090_0x35_ALC_EXPANDER
,
0x00
},
{
MAX98090_0x36_ALC_GAIN
,
0x00
},
/* RECEIVER AND LINE_OUTPUT REGISTERS */
{
MAX98090_0x37_RCV_LOUT_L_MIX
,
0x00
},
{
MAX98090_0x38_RCV_LOUT_L_CNTL
,
0x00
},
{
MAX98090_0x39_RCV_LOUT_L_VOL
,
0x15
},
{
MAX98090_0x3A_LOUT_R_MIX
,
0x00
},
{
MAX98090_0x3B_LOUT_R_CNTL
,
0x00
},
{
MAX98090_0x3C_LOUT_R_VOL
,
0x15
},
/* JACK DETECT AND ENABLE REGISTERS */
{
MAX98090_0x3D_JACK_DETECT
,
0x00
},
{
MAX98090_0x3E_IN_ENABLE
,
0x00
},
{
MAX98090_0x3F_OUT_ENABLE
,
0x00
},
{
MAX98090_0x40_LVL_CTR
,
0x00
},
{
MAX98090_0x41_DSP_FILTER_ENABLE
,
0x00
},
/* BIAS AND POWER MODE CONFIGURATION REGISTERS */
{
MAX98090_0x42_BIAS_CTR
,
0x00
},
{
MAX98090_0x43_DAC_CTR
,
0x00
},
{
MAX98090_0x44_ADC_CTR
,
0x06
},
{
MAX98090_0x45_DEV_SHUTDOWN
,
0x00
},
};
static
const
unsigned
int
max98090_hp_tlv
[]
=
{
TLV_DB_RANGE_HEAD
(
5
),
0x0
,
0x6
,
TLV_DB_SCALE_ITEM
(
-
6700
,
400
,
0
),
0x7
,
0xE
,
TLV_DB_SCALE_ITEM
(
-
4000
,
300
,
0
),
0xF
,
0x15
,
TLV_DB_SCALE_ITEM
(
-
1700
,
200
,
0
),
0x16
,
0x1B
,
TLV_DB_SCALE_ITEM
(
-
400
,
100
,
0
),
0x1C
,
0x1F
,
TLV_DB_SCALE_ITEM
(
150
,
50
,
0
),
};
static
struct
snd_kcontrol_new
max98090_snd_controls
[]
=
{
SOC_DOUBLE_R_TLV
(
"Headphone Volume"
,
MAX98090_0x2C_L_HP_VOL
,
MAX98090_0x2D_R_HP_VOL
,
0
,
31
,
0
,
max98090_hp_tlv
),
};
/* Left HeadPhone Mixer Switch */
static
struct
snd_kcontrol_new
max98090_left_hp_mixer_controls
[]
=
{
SOC_DAPM_SINGLE
(
"DACR Switch"
,
MAX98090_0x29_L_HP_MIX
,
1
,
1
,
0
),
SOC_DAPM_SINGLE
(
"DACL Switch"
,
MAX98090_0x29_L_HP_MIX
,
0
,
1
,
0
),
};
/* Right HeadPhone Mixer Switch */
static
struct
snd_kcontrol_new
max98090_right_hp_mixer_controls
[]
=
{
SOC_DAPM_SINGLE
(
"DACR Switch"
,
MAX98090_0x2A_R_HP_MIX
,
1
,
1
,
0
),
SOC_DAPM_SINGLE
(
"DACL Switch"
,
MAX98090_0x2A_R_HP_MIX
,
0
,
1
,
0
),
};
static
struct
snd_soc_dapm_widget
max98090_dapm_widgets
[]
=
{
/* Output */
SND_SOC_DAPM_OUTPUT
(
"HPL"
),
SND_SOC_DAPM_OUTPUT
(
"HPR"
),
/* PGA */
SND_SOC_DAPM_PGA
(
"HPL Out"
,
MAX98090_0x3F_OUT_ENABLE
,
7
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"HPR Out"
,
MAX98090_0x3F_OUT_ENABLE
,
6
,
0
,
NULL
,
0
),
/* Mixer */
SND_SOC_DAPM_MIXER
(
"HPL Mixer"
,
SND_SOC_NOPM
,
0
,
0
,
max98090_left_hp_mixer_controls
,
ARRAY_SIZE
(
max98090_left_hp_mixer_controls
)),
SND_SOC_DAPM_MIXER
(
"HPR Mixer"
,
SND_SOC_NOPM
,
0
,
0
,
max98090_right_hp_mixer_controls
,
ARRAY_SIZE
(
max98090_right_hp_mixer_controls
)),
/* DAC */
SND_SOC_DAPM_DAC
(
"DACL"
,
"Hifi Playback"
,
MAX98090_0x3F_OUT_ENABLE
,
0
,
0
),
SND_SOC_DAPM_DAC
(
"DACR"
,
"Hifi Playback"
,
MAX98090_0x3F_OUT_ENABLE
,
1
,
0
),
};
static
struct
snd_soc_dapm_route
max98090_audio_map
[]
=
{
/* Output */
{
"HPL"
,
NULL
,
"HPL Out"
},
{
"HPR"
,
NULL
,
"HPR Out"
},
/* PGA */
{
"HPL Out"
,
NULL
,
"HPL Mixer"
},
{
"HPR Out"
,
NULL
,
"HPR Mixer"
},
/* Mixer*/
{
"HPL Mixer"
,
"DACR Switch"
,
"DACR"
},
{
"HPL Mixer"
,
"DACL Switch"
,
"DACL"
},
{
"HPR Mixer"
,
"DACR Switch"
,
"DACR"
},
{
"HPR Mixer"
,
"DACL Switch"
,
"DACL"
},
};
static
bool
max98090_volatile
(
struct
device
*
dev
,
unsigned
int
reg
)
{
if
((
reg
==
MAX98090_0x01_INT_STS
)
||
(
reg
==
MAX98090_0x02_JACK_STS
)
||
(
reg
>
MAX98090_REG_MAX_CACHED
))
return
true
;
return
false
;
}
static
int
max98090_dai_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
unsigned
int
val
;
switch
(
params_rate
(
params
))
{
case
96000
:
val
=
1
<<
5
;
break
;
case
32000
:
val
=
1
<<
4
;
break
;
case
48000
:
val
=
1
<<
3
;
break
;
case
44100
:
val
=
1
<<
2
;
break
;
case
16000
:
val
=
1
<<
1
;
break
;
case
8000
:
val
=
1
<<
0
;
break
;
default:
dev_err
(
codec
->
dev
,
"unsupported rate
\n
"
);
return
-
EINVAL
;
}
snd_soc_update_bits
(
codec
,
MAX98090_0x05_SAMPLE_RATE
,
0x03F
,
val
);
return
0
;
}
static
int
max98090_dai_set_sysclk
(
struct
snd_soc_dai
*
dai
,
int
clk_id
,
unsigned
int
freq
,
int
dir
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
unsigned
int
val
;
snd_soc_update_bits
(
codec
,
MAX98090_0x45_DEV_SHUTDOWN
,
MAX98090_SHDNRUN
,
0
);
switch
(
freq
)
{
case
26000000
:
val
=
1
<<
7
;
break
;
case
19200000
:
val
=
1
<<
6
;
break
;
case
13000000
:
val
=
1
<<
5
;
break
;
case
12288000
:
val
=
1
<<
4
;
break
;
case
12000000
:
val
=
1
<<
3
;
break
;
case
11289600
:
val
=
1
<<
2
;
break
;
default:
dev_err
(
codec
->
dev
,
"Invalid master clock frequency
\n
"
);
return
-
EINVAL
;
}
snd_soc_update_bits
(
codec
,
MAX98090_0x04_SYS_CLK
,
0xFD
,
val
);
snd_soc_update_bits
(
codec
,
MAX98090_0x45_DEV_SHUTDOWN
,
MAX98090_SHDNRUN
,
MAX98090_SHDNRUN
);
dev_dbg
(
dai
->
dev
,
"sysclk is %uHz
\n
"
,
freq
);
return
0
;
}
static
int
max98090_dai_set_fmt
(
struct
snd_soc_dai
*
dai
,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
int
is_master
;
u8
val
;
/* master/slave mode */
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
case
SND_SOC_DAIFMT_CBM_CFM
:
is_master
=
1
;
break
;
case
SND_SOC_DAIFMT_CBS_CFS
:
is_master
=
0
;
break
;
default:
dev_err
(
codec
->
dev
,
"unsupported clock
\n
"
);
return
-
EINVAL
;
}
/* format */
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
case
SND_SOC_DAIFMT_I2S
:
val
=
(
is_master
)
?
MAX98090_I2S_M
:
MAX98090_I2S_S
;
break
;
case
SND_SOC_DAIFMT_RIGHT_J
:
val
=
(
is_master
)
?
MAX98090_RJ_M
:
MAX98090_RJ_S
;
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
val
=
(
is_master
)
?
MAX98090_LJ_M
:
MAX98090_LJ_S
;
break
;
default:
dev_err
(
codec
->
dev
,
"unsupported format
\n
"
);
return
-
EINVAL
;
}
snd_soc_update_bits
(
codec
,
MAX98090_0x06_DAI_IF
,
MAX98090_DAI_IF_MASK
,
val
);
return
0
;
}
#define MAX98090_RATES SNDRV_PCM_RATE_8000_96000
#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
static
struct
snd_soc_dai_ops
max98090_dai_ops
=
{
.
set_sysclk
=
max98090_dai_set_sysclk
,
.
set_fmt
=
max98090_dai_set_fmt
,
.
hw_params
=
max98090_dai_hw_params
,
};
static
struct
snd_soc_dai_driver
max98090_dai
=
{
.
name
=
"max98090-Hifi"
,
.
playback
=
{
.
stream_name
=
"Playback"
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
MAX98090_RATES
,
.
formats
=
MAX98090_FORMATS
,
},
.
ops
=
&
max98090_dai_ops
,
};
static
int
max98090_probe
(
struct
snd_soc_codec
*
codec
)
{
struct
max98090_priv
*
priv
=
snd_soc_codec_get_drvdata
(
codec
);
struct
device
*
dev
=
codec
->
dev
;
int
ret
;
codec
->
control_data
=
priv
->
regmap
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
8
,
SND_SOC_REGMAP
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
return
ret
;
}
/* Device active */
snd_soc_update_bits
(
codec
,
MAX98090_0x45_DEV_SHUTDOWN
,
MAX98090_SHDNRUN
,
MAX98090_SHDNRUN
);
return
0
;
}
static
int
max98090_remove
(
struct
snd_soc_codec
*
codec
)
{
return
0
;
}
static
struct
snd_soc_codec_driver
soc_codec_dev_max98090
=
{
.
probe
=
max98090_probe
,
.
remove
=
max98090_remove
,
.
controls
=
max98090_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
max98090_snd_controls
),
.
dapm_widgets
=
max98090_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
max98090_dapm_widgets
),
.
dapm_routes
=
max98090_audio_map
,
.
num_dapm_routes
=
ARRAY_SIZE
(
max98090_audio_map
),
};
static
const
struct
regmap_config
max98090_regmap
=
{
.
reg_bits
=
8
,
.
val_bits
=
8
,
.
max_register
=
MAX98090_REG_END
,
.
volatile_reg
=
max98090_volatile
,
.
cache_type
=
REGCACHE_RBTREE
,
.
reg_defaults
=
max98090_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
max98090_reg_defaults
),
};
static
int
max98090_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
max98090_priv
*
priv
;
struct
device
*
dev
=
&
i2c
->
dev
;
unsigned
int
val
;
int
ret
;
priv
=
devm_kzalloc
(
dev
,
sizeof
(
struct
max98090_priv
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
ENOMEM
;
priv
->
regmap
=
devm_regmap_init_i2c
(
i2c
,
&
max98090_regmap
);
if
(
IS_ERR
(
priv
->
regmap
))
{
ret
=
PTR_ERR
(
priv
->
regmap
);
dev_err
(
dev
,
"Failed to init regmap: %d
\n
"
,
ret
);
return
ret
;
}
i2c_set_clientdata
(
i2c
,
priv
);
ret
=
regmap_read
(
priv
->
regmap
,
MAX98090_0xFF_REV_ID
,
&
val
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"Failed to read device revision: %d
\n
"
,
ret
);
return
ret
;
}
dev_info
(
dev
,
"revision 0x%02x
\n
"
,
val
);
ret
=
snd_soc_register_codec
(
dev
,
&
soc_codec_dev_max98090
,
&
max98090_dai
,
1
);
return
ret
;
}
static
int
max98090_i2c_remove
(
struct
i2c_client
*
client
)
{
snd_soc_unregister_codec
(
&
client
->
dev
);
return
0
;
}
static
const
struct
i2c_device_id
max98090_i2c_id
[]
=
{
{
"max98090"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
max98090_i2c_id
);
static
struct
i2c_driver
max98090_i2c_driver
=
{
.
driver
=
{
.
name
=
"max98090"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
max98090_i2c_probe
,
.
remove
=
max98090_i2c_remove
,
.
id_table
=
max98090_i2c_id
,
};
module_i2c_driver
(
max98090_i2c_driver
);
MODULE_DESCRIPTION
(
"ALSA SoC MAX98090 driver"
);
MODULE_AUTHOR
(
"Peter Hsiang, Kuninori Morimoto"
);
MODULE_LICENSE
(
"GPL"
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录