Skip to content

Commit 296bd7d

Browse files
committed
Add support for CS42L43B codec to CS42L43 driver
Merge series from Maciej Strozek <mstrozek@opensource.cirrus.com>: Introducing CS42L43B, a variant of the CS42L43 codec with changes to PDM (DMIC) inputs, RAM/ROM memory and extra channels to two SoundWire ports and ISRCs, and can be supported by the existing CS42L43 driver with some modifications.
2 parents ed03132 + 0a208ad commit 296bd7d

10 files changed

Lines changed: 848 additions & 152 deletions

File tree

Documentation/devicetree/bindings/sound/cirrus,cs42l43.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ description: |
1616
DAC for headphone output, two integrated Class D amplifiers for
1717
loudspeakers, and two ADCs for wired headset microphone input or
1818
stereo line input. PDM inputs are provided for digital microphones.
19+
CS42L43B variant adds dedicated PDM interface, SoundWire Clock Gearing
20+
support and more decimators to ISRCs.
1921
2022
allOf:
2123
- $ref: dai-common.yaml#
@@ -24,6 +26,7 @@ properties:
2426
compatible:
2527
enum:
2628
- cirrus,cs42l43
29+
- cirrus,cs42l43b
2730

2831
reg:
2932
maxItems: 1

drivers/mfd/cs42l43-i2c.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static int cs42l43_i2c_probe(struct i2c_client *i2c)
4747
cs42l43->irq = i2c->irq;
4848
/* A device on an I2C is always attached by definition. */
4949
cs42l43->attached = true;
50+
cs42l43->variant_id = (long)device_get_match_data(cs42l43->dev);
5051

5152
cs42l43->regmap = devm_regmap_init_i2c(i2c, &cs42l43_i2c_regmap);
5253
if (IS_ERR(cs42l43->regmap))
@@ -58,15 +59,17 @@ static int cs42l43_i2c_probe(struct i2c_client *i2c)
5859

5960
#if IS_ENABLED(CONFIG_OF)
6061
static const struct of_device_id cs42l43_of_match[] = {
61-
{ .compatible = "cirrus,cs42l43", },
62+
{ .compatible = "cirrus,cs42l43", .data = (void *)CS42L43_DEVID_VAL },
63+
{ .compatible = "cirrus,cs42l43b", .data = (void *)CS42L43B_DEVID_VAL },
6264
{}
6365
};
6466
MODULE_DEVICE_TABLE(of, cs42l43_of_match);
6567
#endif
6668

6769
#if IS_ENABLED(CONFIG_ACPI)
6870
static const struct acpi_device_id cs42l43_acpi_match[] = {
69-
{ "CSC4243", 0 },
71+
{ "CSC4243", CS42L43_DEVID_VAL },
72+
{ "CSC2A3B", CS42L43B_DEVID_VAL },
7073
{}
7174
};
7275
MODULE_DEVICE_TABLE(acpi, cs42l43_acpi_match);

drivers/mfd/cs42l43-sdw.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *
178178

179179
cs42l43->dev = dev;
180180
cs42l43->sdw = sdw;
181+
cs42l43->variant_id = (long)id->driver_data;
181182

182183
cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap);
183184
if (IS_ERR(cs42l43->regmap))
@@ -188,7 +189,8 @@ static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *
188189
}
189190

190191
static const struct sdw_device_id cs42l43_sdw_id[] = {
191-
SDW_SLAVE_ENTRY(0x01FA, 0x4243, 0),
192+
SDW_SLAVE_ENTRY(0x01FA, 0x4243, (void *) CS42L43_DEVID_VAL),
193+
SDW_SLAVE_ENTRY(0x01FA, 0x2A3B, (void *) CS42L43B_DEVID_VAL),
192194
{}
193195
};
194196
MODULE_DEVICE_TABLE(sdw, cs42l43_sdw_id);

drivers/mfd/cs42l43.c

Lines changed: 80 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,14 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
115115
{ CS42L43_DECIM_HPF_WNF_CTRL2, 0x00000001 },
116116
{ CS42L43_DECIM_HPF_WNF_CTRL3, 0x00000001 },
117117
{ CS42L43_DECIM_HPF_WNF_CTRL4, 0x00000001 },
118+
{ CS42L43B_DECIM_HPF_WNF_CTRL5, 0x00000001 },
119+
{ CS42L43B_DECIM_HPF_WNF_CTRL6, 0x00000001 },
118120
{ CS42L43_DMIC_PDM_CTRL, 0x00000000 },
119121
{ CS42L43_DECIM_VOL_CTRL_CH1_CH2, 0x20122012 },
120122
{ CS42L43_DECIM_VOL_CTRL_CH3_CH4, 0x20122012 },
123+
{ CS42L43B_DECIM_VOL_CTRL_CH1_CH2, 0x20122012 },
124+
{ CS42L43B_DECIM_VOL_CTRL_CH3_CH4, 0x20122012 },
125+
{ CS42L43B_DECIM_VOL_CTRL_CH5_CH6, 0x20122012 },
121126
{ CS42L43_INTP_VOLUME_CTRL1, 0x00000180 },
122127
{ CS42L43_INTP_VOLUME_CTRL2, 0x00000180 },
123128
{ CS42L43_AMP1_2_VOL_RAMP, 0x00000022 },
@@ -155,8 +160,12 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
155160
{ CS42L43_SWIRE_DP2_CH2_INPUT, 0x00000000 },
156161
{ CS42L43_SWIRE_DP3_CH1_INPUT, 0x00000000 },
157162
{ CS42L43_SWIRE_DP3_CH2_INPUT, 0x00000000 },
163+
{ CS42L43B_SWIRE_DP3_CH3_INPUT, 0x00000000 },
164+
{ CS42L43B_SWIRE_DP3_CH4_INPUT, 0x00000000 },
158165
{ CS42L43_SWIRE_DP4_CH1_INPUT, 0x00000000 },
159166
{ CS42L43_SWIRE_DP4_CH2_INPUT, 0x00000000 },
167+
{ CS42L43B_SWIRE_DP4_CH3_INPUT, 0x00000000 },
168+
{ CS42L43B_SWIRE_DP4_CH4_INPUT, 0x00000000 },
160169
{ CS42L43_ASRC_INT1_INPUT1, 0x00000000 },
161170
{ CS42L43_ASRC_INT2_INPUT1, 0x00000000 },
162171
{ CS42L43_ASRC_INT3_INPUT1, 0x00000000 },
@@ -169,10 +178,14 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
169178
{ CS42L43_ISRC1INT2_INPUT1, 0x00000000 },
170179
{ CS42L43_ISRC1DEC1_INPUT1, 0x00000000 },
171180
{ CS42L43_ISRC1DEC2_INPUT1, 0x00000000 },
181+
{ CS42L43B_ISRC1DEC3_INPUT1, 0x00000000 },
182+
{ CS42L43B_ISRC1DEC4_INPUT1, 0x00000000 },
172183
{ CS42L43_ISRC2INT1_INPUT1, 0x00000000 },
173184
{ CS42L43_ISRC2INT2_INPUT1, 0x00000000 },
174185
{ CS42L43_ISRC2DEC1_INPUT1, 0x00000000 },
175186
{ CS42L43_ISRC2DEC2_INPUT1, 0x00000000 },
187+
{ CS42L43B_ISRC2DEC3_INPUT1, 0x00000000 },
188+
{ CS42L43B_ISRC2DEC4_INPUT1, 0x00000000 },
176189
{ CS42L43_EQ1MIX_INPUT1, 0x00800000 },
177190
{ CS42L43_EQ1MIX_INPUT2, 0x00800000 },
178191
{ CS42L43_EQ1MIX_INPUT3, 0x00800000 },
@@ -269,6 +282,8 @@ EXPORT_SYMBOL_NS_GPL(cs42l43_reg_default, "MFD_CS42L43");
269282

270283
bool cs42l43_readable_register(struct device *dev, unsigned int reg)
271284
{
285+
struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
286+
272287
switch (reg) {
273288
case CS42L43_DEVID:
274289
case CS42L43_REVID:
@@ -292,7 +307,6 @@ bool cs42l43_readable_register(struct device *dev, unsigned int reg)
292307
case CS42L43_ADC_B_CTRL1 ... CS42L43_ADC_B_CTRL2:
293308
case CS42L43_DECIM_HPF_WNF_CTRL1 ... CS42L43_DECIM_HPF_WNF_CTRL4:
294309
case CS42L43_DMIC_PDM_CTRL:
295-
case CS42L43_DECIM_VOL_CTRL_CH1_CH2 ... CS42L43_DECIM_VOL_CTRL_CH3_CH4:
296310
case CS42L43_INTP_VOLUME_CTRL1 ... CS42L43_INTP_VOLUME_CTRL2:
297311
case CS42L43_AMP1_2_VOL_RAMP:
298312
case CS42L43_ASP_CTRL:
@@ -387,8 +401,16 @@ bool cs42l43_readable_register(struct device *dev, unsigned int reg)
387401
case CS42L43_BOOT_CONTROL:
388402
case CS42L43_BLOCK_EN:
389403
case CS42L43_SHUTTER_CONTROL:
390-
case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX:
391-
return true;
404+
case CS42L43B_MCU_SW_REV ... CS42L43B_MCU_RAM_MAX:
405+
return true; // registers present on all variants
406+
case CS42L43_MCU_SW_REV ... CS42L43B_MCU_SW_REV - 1:
407+
case CS42L43B_MCU_RAM_MAX + 1 ... CS42L43_MCU_RAM_MAX:
408+
case CS42L43_DECIM_VOL_CTRL_CH1_CH2 ... CS42L43_DECIM_VOL_CTRL_CH3_CH4:
409+
return cs42l43->variant_id == CS42L43_DEVID_VAL; // regs only in CS42L43 variant
410+
case CS42L43B_DECIM_VOL_CTRL_CH1_CH2 ... CS42L43B_DECIM_HPF_WNF_CTRL6:
411+
case CS42L43B_SWIRE_DP3_CH3_INPUT ... CS42L43B_SWIRE_DP4_CH4_INPUT:
412+
case CS42L43B_ISRC1DEC3_INPUT1 ... CS42L43B_ISRC2DEC4_INPUT1:
413+
return cs42l43->variant_id == CS42L43B_DEVID_VAL; // regs only in CS42L43B variant
392414
default:
393415
return false;
394416
}
@@ -597,15 +619,27 @@ static int cs42l43_wait_for_attach(struct cs42l43 *cs42l43)
597619
static int cs42l43_mcu_stage_2_3(struct cs42l43 *cs42l43, bool shadow)
598620
{
599621
unsigned int need_reg = CS42L43_NEED_CONFIGS;
622+
unsigned int boot_reg;
600623
unsigned int val;
601624
int ret;
602625

603-
if (shadow)
604-
need_reg = CS42L43_FW_SH_BOOT_CFG_NEED_CONFIGS;
626+
switch (cs42l43->variant_id) {
627+
case CS42L43_DEVID_VAL:
628+
if (shadow)
629+
need_reg = CS42L43_FW_SH_BOOT_CFG_NEED_CONFIGS;
630+
boot_reg = CS42L43_BOOT_STATUS;
631+
break;
632+
case CS42L43B_DEVID_VAL:
633+
need_reg = CS42L43B_NEED_CONFIGS;
634+
boot_reg = CS42L43B_BOOT_STATUS;
635+
break;
636+
default:
637+
return -EINVAL;
638+
}
605639

606640
regmap_write(cs42l43->regmap, need_reg, 0);
607641

608-
ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_BOOT_STATUS,
642+
ret = regmap_read_poll_timeout(cs42l43->regmap, boot_reg,
609643
val, (val == CS42L43_MCU_BOOT_STAGE3),
610644
CS42L43_MCU_POLL_US, CS42L43_MCU_CMD_TIMEOUT_US);
611645
if (ret) {
@@ -644,13 +678,25 @@ static int cs42l43_mcu_stage_3_2(struct cs42l43 *cs42l43)
644678
*/
645679
static int cs42l43_mcu_disable(struct cs42l43 *cs42l43)
646680
{
647-
unsigned int val;
681+
unsigned int val, cfg_reg, ctrl_reg;
648682
int ret;
649683

650-
regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG,
651-
CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL);
652-
regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION,
653-
CS42L43_FW_MM_CTRL_MCU_SEL_MASK);
684+
switch (cs42l43->variant_id) {
685+
case CS42L43_DEVID_VAL:
686+
cfg_reg = CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG;
687+
ctrl_reg = CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION;
688+
break;
689+
case CS42L43B_DEVID_VAL:
690+
cfg_reg = CS42L43B_FW_MISSION_CTRL_MM_MCU_CFG_REG;
691+
ctrl_reg = CS42L43B_FW_MISSION_CTRL_MM_CTRL_SELECTION;
692+
break;
693+
default:
694+
return -EINVAL;
695+
}
696+
697+
regmap_write(cs42l43->regmap, cfg_reg, CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL);
698+
regmap_write(cs42l43->regmap, ctrl_reg, CS42L43_FW_MM_CTRL_MCU_SEL_MASK);
699+
654700
regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_CONTROL_IND_MASK);
655701
regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0);
656702

@@ -740,18 +786,32 @@ static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43)
740786
{
741787
unsigned int mcu_rev, bios_rev, boot_status, secure_cfg;
742788
bool patched, shadow;
789+
int boot_status_reg, mcu_sw_rev_reg;
743790
int ret;
744791

792+
switch (cs42l43->variant_id) {
793+
case CS42L43_DEVID_VAL:
794+
boot_status_reg = CS42L43_BOOT_STATUS;
795+
mcu_sw_rev_reg = CS42L43_MCU_SW_REV;
796+
break;
797+
case CS42L43B_DEVID_VAL:
798+
boot_status_reg = CS42L43B_BOOT_STATUS;
799+
mcu_sw_rev_reg = CS42L43B_MCU_SW_REV;
800+
break;
801+
default:
802+
return -EINVAL;
803+
}
804+
745805
/* Clear any stale software interrupt bits. */
746806
regmap_read(cs42l43->regmap, CS42L43_SOFT_INT, &mcu_rev);
747807

748-
ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_STATUS, &boot_status);
808+
ret = regmap_read(cs42l43->regmap, boot_status_reg, &boot_status);
749809
if (ret) {
750810
dev_err(cs42l43->dev, "Failed to read boot status: %d\n", ret);
751811
return ret;
752812
}
753813

754-
ret = regmap_read(cs42l43->regmap, CS42L43_MCU_SW_REV, &mcu_rev);
814+
ret = regmap_read(cs42l43->regmap, mcu_sw_rev_reg, &mcu_rev);
755815
if (ret) {
756816
dev_err(cs42l43->dev, "Failed to read firmware revision: %d\n", ret);
757817
return ret;
@@ -918,6 +978,13 @@ static void cs42l43_boot_work(struct work_struct *work)
918978

919979
switch (devid) {
920980
case CS42L43_DEVID_VAL:
981+
case CS42L43B_DEVID_VAL:
982+
if (devid != cs42l43->variant_id) {
983+
dev_err(cs42l43->dev,
984+
"Device ID (0x%06x) does not match variant ID (0x%06lx)\n",
985+
devid, cs42l43->variant_id);
986+
goto err;
987+
}
921988
break;
922989
default:
923990
dev_err(cs42l43->dev, "Unrecognised devid: 0x%06x\n", devid);

drivers/mfd/cs42l43.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#ifndef CS42L43_CORE_INT_H
1010
#define CS42L43_CORE_INT_H
1111

12-
#define CS42L43_N_DEFAULTS 176
12+
#define CS42L43_N_DEFAULTS 189
1313

1414
struct dev_pm_ops;
1515
struct device;

include/linux/mfd/cs42l43-regs.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,4 +1181,80 @@
11811181
/* CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG */
11821182
#define CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL 0xF05AA50F
11831183

1184+
/* CS42L43B VARIANT REGISTERS */
1185+
#define CS42L43B_DEVID_VAL 0x0042A43B
1186+
1187+
#define CS42L43B_DECIM_VOL_CTRL_CH1_CH2 0x00008280
1188+
#define CS42L43B_DECIM_VOL_CTRL_CH3_CH4 0x00008284
1189+
1190+
#define CS42L43B_DECIM_VOL_CTRL_CH5_CH6 0x00008290
1191+
#define CS42L43B_DECIM_VOL_CTRL_UPDATE 0x0000829C
1192+
1193+
#define CS42L43B_DECIM_HPF_WNF_CTRL5 0x000082A0
1194+
#define CS42L43B_DECIM_HPF_WNF_CTRL6 0x000082A4
1195+
1196+
#define CS42L43B_SWIRE_DP3_CH3_INPUT 0x0000C320
1197+
#define CS42L43B_SWIRE_DP3_CH4_INPUT 0x0000C330
1198+
#define CS42L43B_SWIRE_DP4_CH3_INPUT 0x0000C340
1199+
#define CS42L43B_SWIRE_DP4_CH4_INPUT 0x0000C350
1200+
1201+
#define CS42L43B_ISRC1DEC3_INPUT1 0x0000C780
1202+
#define CS42L43B_ISRC1DEC4_INPUT1 0x0000C790
1203+
#define CS42L43B_ISRC2DEC3_INPUT1 0x0000C7A0
1204+
#define CS42L43B_ISRC2DEC4_INPUT1 0x0000C7B0
1205+
1206+
#define CS42L43B_FW_MISSION_CTRL_NEED_CONFIGS 0x00117E00
1207+
#define CS42L43B_FW_MISSION_CTRL_HAVE_CONFIGS 0x00117E04
1208+
#define CS42L43B_FW_MISSION_CTRL_PATCH_START_ADDR_REG 0x00117E08
1209+
#define CS42L43B_FW_MISSION_CTRL_MM_CTRL_SELECTION 0x00117E0C
1210+
#define CS42L43B_FW_MISSION_CTRL_MM_MCU_CFG_REG 0x00117E10
1211+
1212+
#define CS42L43B_MCU_SW_REV 0x00117314
1213+
#define CS42L43B_PATCH_START_ADDR 0x00117318
1214+
#define CS42L43B_CONFIG_SELECTION 0x0011731C
1215+
#define CS42L43B_NEED_CONFIGS 0x00117320
1216+
#define CS42L43B_BOOT_STATUS 0x00117330
1217+
1218+
#define CS42L43B_FW_MISSION_CTRL_NEED_CONFIGS 0x00117E00
1219+
#define CS42L43B_FW_MISSION_CTRL_HAVE_CONFIGS 0x00117E04
1220+
#define CS42L43B_FW_MISSION_CTRL_PATCH_START_ADDR_REG 0x00117E08
1221+
#define CS42L43B_FW_MISSION_CTRL_MM_CTRL_SELECTION 0x00117E0C
1222+
#define CS42L43B_FW_MISSION_CTRL_MM_MCU_CFG_REG 0x00117E10
1223+
1224+
#define CS42L43B_MCU_RAM_MAX 0x00117FFF
1225+
1226+
/* CS42L43B_DECIM_DECIM_VOL_CTRL_CH5_CH6 */
1227+
#define CS42L43B_DECIM6_MUTE_MASK 0x80000000
1228+
#define CS42L43B_DECIM6_MUTE_SHIFT 31
1229+
#define CS42L43B_DECIM6_VOL_MASK 0x3FC00000
1230+
#define CS42L43B_DECIM6_VOL_SHIFT 22
1231+
#define CS42L43B_DECIM6_PATH1_VOL_FALL_RATE_MASK 0x00380000
1232+
#define CS42L43B_DECIM6_PATH1_VOL_FALL_RATE_SHIFT 19
1233+
#define CS42L43B_DECIM6_PATH1_VOL_RISE_RATE_MASK 0x00070000
1234+
#define CS42L43B_DECIM6_PATH1_VOL_RISE_RATE_SHIFT 16
1235+
#define CS42L43B_DECIM5_MUTE_MASK 0x00008000
1236+
#define CS42L43B_DECIM5_MUTE_SHIFT 15
1237+
#define CS42L43B_DECIM5_VOL_MASK 0x00003FC0
1238+
#define CS42L43B_DECIM5_VOL_SHIFT 6
1239+
#define CS42L43B_DECIM5_PATH1_VOL_FALL_RATE_MASK 0x00000038
1240+
#define CS42L43B_DECIM5_PATH1_VOL_FALL_RATE_SHIFT 3
1241+
#define CS42L43B_DECIM5_PATH1_VOL_RISE_RATE_MASK 0x00000007
1242+
#define CS42L43B_DECIM5_PATH1_VOL_RISE_RATE_SHIFT 0
1243+
1244+
/* CS42L43B_DECIM_VOL_CTRL_UPDATE */
1245+
#define CS42L43B_DECIM6_PATH1_VOL_TRIG_MASK 0x00000800
1246+
#define CS42L43B_DECIM6_PATH1_VOL_TRIG_SHIFT 11
1247+
#define CS42L43B_DECIM5_PATH1_VOL_TRIG_MASK 0x00000100
1248+
#define CS42L43B_DECIM5_PATH1_VOL_TRIG_SHIFT 8
1249+
#define CS42L43B_DECIM4_VOL_UPDATE_MASK 0x00000020
1250+
#define CS42L43B_DECIM4_VOL_UPDATE_SHIFT 5
1251+
1252+
/* CS42L43_ISRC1_CTRL..CS42L43_ISRC2_CTRL */
1253+
#define CS42L43B_ISRC_DEC4_EN_MASK 0x00000008
1254+
#define CS42L43B_ISRC_DEC4_EN_SHIFT 3
1255+
#define CS42L43B_ISRC_DEC4_EN_WIDTH 1
1256+
#define CS42L43B_ISRC_DEC3_EN_MASK 0x00000004
1257+
#define CS42L43B_ISRC_DEC3_EN_SHIFT 2
1258+
#define CS42L43B_ISRC_DEC3_EN_WIDTH 1
1259+
11841260
#endif /* CS42L43_CORE_REGS_H */

include/linux/mfd/cs42l43.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct cs42l43 {
9898
bool sdw_pll_active;
9999
bool attached;
100100
bool hw_lock;
101+
long variant_id;
101102
};
102103

103104
#endif /* CS42L43_CORE_EXT_H */

0 commit comments

Comments
 (0)