Alsa-devel
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
July 2024
- 85 participants
- 229 discussions

11 Aug '24
Requriment from customer to add new kcontrol to set tas2563 digital gain
and set "Speaker Force Firmware Load" as the common kcontrol for both
tas27871 and tas2563.
Signed-off-by: Shenghao Ding <shenghao-ding(a)ti.com>
---
v1:
- Changed the copyright year to 2024 in tas2781-tlv.h.
- Changed the copyright year to 2024 in tas2781.h.
- Set "Speaker Force Firmware Load" as the common kcontrol for for both
tas27871 and tas2563, that is tasdevice_snd_controls.
- Only tas2781_snd_controls only for gain setting.
- Add tas2563_dvc_tlv kcontrol for tas2563 digital gain setting.
- In codec probe, for tas2563, loading tas2563 gain control; for tas2781,
loading tas2781 gain control.
---
include/sound/tas2781-tlv.h | 262 ++++++++++++++++++++++++++++++++-
include/sound/tas2781.h | 3 +-
sound/soc/codecs/tas2781-i2c.c | 135 ++++++++++++++++-
3 files changed, 392 insertions(+), 8 deletions(-)
diff --git a/include/sound/tas2781-tlv.h b/include/sound/tas2781-tlv.h
index 1dc59005d241..99c41bfc7827 100644
--- a/include/sound/tas2781-tlv.h
+++ b/include/sound/tas2781-tlv.h
@@ -2,7 +2,7 @@
//
// ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier
//
-// Copyright (C) 2022 - 2023 Texas Instruments Incorporated
+// Copyright (C) 2022 - 2024 Texas Instruments Incorporated
// https://www.ti.com
//
// The TAS2781 driver implements a flexible and configurable
@@ -17,5 +17,265 @@
static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0);
static const DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0);
+static const DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1);
+/* pow(10, db/20) * pow(2,30) */
+static const unsigned char tas2563_dvc_table[][4] = {
+ { 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */
+ { 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */
+ { 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */
+ { 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */
+ { 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */
+ { 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */
+ { 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */
+ { 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */
+ { 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */
+ { 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */
+ { 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */
+ { 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */
+ { 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */
+ { 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */
+ { 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */
+ { 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */
+ { 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */
+ { 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */
+ { 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */
+ { 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */
+ { 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */
+ { 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */
+ { 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */
+ { 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */
+ { 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */
+ { 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */
+ { 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */
+ { 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */
+ { 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */
+ { 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */
+ { 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */
+ { 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */
+ { 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */
+ { 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */
+ { 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */
+ { 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */
+ { 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */
+ { 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */
+ { 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */
+ { 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */
+ { 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */
+ { 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */
+ { 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */
+ { 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */
+ { 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */
+ { 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */
+ { 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */
+ { 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */
+ { 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */
+ { 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */
+ { 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */
+ { 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */
+ { 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */
+ { 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */
+ { 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */
+ { 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */
+ { 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */
+ { 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */
+ { 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */
+ { 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */
+ { 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */
+ { 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */
+ { 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */
+ { 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */
+ { 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */
+ { 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */
+ { 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */
+ { 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */
+ { 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */
+ { 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */
+ { 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */
+ { 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */
+ { 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */
+ { 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */
+ { 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */
+ { 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */
+ { 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */
+ { 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */
+ { 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */
+ { 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */
+ { 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */
+ { 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */
+ { 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */
+ { 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */
+ { 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */
+ { 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */
+ { 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */
+ { 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */
+ { 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */
+ { 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */
+ { 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */
+ { 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */
+ { 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */
+ { 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */
+ { 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */
+ { 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */
+ { 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */
+ { 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */
+ { 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */
+ { 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */
+ { 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */
+ { 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */
+ { 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */
+ { 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */
+ { 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */
+ { 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */
+ { 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */
+ { 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */
+ { 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */
+ { 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */
+ { 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */
+ { 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */
+ { 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */
+ { 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */
+ { 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */
+ { 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */
+ { 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */
+ { 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */
+ { 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */
+ { 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */
+ { 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */
+ { 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */
+ { 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */
+ { 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */
+ { 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */
+ { 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */
+ { 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */
+ { 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */
+ { 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */
+ { 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */
+ { 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */
+ { 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */
+ { 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */
+ { 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */
+ { 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */
+ { 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */
+ { 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */
+ { 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */
+ { 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */
+ { 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */
+ { 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */
+ { 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */
+ { 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */
+ { 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */
+ { 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */
+ { 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */
+ { 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */
+ { 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */
+ { 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */
+ { 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */
+ { 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */
+ { 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */
+ { 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */
+ { 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */
+ { 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */
+ { 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */
+ { 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */
+ { 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */
+ { 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */
+ { 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */
+ { 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */
+ { 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */
+ { 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */
+ { 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */
+ { 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */
+ { 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */
+ { 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */
+ { 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */
+ { 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */
+ { 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */
+ { 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */
+ { 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */
+ { 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */
+ { 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */
+ { 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */
+ { 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */
+ { 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */
+ { 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */
+ { 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */
+ { 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */
+ { 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */
+ { 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */
+ { 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */
+ { 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */
+ { 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */
+ { 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */
+ { 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */
+ { 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */
+ { 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */
+ { 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */
+ { 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */
+ { 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */
+ { 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */
+ { 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */
+ { 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */
+ { 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */
+ { 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */
+ { 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */
+ { 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */
+ { 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */
+ { 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */
+ { 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */
+ { 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */
+ { 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */
+ { 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */
+ { 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */
+ { 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */
+ { 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */
+ { 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */
+ { 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */
+ { 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */
+ { 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */
+ { 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */
+ { 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */
+ { 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */
+ { 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */
+ { 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */
+ { 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */
+ { 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */
+ { 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */
+ { 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */
+ { 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */
+ { 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */
+ { 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */
+ { 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */
+ { 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */
+ { 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */
+ { 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */
+ { 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */
+ { 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */
+ { 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */
+ { 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */
+ { 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */
+ { 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */
+ { 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */
+ { 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */
+ { 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */
+ { 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */
+ { 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */
+ { 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */
+ { 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */
+ { 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */
+ { 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */
+ { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */
+ { 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */
+ { 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */
+ { 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */
+ { 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */
+ { 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */
+ { 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */
+ { 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */
+ { 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */
+ { 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */
+ { 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */
+ { 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */
+ { 0XFF, 0XFF, 0XFF, 0XFF }, /* 6.0db */
+};
#endif
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index cd8ce522b78e..3275575f5bfb 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -2,7 +2,7 @@
//
// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
//
-// Copyright (C) 2022 - 2023 Texas Instruments Incorporated
+// Copyright (C) 2022 - 2024 Texas Instruments Incorporated
// https://www.ti.com
//
// The TAS2563/TAS2781 driver implements a flexible and configurable
@@ -50,6 +50,7 @@
#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E)
/* Volume control */
+#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C)
#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A)
#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03)
#define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1)
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index 4d1a0d836e77..4960ab6577f7 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -30,6 +30,7 @@
#include <sound/tas2781.h>
#include <sound/tlv.h>
#include <sound/tas2781-tlv.h>
+#include <asm/unaligned.h>
static const struct i2c_device_id tasdevice_id[] = {
{ "tas2563", TAS2563 },
@@ -103,7 +104,7 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
return tasdevice_amp_putvol(tas_priv, ucontrol, mc);
}
-static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
+static int tasdev_force_fwload_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
@@ -118,7 +119,7 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
+static int tasdev_force_fwload_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
@@ -127,18 +128,114 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(component);
bool change, val = (bool)ucontrol->value.integer.value[0];
+ mutex_lock(&tas_priv->codec_lock);
if (tas_priv->force_fwload_status == val)
change = false;
else {
change = true;
tas_priv->force_fwload_status = val;
}
+ mutex_unlock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
tas_priv->force_fwload_status ? "ON" : "OFF");
return change;
}
+static int tas2563_digital_gain_get(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_dev = snd_soc_component_get_drvdata(codec);
+ unsigned int l = 0, r = mc->max;
+ unsigned int target, ar_mid, mid, ar_l, ar_r;
+ unsigned int reg = mc->reg;
+ unsigned char data[4];
+ int ret;
+
+ mutex_lock(&tas_dev->codec_lock);
+ /* Read the primary device */
+ ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4);
+ if (ret) {
+ dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__);
+ goto out;
+ }
+
+ target = get_unaligned_be32(&data[0]);
+
+ while (r > 1 + l) {
+ mid = (l + r) / 2;
+ ar_mid = get_unaligned_be32(tas2563_dvc_table[mid]);
+ if (target < ar_mid)
+ r = mid;
+ else
+ l = mid;
+ }
+
+ ar_l = get_unaligned_be32(tas2563_dvc_table[l]);
+ ar_r = get_unaligned_be32(tas2563_dvc_table[r]);
+
+ /* find out the member same as or closer to the current volume */
+ ucontrol->value.integer.value[0] =
+ abs(target - ar_l) <= abs(target - ar_r) ? l : r;
+out:
+ mutex_unlock(&tas_dev->codec_lock);
+ return 0;
+}
+
+static int tas2563_digital_gain_put(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_dev = snd_soc_component_get_drvdata(codec);
+ unsigned int reg = mc->reg;
+ unsigned int volrd, volwr;
+ int vol = ucontrol->value.integer.value[0];
+ int max = mc->max, i, ret = 1;
+ unsigned char data[4];
+
+ vol = clamp(vol, 0, max);
+ mutex_lock(&tas_dev->codec_lock);
+ /* Read the primary device */
+ ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4);
+ if (ret) {
+ dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__);
+ goto out;
+ }
+
+ volrd = get_unaligned_be32(&data[0]);
+ volwr = get_unaligned_be32(tas2563_dvc_table[vol]);
+
+ if (volrd == volwr) {
+ ret = 0;
+ goto out;
+ }
+
+ for (i = 0; i < tas_dev->ndev; i++) {
+ ret = tasdevice_dev_bulk_write(tas_dev, i, reg,
+ (unsigned char *)tas2563_dvc_table[vol], 4);
+ if (ret)
+ dev_err(tas_dev->dev,
+ "%s, set digital vol error in device %d\n",
+ __func__, i);
+ }
+
+out:
+ mutex_unlock(&tas_dev->codec_lock);
+ return ret;
+}
+
+static const struct snd_kcontrol_new tasdevice_snd_controls[] = {
+ SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
+ tasdev_force_fwload_get, tasdev_force_fwload_put),
+};
+
static const struct snd_kcontrol_new tas2781_snd_controls[] = {
SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL,
1, 0, 20, 0, tas2781_amp_getvol,
@@ -146,8 +243,13 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = {
SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL,
0, 0, 200, 1, tas2781_digital_getvol,
tas2781_digital_putvol, dvc_tlv),
- SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
- tas2781_force_fwload_get, tas2781_force_fwload_put),
+};
+
+static const struct snd_kcontrol_new tas2563_snd_controls[] = {
+ SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2563_DVC_LVL, 0,
+ 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0,
+ tas2563_digital_gain_get, tas2563_digital_gain_put,
+ tas2563_dvc_tlv),
};
static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
@@ -578,6 +680,27 @@ static struct snd_soc_dai_driver tasdevice_dai_driver[] = {
static int tasdevice_codec_probe(struct snd_soc_component *codec)
{
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
+ int rc;
+
+ if (tas_priv->chip_id == TAS2781) {
+ rc = snd_soc_add_component_controls(codec,
+ tas2781_snd_controls,
+ ARRAY_SIZE(tas2781_snd_controls));
+ if (rc < 0) {
+ dev_err(tas_priv->dev, "%s: Add control err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+ } else {
+ rc = snd_soc_add_component_controls(codec,
+ tas2563_snd_controls,
+ ARRAY_SIZE(tas2563_snd_controls));
+ if (rc < 0) {
+ dev_err(tas_priv->dev, "%s: Add control err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+ }
tas_priv->name_prefix = codec->name_prefix;
return tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready);
@@ -605,8 +728,8 @@ static const struct snd_soc_component_driver
soc_codec_driver_tasdevice = {
.probe = tasdevice_codec_probe,
.remove = tasdevice_codec_remove,
- .controls = tas2781_snd_controls,
- .num_controls = ARRAY_SIZE(tas2781_snd_controls),
+ .controls = tasdevice_snd_controls,
+ .num_controls = ARRAY_SIZE(tasdevice_snd_controls),
.dapm_widgets = tasdevice_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tasdevice_dapm_widgets),
.dapm_routes = tasdevice_audio_map,
--
2.34.1
4
3

[PATCH AUTOSEL 5.10 02/11] ASoC: Intel: sof_sdw: Add quirks for some new Dell laptops
by Sasha Levin 10 Aug '24
by Sasha Levin 10 Aug '24
10 Aug '24
From: Charles Keepax <ckeepax(a)opensource.cirrus.com>
[ Upstream commit 91cdecaba791c74df6da0650e797fe1192cf2700 ]
Add quirks for some new Dell laptops using Cirrus amplifiers in a bridge
configuration.
Reviewed-by: Bard Liao <yung-chuan.liao(a)linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax(a)opensource.cirrus.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Link: https://msgid.link/r/20240527193552.165567-11-pierre-louis.bossart@linux.in…
Signed-off-by: Mark Brown <broonie(a)kernel.org>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
sound/soc/intel/boards/sof_sdw.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index 25bf73a7e7bfa..ad3694d36d969 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -234,6 +234,22 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
},
.driver_data = (void *)(RT711_JD2_100K),
},
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3")
+ },
+ .driver_data = (void *)(SOF_SIDECAR_AMPS),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4")
+ },
+ .driver_data = (void *)(SOF_SIDECAR_AMPS),
+ },
{}
};
--
2.43.0
2
2
This patchset updates some sample rate definition for eARC support.
Notably it:
* adds the definition for 128kHz
* update the ASoC spdif codecs to include all supported rates, up to 768kHz
* adds missing IEC958 definition for 128k, 352.4k, 384k and 705.6kHz
On that last point, as noted in the related commit description, I'd like to
stress that I have found the definitions using a testing equipement. I
do not have access to the IEC958 specification. It would be best if someone
with access to this specification could review/ack patch #2, before
applying it.
Jerome Brunet (3):
ALSA: pcm: add support for 128kHz sample rate
ALSA: IEC958 definition for consumer status channel update
ASoC: spdif: extend supported rates to 768kHz
include/sound/asoundef.h | 6 +++++-
include/sound/pcm.h | 13 +++++++------
sound/core/pcm_native.c | 6 +++---
sound/soc/codecs/spdif_receiver.c | 3 ++-
sound/soc/codecs/spdif_transmitter.c | 3 ++-
5 files changed, 19 insertions(+), 12 deletions(-)
--
2.43.0
5
15

[PATCH v1] ASoc: tas2781: Add Calibration Kcontrols and tas2563 digtial gain for Chromebook
by Shenghao Ding 09 Aug '24
by Shenghao Ding 09 Aug '24
09 Aug '24
Calibrated data will be set to default after loading DSP config params,
which will cause speaker protection work abnormally. Reload calibrated
data after loading DSP config params.
Signed-off-by: Shenghao Ding <shenghao-ding(a)ti.com>
---
v1:
- Changed the copyright year to 2024 in the related files.
- Add CAL_DAT_SZ for calibrated data size.
- Add TAS2563_DVC_LVL for digtial gain kcontrol.
- Add registers for TAS2563 and TAS2781 calibration.
- Add cali_data_restore for regsiter restore after calibration.
- Add is_user_space_calidata to store the flag where the calibrated
from, user space or bin file from driver parsing.
- Add TASDEVICE_RCA_FW_OK to support only register setting bin in the
device.
- Add tas2563_dvc_table for relationship between tas2563 digtial gains
and register values.
- Correct the filename in the header comments of tas2781-comlib.c,
tas2781-lib.c --> tas2781-comlib.c.
- tasdevice_chn_switch for chip switch among multiple chips(tas2563
or tas2781)
- Add loading the calibrated values from user space in
tasdev_load_calibrated_data
- Correct no dsp no work, it can still work in bypass mode.
- Add calibrated register setting for tas2563&tas2781.
- Add mutex into each kcontrol.
- rename tas2781_force_fwload_get, tas2781_force_fwload_put-->
tasdev_force_fwload_get, tasdev_force_fwload_put
- rename tas2781_codec --> tasdev_codec
- define tas2781_snd_control and tas2563_snd_control for volume
- define tas2781_cali_control and tas2563_cali_control for calibration
---
include/sound/tas2781-dsp.h | 1 +
include/sound/tas2781.h | 92 ++-
sound/soc/codecs/tas2781-comlib.c | 35 +-
sound/soc/codecs/tas2781-fmwlib.c | 51 +-
sound/soc/codecs/tas2781-i2c.c | 941 +++++++++++++++++++++++++++++-
5 files changed, 1061 insertions(+), 59 deletions(-)
diff --git a/include/sound/tas2781-dsp.h b/include/sound/tas2781-dsp.h
index 7fba7ea26a4b..74ab6f113029 100644
--- a/include/sound/tas2781-dsp.h
+++ b/include/sound/tas2781-dsp.h
@@ -121,6 +121,7 @@ enum tasdevice_dsp_fw_state {
TASDEVICE_DSP_FW_NONE = 0,
TASDEVICE_DSP_FW_PENDING,
TASDEVICE_DSP_FW_FAIL,
+ TASDEVICE_RCA_FW_OK,
TASDEVICE_DSP_FW_ALL_OK,
};
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index 99ca3e401fd1..2fb3d03d0040 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -2,7 +2,7 @@
//
// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
//
-// Copyright (C) 2022 - 2023 Texas Instruments Incorporated
+// Copyright (C) 2022 - 2024 Texas Instruments Incorporated
// https://www.ti.com
//
// The TAS2563/TAS2781 driver implements a flexible and configurable
@@ -23,6 +23,8 @@
#define SMARTAMP_MODULE_NAME "tas2781"
#define TAS2781_GLOBAL_ADDR 0x40
#define TAS2563_GLOBAL_ADDR 0x48
+#define CAL_DAT_SZ 20
+
#define TASDEVICE_RATES (SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_88200)
@@ -31,6 +33,11 @@
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
+#define TASDEVICE_CMD_SING_W 0x1
+#define TASDEVICE_CMD_BURST 0x2
+#define TASDEVICE_CMD_DELAY 0x3
+#define TASDEVICE_CMD_FIELD_W 0x4
+
/*PAGE Control Register (available in page0 of each book) */
#define TASDEVICE_PAGE_SELECT 0x00
#define TASDEVICE_BOOKCTL_PAGE 0x00
@@ -43,21 +50,73 @@
(page * 128)) + reg)
/*Software Reset */
-#define TAS2781_REG_SWRESET TASDEVICE_REG(0x0, 0X0, 0x01)
-#define TAS2781_REG_SWRESET_RESET BIT(0)
+#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x00, 0X00, 0x01)
+#define TASDEVICE_REG_SWRESET_RESET BIT(0)
/*I2C Checksum */
-#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E)
+#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x00, 0x00, 0x7E)
+
+/* XM_340 */
+#define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x02, 0x4c)
+/* XM_341 */
+#define TASDEVICE_XM_A2_REG TASDEVICE_REG(0x64, 0x02, 0x64)
/* Volume control */
-#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A)
-#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03)
+#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0C)
+#define TAS2781_DVC_LVL TASDEVICE_REG(0x00, 0x00, 0x1A)
+#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x00, 0x00, 0x03)
#define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1)
-#define TASDEVICE_CMD_SING_W 0x1
-#define TASDEVICE_CMD_BURST 0x2
-#define TASDEVICE_CMD_DELAY 0x3
-#define TASDEVICE_CMD_FIELD_W 0x4
+#define TAS2563_PRM_R0_REG TASDEVICE_REG(0x00, 0x0f, 0x34)
+#define TAS2563_PRM_R0_LOW_REG TASDEVICE_REG(0x00, 0x0f, 0x48)
+#define TAS2563_PRM_INVR0_REG TASDEVICE_REG(0x00, 0x0f, 0x40)
+#define TAS2563_PRM_POW_REG TASDEVICE_REG(0x00, 0x0d, 0x3c)
+#define TAS2563_PRM_TLIMIT_REG TASDEVICE_REG(0x00, 0x10, 0x14)
+
+#define TAS2563_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x02, 0x70)
+#define TAS2563_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x02, 0x48)
+
+#define TAS2563_PRM_ENFF_REG TASDEVICE_REG(0x00, 0x0d, 0x54)
+#define TAS2563_PRM_DISTCK_REG TASDEVICE_REG(0x00, 0x0d, 0x58)
+#define TAS2563_PRM_TE_SCTHR_REG TASDEVICE_REG(0x00, 0x0f, 0x60)
+#define TAS2563_PRM_PLT_FLAG_REG TASDEVICE_REG(0x00, 0x0d, 0x74)
+#define TAS2563_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x0d, 0x7c)
+/* prm_Int_B0 */
+#define TAS2563_TE_TA1_REG TASDEVICE_REG(0x00, 0x10, 0x0c)
+/* prm_Int_A1 */
+#define TAS2563_TE_TA1_AT_REG TASDEVICE_REG(0x00, 0x10, 0x10)
+/* prm_TE_Beta */
+#define TAS2563_TE_TA2_REG TASDEVICE_REG(0x00, 0x0f, 0x64)
+/* prm_TE_Beta1 */
+#define TAS2563_TE_AT_REG TASDEVICE_REG(0x00, 0x0f, 0x68)
+/* prm_TE_1_Beta1 */
+#define TAS2563_TE_DT_REG TASDEVICE_REG(0x00, 0x0f, 0x70)
+
+#define TAS2781_PRM_R0_REG TASDEVICE_REG(0x00, 0x17, 0x74)
+#define TAS2781_PRM_R0_LOW_REG TASDEVICE_REG(0x00, 0x18, 0x0c)
+#define TAS2781_PRM_INVR0_REG TASDEVICE_REG(0x00, 0x18, 0x14)
+#define TAS2781_PRM_POW_REG TASDEVICE_REG(0x00, 0x13, 0x70)
+#define TAS2781_PRM_TLIMIT_REG TASDEVICE_REG(0x00, 0x18, 0x7c)
+
+#define TAS2781_PRM_INT_MASK_REG TASDEVICE_REG(0x00, 0x00, 0x3b)
+#define TAS2781_PRM_CLK_CFG_REG TASDEVICE_REG(0x00, 0x00, 0x5c)
+#define TAS2781_PRM_RSVD_REG TASDEVICE_REG(0x00, 0x01, 0x19)
+#define TAS2781_PRM_TEST_57_REG TASDEVICE_REG(0x00, 0xfd, 0x39)
+#define TAS2781_PRM_TEST_62_REG TASDEVICE_REG(0x00, 0xfd, 0x3e)
+#define TAS2781_PRM_PVDD_UVLO_REG TASDEVICE_REG(0x00, 0x00, 0x71)
+#define TAS2781_PRM_CHNL_0_REG TASDEVICE_REG(0x00, 0x00, 0x03)
+#define TAS2781_PRM_NG_CFG0_REG TASDEVICE_REG(0x00, 0x00, 0x35)
+#define TAS2781_PRM_IDLE_CH_DET_REG TASDEVICE_REG(0x00, 0x00, 0x66)
+#define TAS2781_PRM_PLT_FLAG_REG TASDEVICE_REG(0x00, 0x14, 0x38)
+#define TAS2781_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x14, 0x40)
+#define TAS2781_PRM_SINEGAIN2_REG TASDEVICE_REG(0x00, 0x14, 0x44)
+
+#define TAS2781_TEST_UNLOCK_REG TASDEVICE_REG(0x00, 0xFD, 0x0D)
+#define TAS2781_TEST_PAGE_UNLOCK 0x0D
+
+#define TAS2781_RUNTIME_LATCH_RE_REG TASDEVICE_REG(0x00, 0x00, 0x49)
+#define TAS2781_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x62, 0x48)
+#define TAS2781_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x63, 0x44)
enum audio_device {
TAS2563,
@@ -69,7 +128,15 @@ enum device_catlog_id {
OTHERS
};
+struct bulk_reg_val {
+ int reg;
+ unsigned char val[4];
+ unsigned char val_len;
+ bool is_locked;
+};
+
struct tasdevice {
+ struct bulk_reg_val *cali_data_restore;
struct tasdevice_fw *cali_data_fmw;
unsigned int dev_addr;
unsigned int err_code;
@@ -88,6 +155,8 @@ struct tasdevice_irqinfo {
struct calidata {
unsigned char *data;
unsigned long total_sz;
+ unsigned int *reg_array;
+ unsigned int reg_array_sz;
};
struct tasdevice_priv {
@@ -122,6 +191,7 @@ struct tasdevice_priv {
bool force_fwload_status;
bool playback_started;
bool isacpi;
+ bool is_user_space_calidata;
unsigned int global_addr;
int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,
@@ -148,6 +218,8 @@ int tasdevice_init(struct tasdevice_priv *tas_priv);
void tasdevice_remove(struct tasdevice_priv *tas_priv);
int tasdevice_save_calibration(struct tasdevice_priv *tas_priv);
void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv);
+int tasdevice_chn_switch(struct tasdevice_priv *tas_priv,
+ unsigned short chn);
int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
unsigned short chn, unsigned int reg, unsigned int *value);
int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c
index 3aa81514dad7..9d7b56663b6b 100644
--- a/sound/soc/codecs/tas2781-comlib.c
+++ b/sound/soc/codecs/tas2781-comlib.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
//
-// tas2781-lib.c -- TAS2781 Common functions for HDA and ASoC Audio drivers
+// tas2781-comlib.c -- TAS2781 Common functions for HDA and ASoC Audio drivers
//
-// Copyright 2023 Texas Instruments, Inc.
+// Copyright 2023 - 2024 Texas Instruments, Inc.
//
// Author: Shenghao Ding <shenghao-ding(a)ti.com>
@@ -89,6 +89,33 @@ static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv,
return ret;
}
+int tasdevice_chn_switch(struct tasdevice_priv *tas_priv,
+ unsigned short chn)
+{
+ struct i2c_client *client = (struct i2c_client *)tas_priv->client;
+ struct tasdevice *tasdev = &tas_priv->tasdevice[chn];
+ struct regmap *map = tas_priv->regmap;
+ int ret;
+
+ if (client->addr != tasdev->dev_addr) {
+ client->addr = tasdev->dev_addr;
+ /* All devices share the same regmap, clear the page
+ * inside regmap once switching to another device.
+ * Register 0 at any pages and any books inside tas2781
+ * is the same one for page-switching.
+ */
+ ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0);
+ if (ret < 0) {
+ dev_err(tas_priv->dev, "%s, E=%d\n",
+ __func__, ret);
+ return ret;
+ }
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tasdevice_chn_switch);
+
int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
unsigned short chn, unsigned int reg, unsigned int *val)
{
@@ -254,8 +281,8 @@ void tas2781_reset(struct tasdevice_priv *tas_dev)
} else {
for (i = 0; i < tas_dev->ndev; i++) {
ret = tasdevice_dev_write(tas_dev, i,
- TAS2781_REG_SWRESET,
- TAS2781_REG_SWRESET_RESET);
+ TASDEVICE_REG_SWRESET,
+ TASDEVICE_REG_SWRESET_RESET);
if (ret < 0)
dev_err(tas_dev->dev,
"dev %d swreset fail, %d\n",
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index 265a8ca25cbb..19a5133083dc 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -2153,20 +2153,39 @@ static int tasdevice_load_data(struct tasdevice_priv *tas_priv,
static void tasdev_load_calibrated_data(struct tasdevice_priv *priv, int i)
{
+ struct tasdevice_fw *cal_fmw = priv->tasdevice[i].cali_data_fmw;
+ struct calidata *cali_data = &priv->cali_data;
+ unsigned char *data = cali_data->data;
struct tasdevice_calibration *cal;
- struct tasdevice_fw *cal_fmw;
+ int k = i * (CAL_DAT_SZ + 1);
+ int j, rc;
- cal_fmw = priv->tasdevice[i].cali_data_fmw;
+ if (!priv->is_user_space_calidata &&
+ cal_fmw) {
+ cal = cal_fmw->calibrations;
- /* No calibrated data for current devices, playback will go ahead. */
- if (!cal_fmw)
+ if (cal)
+ load_calib_data(priv, &cal->dev_data);
return;
-
- cal = cal_fmw->calibrations;
- if (cal)
+ }
+ if (!priv->is_user_space_calidata)
return;
-
- load_calib_data(priv, &cal->dev_data);
+ /* load calibrated data from user space */
+ if (data[k] != i) {
+ dev_err(priv->dev, "%s: no cal-data for dev %d from usr-spc\n",
+ __func__, i);
+ return;
+ }
+ for (j = 0; j < cali_data->reg_array_sz; j++) {
+ if (data[k] != j)
+ rc = tasdevice_dev_bulk_write(priv, i,
+ cali_data->reg_array[j],
+ &(data[k + 4 * j]), 4);
+ if (rc < 0)
+ dev_err(priv->dev,
+ "chn %d calib %d bulk_wr err = %d\n",
+ i, j, rc);
+ }
}
int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
@@ -2261,9 +2280,10 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
tas_priv->tasdevice[i].cur_conf = cfg_no;
}
}
- } else
+ } else {
dev_dbg(tas_priv->dev, "%s: Unneeded loading dsp conf %d\n",
__func__, cfg_no);
+ }
status |= cfg_info[rca_conf_no]->active_dev;
@@ -2324,13 +2344,15 @@ void tasdevice_tuning_switch(void *context, int state)
struct tasdevice_fw *tas_fmw = tas_priv->fmw;
int profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
- dev_err(tas_priv->dev, "DSP bin file not loaded\n");
+ /* Only RCA file loaded still can work without speaker protection */
+ if (!(tas_priv->fw_state == TASDEVICE_RCA_FW_OK ||
+ tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)) {
+ dev_err(tas_priv->dev, "No firmware loaded\n");
return;
}
if (state == 0) {
- if (tas_priv->cur_prog < tas_fmw->nr_programs) {
+ if (tas_fmw && tas_priv->cur_prog < tas_fmw->nr_programs) {
/*dsp mode or tuning mode*/
profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
tasdevice_select_tuningprm_cfg(tas_priv,
@@ -2340,9 +2362,10 @@ void tasdevice_tuning_switch(void *context, int state)
tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,
TASDEVICE_BIN_BLK_PRE_POWER_UP);
- } else
+ } else {
tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,
TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
+ }
}
EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch,
SND_SOC_TAS2781_FMWLIB);
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index 9350972dfefe..239f3538c558 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -13,6 +13,7 @@
// Author: Kevin Lu <kevin-lu(a)ti.com>
//
+#include <asm/unaligned.h>
#include <linux/crc8.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
@@ -31,6 +32,122 @@
#include <sound/tlv.h>
#include <sound/tas2781-tlv.h>
+static const struct bulk_reg_val tas2563_cali_start_reg[] = {
+ {
+ .reg = TAS2563_PRM_ENFF_REG,
+ .val = { 0x40, 0x00, 0x00, 0x00 },
+ },
+ {
+ .reg = TAS2563_PRM_DISTCK_REG,
+ .val = { 0x40, 0x00, 0x00, 0x00 },
+ },
+ {
+ .reg = TAS2563_PRM_TE_SCTHR_REG,
+ .val = { 0x7f, 0xff, 0xff, 0xff },
+ },
+ {
+ .reg = TAS2563_PRM_PLT_FLAG_REG,
+ .val = { 0x40, 0x00, 0x00, 0x00 },
+ },
+ {
+ .reg = TAS2563_PRM_SINEGAIN_REG,
+ .val = { 0x0a, 0x3d, 0x70, 0xa4 },
+ },
+ {
+ .reg = TAS2563_TE_TA1_REG,
+ .val = { 0x00, 0x36, 0x91, 0x5e },
+ },
+ {
+ .reg = TAS2563_TE_TA1_AT_REG,
+ .val = { 0x00, 0x36, 0x91, 0x5e },
+ },
+ {
+ .reg = TAS2563_TE_TA2_REG,
+ .val = { 0x00, 0x06, 0xd3, 0x72 },
+ },
+ {
+ .reg = TAS2563_TE_AT_REG,
+ .val = { 0x00, 0x36, 0x91, 0x5e },
+ },
+ {
+ .reg = TAS2563_TE_DT_REG,
+ .val = { 0x00, 0x36, 0x91, 0x5e },
+ },
+};
+
+static const struct bulk_reg_val tas2781_cali_start_reg[] = {
+ {
+ .reg = TAS2781_PRM_INT_MASK_REG,
+ .val = { 0xfe },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_CLK_CFG_REG,
+ .val = { 0xdd },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_RSVD_REG,
+ .val = { 0x20 },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_TEST_57_REG,
+ .val = { 0x14 },
+ .val_len = 1,
+ .is_locked = true
+ },
+ {
+ .reg = TAS2781_PRM_TEST_62_REG,
+ .val = { 0x45 },
+ .val_len = 1,
+ .is_locked = true
+ },
+ {
+ .reg = TAS2781_PRM_PVDD_UVLO_REG,
+ .val = { 0x03 },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_CHNL_0_REG,
+ .val = { 0xA8 },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_NG_CFG0_REG,
+ .val = { 0xb9 },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_IDLE_CH_DET_REG,
+ .val = { 0x92 },
+ .val_len = 1,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_PLT_FLAG_REG,
+ .val = { 0x40, 0x00, 0x00, 0x00 },
+ .val_len = 4,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_SINEGAIN_REG,
+ .val_len = 4,
+ .is_locked = false
+ },
+ {
+ .reg = TAS2781_PRM_SINEGAIN2_REG,
+ .val_len = 4,
+ .is_locked = false
+ },
+};
+
static const struct i2c_device_id tasdevice_id[] = {
{ "tas2563", TAS2563 },
{ "tas2781", TAS2781 },
@@ -47,6 +164,22 @@ static const struct of_device_id tasdevice_of_match[] = {
MODULE_DEVICE_TABLE(of, tasdevice_of_match);
#endif
+static const int tas2563_cali_data_reg[] = {
+ TAS2563_PRM_R0_REG,
+ TAS2563_PRM_R0_LOW_REG,
+ TAS2563_PRM_INVR0_REG,
+ TAS2563_PRM_POW_REG,
+ TAS2563_PRM_TLIMIT_REG,
+};
+
+static const int tas2781_cali_data_reg[] = {
+ TAS2781_PRM_R0_REG,
+ TAS2781_PRM_R0_LOW_REG,
+ TAS2781_PRM_INVR0_REG,
+ TAS2781_PRM_POW_REG,
+ TAS2781_PRM_TLIMIT_REG,
+};
+
/**
* tas2781_digital_getvol - get the volum control
* @kcontrol: control pointer
@@ -65,8 +198,13 @@ static int tas2781_digital_getvol(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ int rc;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = tasdevice_digital_getvol(tas_priv, ucontrol, mc);
+ mutex_unlock(&tas_priv->codec_lock);
- return tasdevice_digital_getvol(tas_priv, ucontrol, mc);
+ return rc;
}
static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol,
@@ -76,8 +214,13 @@ static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ int rc;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = tasdevice_digital_putvol(tas_priv, ucontrol, mc);
+ mutex_unlock(&tas_priv->codec_lock);
- return tasdevice_digital_putvol(tas_priv, ucontrol, mc);
+ return rc;
}
static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
@@ -87,8 +230,13 @@ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ int rc;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = tasdevice_amp_getvol(tas_priv, ucontrol, mc);
+ mutex_unlock(&tas_priv->codec_lock);
- return tasdevice_amp_getvol(tas_priv, ucontrol, mc);
+ return rc;
}
static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
@@ -99,11 +247,16 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(codec);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ int rc;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = tasdevice_amp_putvol(tas_priv, ucontrol, mc);
+ mutex_unlock(&tas_priv->codec_lock);
- return tasdevice_amp_putvol(tas_priv, ucontrol, mc);
+ return rc;
}
-static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
+static int tasdev_force_fwload_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
@@ -118,7 +271,7 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
+static int tasdev_force_fwload_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
@@ -127,18 +280,496 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(component);
bool change, val = (bool)ucontrol->value.integer.value[0];
+ mutex_lock(&tas_priv->codec_lock);
if (tas_priv->force_fwload_status == val)
change = false;
else {
change = true;
tas_priv->force_fwload_status = val;
}
+ mutex_unlock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
tas_priv->force_fwload_status ? "ON" : "OFF");
return change;
}
+static int tasdev_cali_data_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ unsigned char *data = tas_priv->cali_data.data;
+
+ mutex_lock(&tas_priv->codec_lock);
+ if (!tas_priv->is_user_space_calidata ||
+ tas_priv->cali_data.total_sz != bytes_ext->max) {
+ goto out;
+ }
+ memcpy(dst, data, bytes_ext->max);
+out:
+ mutex_unlock(&tas_priv->codec_lock);
+ return 0;
+}
+
+static int calib_data_get(struct tasdevice_priv *tas_priv, int reg,
+ unsigned char *dst, int data_len)
+{
+ struct i2c_client *clt = (struct i2c_client *)tas_priv->client;
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ int rc = -1;
+ int i;
+
+ if (data_len != 4)
+ return rc;
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ if (clt->addr == tasdev[i].dev_addr) {
+ /* First byte is the device index. */
+ dst[0] = i;
+ tasdevice_dev_bulk_read(tas_priv, i, reg, &dst[1],
+ 4);
+ rc = 0;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int tas2781_calib_start_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ const int sum = ARRAY_SIZE(tas2781_cali_start_reg);
+ unsigned char *dat = ucontrol->value.bytes.data;
+ int rc = 1;
+ int i, j;
+
+ mutex_lock(&tas_priv->codec_lock);
+ if (tas_priv->chip_id != TAS2781 &&
+ bytes_ext->max != 8 * tas_priv->ndev) {
+ rc = -1;
+ goto out;
+ }
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ struct bulk_reg_val *p = tasdev[i].cali_data_restore;
+ int k = i * 9;
+
+ if (p == NULL)
+ continue;
+
+ for (j = 0; j < sum; j++) {
+ if (p[j].val_len == 1) {
+ if (p[j].is_locked)
+ tasdevice_dev_write(tas_priv, i,
+ TAS2781_TEST_UNLOCK_REG,
+ TAS2781_TEST_PAGE_UNLOCK);
+ tasdevice_dev_read(tas_priv, i, p[j].reg,
+ (int *)&p[j].val[0]);
+ } else
+ tasdevice_dev_bulk_read(tas_priv, i, p[j].reg,
+ p[j].val, 4);
+ }
+
+ for (j = 0; j < sum - 2; j++) {
+ if (p[j].val_len == 1) {
+ if (p[j].is_locked)
+ tasdevice_dev_write(tas_priv, i,
+ TAS2781_TEST_UNLOCK_REG,
+ TAS2781_TEST_PAGE_UNLOCK);
+ tasdevice_dev_write(tas_priv, i, p[j].reg,
+ tas2781_cali_start_reg[j].val[0]);
+ } else
+ tasdevice_dev_bulk_write(tas_priv, i, p[j].reg,
+ (unsigned char *)
+ tas2781_cali_start_reg[j].val, 4);
+ }
+
+ if (dat[k] != i) {
+ dev_err(tas_priv->dev,
+ "%s: no cal-setting for dev %d\n", __func__,
+ i);
+ continue;
+ }
+ tasdevice_dev_bulk_write(tas_priv, i, p[j].reg,
+ &dat[i * 9 + 1], 4);
+ tasdevice_dev_bulk_write(tas_priv, i, p[j + 1].reg,
+ &dat[i * 9 + 5], 4);
+ }
+out:
+ mutex_unlock(&tas_priv->codec_lock);
+ return rc;
+}
+
+static void tas2781_calib_stop_put(struct tasdevice_priv *tas_priv)
+{
+ const int sum = ARRAY_SIZE(tas2781_cali_start_reg);
+ int i, j;
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ struct bulk_reg_val *p = tasdev[i].cali_data_restore;
+
+ if (p == NULL)
+ continue;
+
+ for (j = 0; j < sum; j++) {
+ if (p[j].val_len == 1) {
+ if (p[j].is_locked)
+ tasdevice_dev_write(tas_priv, i,
+ TAS2781_TEST_UNLOCK_REG,
+ TAS2781_TEST_PAGE_UNLOCK);
+ tasdevice_dev_write(tas_priv, i, p[j].reg,
+ p[j].val[0]);
+ } else
+ tasdevice_dev_bulk_write(tas_priv, i, p[j].reg,
+ p[j].val, 4);
+ }
+ }
+}
+
+static int tas2563_calib_start_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ const int sum = ARRAY_SIZE(tas2563_cali_start_reg);
+ int rc = 1;
+ int i, j;
+
+ mutex_lock(&tas_priv->codec_lock);
+ if (tas_priv->chip_id != TAS2563) {
+ rc = -1;
+ goto out;
+ }
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ struct bulk_reg_val *p = tasdev[i].cali_data_restore;
+
+ if (p == NULL)
+ continue;
+ for (j = 0; j < sum; j++) {
+ tasdevice_dev_bulk_read(tas_priv, i, p[j].reg,
+ p[j].val, 4);
+ }
+
+ for (j = 0; j < sum; j++) {
+ tasdevice_dev_bulk_write(tas_priv, i, p[j].reg,
+ (unsigned char *)tas2563_cali_start_reg[j].val,
+ 4);
+ }
+ }
+out:
+ mutex_unlock(&tas_priv->codec_lock);
+ return rc;
+}
+
+static void tas2563_calib_stop_put(struct tasdevice_priv *tas_priv)
+{
+ const int sum = ARRAY_SIZE(tas2563_cali_start_reg);
+ int i, j;
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ struct bulk_reg_val *p = tasdev[i].cali_data_restore;
+
+ if (p == NULL)
+ continue;
+
+ for (j = 0; j < sum; j++) {
+ tasdevice_dev_bulk_write(tas_priv, i, p[j].reg,
+ p[j].val, 4);
+ }
+ }
+}
+
+static int tasdev_calib_stop_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+
+ mutex_lock(&tas_priv->codec_lock);
+ if (tas_priv->chip_id == TAS2563)
+ tas2563_calib_stop_put(tas_priv);
+ else
+ tas2781_calib_stop_put(tas_priv);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return 1;
+}
+
+static int tasdev_cali_data_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *data = tas_priv->cali_data.data;
+ int rc = 1;
+
+ mutex_lock(&tas_priv->codec_lock);
+ if (tas_priv->cali_data.total_sz != bytes_ext->max) {
+ rc = -1;
+ goto out;
+ }
+ tas_priv->is_user_space_calidata = true;
+ memcpy(data, ucontrol->value.bytes.data, bytes_ext->max);
+out:
+ mutex_unlock(&tas_priv->codec_lock);
+ return rc;
+}
+
+static int tas2781_latch_reg_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct i2c_client *clt = (struct i2c_client *)tas_priv->client;
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ int i, val, rc = -1;
+
+ mutex_lock(&tas_priv->codec_lock);
+ for (i = 0; i < tas_priv->ndev; i++) {
+ if (clt->addr == tasdev[i].dev_addr) {
+ /* First byte is the device index. */
+ dst[0] = i;
+ tasdevice_dev_read(tas_priv, i,
+ TAS2781_RUNTIME_LATCH_RE_REG, &val);
+ dst[1] = val;
+ rc = 0;
+ break;
+ }
+ }
+ mutex_unlock(&tas_priv->codec_lock);
+ return rc;
+}
+
+static int tasdev_tf_data_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ unsigned int reg;
+ int rc = -1;
+
+ if (tas_priv->chip_id == TAS2781)
+ reg = TAS2781_RUNTIME_RE_REG_TF;
+ else
+ reg = TAS2563_RUNTIME_RE_REG_TF;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = calib_data_get(tas_priv, reg, dst, bytes_ext->max - 1);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return rc;
+}
+
+static int tasdev_re_data_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ unsigned int reg;
+ int rc = -1;
+
+ if (tas_priv->chip_id == TAS2781)
+ reg = TAS2781_RUNTIME_RE_REG;
+ else
+ reg = TAS2563_RUNTIME_RE_REG;
+ mutex_lock(&tas_priv->codec_lock);
+ rc = calib_data_get(tas_priv, reg, dst, bytes_ext->max - 1);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return rc;
+}
+
+static int tasdev_r0_data_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ unsigned int reg;
+ int rc = -1;
+
+ if (tas_priv->chip_id == TAS2781)
+ reg = TAS2781_PRM_R0_REG;
+ else
+ reg = TAS2563_PRM_R0_REG;
+ mutex_lock(&tas_priv->codec_lock);
+ rc = calib_data_get(tas_priv, reg, dst, bytes_ext->max - 1);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return rc;
+}
+
+static int tasdev_XMA1_data_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ unsigned int reg = TASDEVICE_XM_A1_REG;
+ int rc = -1;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = calib_data_get(tas_priv, reg, dst, bytes_ext->max - 1);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return rc;
+}
+
+static int tasdev_XMA2_data_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(comp);
+ struct soc_bytes_ext *bytes_ext =
+ (struct soc_bytes_ext *) kcontrol->private_value;
+ unsigned char *dst = ucontrol->value.bytes.data;
+ unsigned int reg = TASDEVICE_XM_A2_REG;
+ int rc = -1;
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = calib_data_get(tas_priv, reg, dst, bytes_ext->max - 1);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return rc;
+}
+
+static int tasdev_nop_get(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int tas2563_digital_gain_get(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_dev = snd_soc_component_get_drvdata(codec);
+ unsigned int l = 0, r = mc->max;
+ unsigned int target, ar_mid, mid, ar_l, ar_r;
+ unsigned int reg = mc->reg;
+ unsigned char data[4];
+ int ret;
+
+ mutex_lock(&tas_dev->codec_lock);
+ /* Read the primary device */
+ ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4);
+ if (ret) {
+ dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__);
+ goto out;
+ }
+
+ target = get_unaligned_be32(&data[0]);
+
+ while (r > 1 + l) {
+ mid = (l + r) / 2;
+ ar_mid = get_unaligned_be32(tas2563_dvc_table[mid]);
+ if (target < ar_mid)
+ r = mid;
+ else
+ l = mid;
+ }
+
+ ar_l = get_unaligned_be32(tas2563_dvc_table[l]);
+ ar_r = get_unaligned_be32(tas2563_dvc_table[r]);
+
+ ucontrol->value.integer.value[0] =
+ abs(target - ar_l) <= abs(target - ar_r) ? l : r;
+out:
+ mutex_unlock(&tas_dev->codec_lock);
+ return 0;
+}
+
+static int tas2563_digital_gain_put(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_dev = snd_soc_component_get_drvdata(codec);
+ unsigned int reg = mc->reg;
+ unsigned int volrd, volwr;
+ int vol = ucontrol->value.integer.value[0];
+ int max = mc->max, i, ret = 1;
+ unsigned char data[4];
+
+ vol = clamp(vol, 0, max);
+ mutex_lock(&tas_dev->codec_lock);
+ /* Read the primary device */
+ ret = tasdevice_dev_bulk_read(tas_dev, 0, reg, data, 4);
+ if (ret) {
+ dev_err(tas_dev->dev, "%s, get AMP vol error\n", __func__);
+ goto out;
+ }
+
+ volrd = get_unaligned_be32(&data[0]);
+ volwr = get_unaligned_be32(tas2563_dvc_table[vol]);
+
+ if (volrd == volwr) {
+ ret = 0;
+ goto out;
+ }
+
+ for (i = 0; i < tas_dev->ndev; i++) {
+ ret = tasdevice_dev_bulk_write(tas_dev, i, reg,
+ (unsigned char *)tas2563_dvc_table[vol], 4);
+ if (ret)
+ dev_err(tas_dev->dev,
+ "%s, set digital vol error in device %d\n",
+ __func__, i);
+ }
+
+out:
+ mutex_unlock(&tas_dev->codec_lock);
+ return ret;
+}
+
+static const struct snd_kcontrol_new tasdevice_snd_controls[] = {
+ SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
+ tasdev_force_fwload_get, tasdev_force_fwload_put),
+};
+
+static const struct snd_kcontrol_new tasdevice_cali_controls[] = {
+ SOC_SINGLE_EXT("Calibration Stop", SND_SOC_NOPM, 0, 1, 0,
+ tasdev_nop_get, tasdev_calib_stop_put),
+ SND_SOC_BYTES_EXT("Amp TF Data", 5, tasdev_tf_data_get, NULL),
+ SND_SOC_BYTES_EXT("Amp RE Data", 5, tasdev_re_data_get, NULL),
+ SND_SOC_BYTES_EXT("Amp R0 Data", 5, tasdev_r0_data_get, NULL),
+ SND_SOC_BYTES_EXT("Amp XMA1 Data", 5, tasdev_XMA1_data_get, NULL),
+ SND_SOC_BYTES_EXT("Amp XMA2 Data", 5, tasdev_XMA2_data_get, NULL),
+};
+
static const struct snd_kcontrol_new tas2781_snd_controls[] = {
SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL,
1, 0, 20, 0, tas2781_amp_getvol,
@@ -146,8 +777,22 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = {
SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL,
0, 0, 200, 1, tas2781_digital_getvol,
tas2781_digital_putvol, dvc_tlv),
- SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
- tas2781_force_fwload_get, tas2781_force_fwload_put),
+};
+
+static const struct snd_kcontrol_new tas2781_cali_controls[] = {
+ SND_SOC_BYTES_EXT("Amp Latch Data", 2, tas2781_latch_reg_get, NULL),
+};
+
+static const struct snd_kcontrol_new tas2563_snd_controls[] = {
+ SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2563_DVC_LVL, 0,
+ 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0,
+ tas2563_digital_gain_get, tas2563_digital_gain_put,
+ tas2563_dvc_tlv),
+};
+
+static const struct snd_kcontrol_new tas2563_cali_controls[] = {
+ SOC_SINGLE_EXT("Calibration Start", SND_SOC_NOPM, 0, 1, 0,
+ tasdev_nop_get, tas2563_calib_start_put),
};
static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
@@ -167,6 +812,31 @@ static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
return ret;
}
+static int tasdevice_info_active_id(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = (int)tas_priv->ndev - 1;
+
+ return 0;
+}
+
+static int tasdevice_info_chip_id(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = TAS2563;
+ uinfo->value.integer.max = TAS2781;
+
+ return 0;
+}
+
static int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -223,6 +893,17 @@ static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
return 0;
}
+static int tasdevice_get_chip_id(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = tas_priv->chip_id;
+
+ return 0;
+}
+
static int tasdevice_create_control(struct tasdevice_priv *tas_priv)
{
struct snd_kcontrol_new *prof_ctrls;
@@ -316,15 +997,54 @@ static int tasdevice_configuration_put(
return ret;
}
-static int tasdevice_dsp_create_ctrls(
- struct tasdevice_priv *tas_priv)
+static int tasdevice_active_id_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
+ struct i2c_client *clt = (struct i2c_client *)tas_priv->client;
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ int i;
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ if (clt->addr == tasdev[i].dev_addr) {
+ ucontrol->value.integer.value[0] = i;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int tasdevice_active_id_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
+ struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
+ int nr_dev = ucontrol->value.integer.value[0];
+ int max = tas_priv->ndev - 1, rc;
+
+ nr_dev = clamp(nr_dev, 0, max);
+
+ mutex_lock(&tas_priv->codec_lock);
+ rc = tasdevice_chn_switch(tas_priv, nr_dev);
+ mutex_unlock(&tas_priv->codec_lock);
+
+ return rc;
+}
+
+static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv)
{
+ char *active_dev_name, *cali_name, *chip_id, *conf_name, *prog_name;
+ struct calidata *cali_data = &tas_priv->cali_data;
struct snd_kcontrol_new *dsp_ctrls;
- char *prog_name, *conf_name;
- int nr_controls = 2;
+ struct soc_bytes_ext *ext_cali_data;
+ int nr_controls = 5;
int mix_index = 0;
int ret;
+ if (tas_priv->chip_id == TAS2781)
+ nr_controls++;
/* Alloc kcontrol via devm_kzalloc, which don't manually
* free the kcontrol
*/
@@ -336,11 +1056,20 @@ static int tasdevice_dsp_create_ctrls(
}
/* Create a mixer item for selecting the active profile */
- prog_name = devm_kzalloc(tas_priv->dev,
+ active_dev_name = devm_kzalloc(tas_priv->dev,
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL);
+ cali_name = devm_kzalloc(tas_priv->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ GFP_KERNEL);
+ chip_id = devm_kzalloc(tas_priv->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ GFP_KERNEL);
+ conf_name = devm_kzalloc(tas_priv->dev,
SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL);
- conf_name = devm_kzalloc(tas_priv->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ prog_name = devm_kzalloc(tas_priv->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
GFP_KERNEL);
- if (!prog_name || !conf_name) {
+ ext_cali_data = devm_kzalloc(tas_priv->dev, sizeof(*ext_cali_data),
+ GFP_KERNEL);
+ if (!active_dev_name || !cali_name || !conf_name || !chip_id ||
+ !ext_cali_data || !prog_name) {
ret = -ENOMEM;
goto out;
}
@@ -363,6 +1092,68 @@ static int tasdevice_dsp_create_ctrls(
dsp_ctrls[mix_index].put = tasdevice_configuration_put;
mix_index++;
+ scnprintf(active_dev_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ "Activate Tasdevice Id");
+ dsp_ctrls[mix_index].name = active_dev_name;
+ dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ dsp_ctrls[mix_index].info = tasdevice_info_active_id;
+ dsp_ctrls[mix_index].get = tasdevice_active_id_get;
+ dsp_ctrls[mix_index].put = tasdevice_active_id_put;
+ mix_index++;
+
+ scnprintf(chip_id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ "Tasdevice Chip Id");
+ dsp_ctrls[mix_index].name = chip_id;
+ dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ dsp_ctrls[mix_index].info = tasdevice_info_chip_id;
+ dsp_ctrls[mix_index].get = tasdevice_get_chip_id;
+ mix_index++;
+
+ scnprintf(cali_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ "Speaker Calibrated Data");
+ ext_cali_data->max = tas_priv->ndev * CAL_DAT_SZ;
+ tas_priv->cali_data.total_sz = ext_cali_data->max;
+ tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev,
+ ext_cali_data->max, GFP_KERNEL);
+ dsp_ctrls[mix_index].name = cali_name;
+ dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ dsp_ctrls[mix_index].info = snd_soc_bytes_info_ext;
+ dsp_ctrls[mix_index].get = tasdev_cali_data_get;
+ dsp_ctrls[mix_index].put = tasdev_cali_data_put;
+ dsp_ctrls[mix_index].private_value = (unsigned long)ext_cali_data;
+ mix_index++;
+
+ cali_data->data = devm_kzalloc(tas_priv->dev, tas_priv->ndev *
+ (cali_data->reg_array_sz * 4 + 1), GFP_KERNEL);
+ if (!cali_data->data)
+ return -ENOMEM;
+
+ if (tas_priv->chip_id == TAS2781) {
+ struct soc_bytes_ext *ext_cali_start;
+ char *cali_start_name;
+
+ cali_start_name = devm_kzalloc(tas_priv->dev,
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL);
+ ext_cali_start = devm_kzalloc(tas_priv->dev,
+ sizeof(*ext_cali_start), GFP_KERNEL);
+ if (!cali_start_name || !ext_cali_start) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ scnprintf(cali_start_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
+ "Calibration Start");
+ ext_cali_data->max = tas_priv->ndev * 9;
+ dsp_ctrls[mix_index].name = cali_start_name;
+ dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ dsp_ctrls[mix_index].info = snd_soc_bytes_info_ext;
+ dsp_ctrls[mix_index].put = tas2781_calib_start_put;
+ dsp_ctrls[mix_index].get = tasdev_nop_get;
+ dsp_ctrls[mix_index].private_value =
+ (unsigned long)ext_cali_start;
+ mix_index++;
+ }
+
ret = snd_soc_add_component_controls(tas_priv->codec, dsp_ctrls,
nr_controls < mix_index ? nr_controls : mix_index);
@@ -370,6 +1161,54 @@ static int tasdevice_dsp_create_ctrls(
return ret;
}
+static int tasdevice_create_cali_ctrls(struct tasdevice_priv *tas_priv)
+{
+ struct calidata *cali_data = &tas_priv->cali_data;
+ struct snd_kcontrol_new *cali_ctrls;
+ unsigned int num_controls;
+ int rc;
+
+ rc = snd_soc_add_component_controls(tas_priv->codec,
+ tasdevice_cali_controls, ARRAY_SIZE(tasdevice_cali_controls));
+ if (rc < 0) {
+ dev_err(tas_priv->dev, "%s: Add cali control err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+
+ if (tas_priv->chip_id == TAS2781) {
+ cali_ctrls = (struct snd_kcontrol_new *)tas2781_cali_controls;
+ num_controls = ARRAY_SIZE(tas2781_cali_controls);
+ cali_data->reg_array = (unsigned int *)tas2781_cali_data_reg;
+ cali_data->reg_array_sz = ARRAY_SIZE(tas2781_cali_data_reg);
+ } else {
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ int i;
+
+ cali_ctrls = (struct snd_kcontrol_new *)tas2563_cali_controls;
+ num_controls = ARRAY_SIZE(tas2563_cali_controls);
+ cali_data->reg_array = (unsigned int *)tas2563_cali_data_reg;
+ cali_data->reg_array_sz = sizeof(tas2563_cali_data_reg);
+ for (i = 0; i < tas_priv->ndev; i++) {
+ tasdev[i].cali_data_restore =
+ kmemdup(tas2563_cali_start_reg,
+ sizeof(tas2563_cali_start_reg), GFP_KERNEL);
+ if (!tasdev[i].cali_data_restore)
+ return -ENOMEM;
+ }
+ }
+
+ rc = snd_soc_add_component_controls(tas_priv->codec, cali_ctrls,
+ num_controls);
+ if (rc < 0) {
+ dev_err(tas_priv->dev, "%s: Add control err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+
+ return rc;
+}
+
static void tasdevice_fw_ready(const struct firmware *fmw,
void *context)
{
@@ -380,23 +1219,36 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
mutex_lock(&tas_priv->codec_lock);
ret = tasdevice_rca_parser(tas_priv, fmw);
- if (ret)
+ if (ret) {
+ tasdevice_config_info_remove(tas_priv);
goto out;
+ }
tasdevice_create_control(tas_priv);
tasdevice_dsp_remove(tas_priv);
tasdevice_calbin_remove(tas_priv);
- tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
+ tas_priv->fw_state = TASDEVICE_RCA_FW_OK;
scnprintf(tas_priv->coef_binaryname, 64, "%s_coef.bin",
tas_priv->dev_name);
+
ret = tasdevice_dsp_parser(tas_priv);
if (ret) {
dev_err(tas_priv->dev, "dspfw load %s error\n",
tas_priv->coef_binaryname);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
goto out;
}
- tasdevice_dsp_create_ctrls(tas_priv);
+
+ ret = tasdevice_dsp_create_ctrls(tas_priv);
+ if (ret) {
+ dev_err(tas_priv->dev, "dsp controls error\n");
+ goto out;
+ }
+
+ ret = tasdevice_create_cali_ctrls(tas_priv);
+ if (ret) {
+ dev_err(tas_priv->dev, "cali controls error\n");
+ goto out;
+ }
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
@@ -417,9 +1269,8 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
tasdevice_prmg_load(tas_priv, 0);
tas_priv->cur_prog = 0;
out:
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
- /*If DSP FW fail, kcontrol won't be created */
- tasdevice_config_info_remove(tas_priv);
+ if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) {
+ /*If DSP FW fail, DSP kcontrol won't be created */
tasdevice_dsp_remove(tas_priv);
}
mutex_unlock(&tas_priv->codec_lock);
@@ -466,14 +1317,14 @@ static int tasdevice_startup(struct snd_pcm_substream *substream,
{
struct snd_soc_component *codec = dai->component;
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
- int ret = 0;
- if (tas_priv->fw_state != TASDEVICE_DSP_FW_ALL_OK) {
- dev_err(tas_priv->dev, "DSP bin file not loaded\n");
- ret = -EINVAL;
+ if (!(tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK ||
+ tas_priv->fw_state == TASDEVICE_RCA_FW_OK)) {
+ dev_err(tas_priv->dev, "Bin file not loaded\n");
+ return -EINVAL;
}
- return ret;
+ return 0;
}
static int tasdevice_hw_params(struct snd_pcm_substream *substream,
@@ -541,7 +1392,7 @@ static const struct snd_soc_dai_ops tasdevice_dai_ops = {
static struct snd_soc_dai_driver tasdevice_dai_driver[] = {
{
- .name = "tas2781_codec",
+ .name = "tasdev_codec",
.id = 0,
.playback = {
.stream_name = "Playback",
@@ -565,13 +1416,41 @@ static struct snd_soc_dai_driver tasdevice_dai_driver[] = {
static int tasdevice_codec_probe(struct snd_soc_component *codec)
{
struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
+ int rc;
+
+ if (tas_priv->chip_id == TAS2781) {
+ rc = snd_soc_add_component_controls(codec,
+ tas2781_snd_controls,
+ ARRAY_SIZE(tas2781_snd_controls));
+ if (rc < 0) {
+ dev_err(tas_priv->dev, "%s: Add control err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+ } else {
+ rc = snd_soc_add_component_controls(codec,
+ tas2563_snd_controls,
+ ARRAY_SIZE(tas2563_snd_controls));
+ if (rc < 0) {
+ dev_err(tas_priv->dev, "%s: Add control err rc = %d",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ rc = tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready);
- return tascodec_init(tas_priv, codec, THIS_MODULE, tasdevice_fw_ready);
+ return rc;
}
static void tasdevice_deinit(void *context)
{
struct tasdevice_priv *tas_priv = (struct tasdevice_priv *) context;
+ struct tasdevice *tasdev = tas_priv->tasdevice;
+ int i;
+
+ for (i = 0; i < tas_priv->ndev; i++)
+ kfree(tasdev[i].cali_data_restore);
tasdevice_config_info_remove(tas_priv);
tasdevice_dsp_remove(tas_priv);
@@ -591,8 +1470,8 @@ static const struct snd_soc_component_driver
soc_codec_driver_tasdevice = {
.probe = tasdevice_codec_probe,
.remove = tasdevice_codec_remove,
- .controls = tas2781_snd_controls,
- .num_controls = ARRAY_SIZE(tas2781_snd_controls),
+ .controls = tasdevice_snd_controls,
+ .num_controls = ARRAY_SIZE(tasdevice_snd_controls),
.dapm_widgets = tasdevice_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tasdevice_dapm_widgets),
.dapm_routes = tasdevice_audio_map,
--
2.34.1
5
6

08 Aug '24
Add initial support for the PantherLake platform, and initial ACPI
configurations.
This patchset depends on the first patch of "[PATCH 0/3] ALSA/PCI: add
PantherLake audio support"
Bard Liao (2):
ASoC: Intel: soc-acpi-intel-ptl-match: add rt711-sdca table
ASoC: Intel: soc-acpi-intel-ptl-match: Add rt722 support
Fred Oh (1):
ASoC: SOF: Intel: add PTL specific power control register
Pierre-Louis Bossart (2):
ASoC: SOF: Intel: add initial support for PTL
ASoC: Intel: soc-acpi: add PTL match tables
include/sound/soc-acpi-intel-match.h | 2 +
sound/soc/intel/common/Makefile | 1 +
.../intel/common/soc-acpi-intel-ptl-match.c | 121 ++++++++++++++++++
sound/soc/sof/intel/Kconfig | 17 +++
sound/soc/sof/intel/Makefile | 2 +
sound/soc/sof/intel/hda-dsp.c | 1 +
sound/soc/sof/intel/hda.h | 1 +
sound/soc/sof/intel/lnl.c | 27 ++++
sound/soc/sof/intel/mtl.c | 16 ++-
sound/soc/sof/intel/mtl.h | 2 +
sound/soc/sof/intel/pci-ptl.c | 77 +++++++++++
sound/soc/sof/intel/shim.h | 1 +
12 files changed, 266 insertions(+), 2 deletions(-)
create mode 100644 sound/soc/intel/common/soc-acpi-intel-ptl-match.c
create mode 100644 sound/soc/sof/intel/pci-ptl.c
--
2.43.0
2
9

Re: [PATCH v11 07/10] mtd: spi-nor: Add stacked memories support in spi-nor
by Michael Walle 07 Aug '24
by Michael Walle 07 Aug '24
07 Aug '24
Hi,
> Based on the inputs/suggestions from Tudor, i am planning to add a new
> layer between the SPI-NOR and MTD layers to support stacked and parallel
> configurations. This new layer will be part of the spi-nor and located in
> mtd/spi-nor/
Will AMD submit to maintain this layer? What happens if the
maintainer will leave AMD? TBH, personally, I don't like to
maintain such a niche feature.
I'd really like to see some use cases and performance reports for
this, like actual boards (and no evaluation boards don't count). Why
wouldn't someone just use an octal flash?
And as already mentioned there is also mtdcat, which seems to
duplicate some features?
-michael
5
13
Bespoke trigger support was added when Linux v3.5 by this patch.
commit 07bf84aaf736781a283b1bd36eaa911453b14574
("ASoC: dpcm: Add bespoke trigger()")
test-component driver is using it, but this is because it indicates used
function for debug/trace purpose. Except test-component driver, bespoke
trigger has never been used over 10 years in upstream.
We can re-support it if needed in the future, but let's remove it for now,
because it just noise in upstream.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx(a)renesas.com>
---
include/sound/soc-dai.h | 5 +---
include/sound/soc-dpcm.h | 1 -
sound/soc/generic/test-component.c | 9 ------
sound/soc/soc-dai.c | 20 -------------
sound/soc/soc-pcm.c | 47 +++---------------------------
5 files changed, 5 insertions(+), 77 deletions(-)
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index bbb72ad4c9518..ab4e109fe71d2 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -240,8 +240,6 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd);
int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream);
int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
int rollback);
-int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
- int cmd);
void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
@@ -345,8 +343,7 @@ struct snd_soc_dai_ops {
*/
int (*trigger)(struct snd_pcm_substream *, int,
struct snd_soc_dai *);
- int (*bespoke_trigger)(struct snd_pcm_substream *, int,
- struct snd_soc_dai *);
+
/*
* For hardware based FIFO caused delay reporting.
* Optional.
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
index ebd24753dd000..773f2db8c31c8 100644
--- a/include/sound/soc-dpcm.h
+++ b/include/sound/soc-dpcm.h
@@ -58,7 +58,6 @@ enum snd_soc_dpcm_state {
enum snd_soc_dpcm_trigger {
SND_SOC_DPCM_TRIGGER_PRE = 0,
SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_BESPOKE,
};
/*
diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c
index e9e5e235a8a65..df2487b700cca 100644
--- a/sound/soc/generic/test-component.c
+++ b/sound/soc/generic/test-component.c
@@ -181,14 +181,6 @@ static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct
return 0;
}
-static int test_dai_bespoke_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai)
-{
- mile_stone(dai);
-
- return 0;
-}
-
static const u64 test_dai_formats =
/*
* Select below from Sound Card, not auto
@@ -228,7 +220,6 @@ static const struct snd_soc_dai_ops test_verbose_ops = {
.hw_params = test_dai_hw_params,
.hw_free = test_dai_hw_free,
.trigger = test_dai_trigger,
- .bespoke_trigger = test_dai_bespoke_trigger,
.auto_selectable_formats = &test_dai_formats,
.num_auto_selectable_formats = 1,
};
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index 9e47053419c16..302ca753a1f35 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -685,26 +685,6 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
return ret;
}
-int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *dai;
- int i, ret;
-
- for_each_rtd_dais(rtd, i, dai) {
- if (dai->driver->ops &&
- dai->driver->ops->bespoke_trigger) {
- ret = dai->driver->ops->bespoke_trigger(substream,
- cmd, dai);
- if (ret < 0)
- return soc_dai_ret(dai, ret);
- }
- }
-
- return 0;
-}
-
void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
snd_pcm_sframes_t *cpu_delay,
snd_pcm_sframes_t *codec_delay)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 4571785736f76..5646525ad7924 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2371,14 +2371,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
break;
}
break;
- case SND_SOC_DPCM_TRIGGER_BESPOKE:
- /* bespoke trigger() - handles both FE and BEs */
-
- dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n",
- fe->dai_link->name, cmd);
-
- ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd);
- break;
default:
dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd,
fe->dai_link->name);
@@ -2508,26 +2500,12 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
{
- struct snd_pcm_substream *substream =
- snd_soc_dpcm_get_substream(fe, stream);
- enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
int err;
dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n",
stream ? "capture" : "playback", fe->dai_link->name);
- if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
- /* call bespoke trigger - FE takes care of all BE triggers */
- dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n",
- fe->dai_link->name);
-
- err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
- } else {
- dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n",
- fe->dai_link->name);
-
- err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
- }
+ err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
dpcm_be_dai_hw_free(fe, stream);
@@ -2541,10 +2519,7 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
{
- struct snd_pcm_substream *substream =
- snd_soc_dpcm_get_substream(fe, stream);
struct snd_soc_dpcm *dpcm;
- enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
int ret = 0;
dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
@@ -2588,23 +2563,9 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
return 0;
- if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
- /* call trigger on the frontend - FE takes care of all BE triggers */
- dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n",
- fe->dai_link->name);
-
- ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
- if (ret < 0)
- goto hw_free;
- } else {
- dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n",
- fe->dai_link->name);
-
- ret = dpcm_be_dai_trigger(fe, stream,
- SNDRV_PCM_TRIGGER_START);
- if (ret < 0)
- goto hw_free;
- }
+ ret = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_START);
+ if (ret < 0)
+ goto hw_free;
return 0;
--
2.43.0
2
3
The aim of this serie is to add scaling support to STM32 DFSDM
peripheral in the analog context.
The DFSDM currently operates as a consumer of IIO channels
provided by a generic SD modulator. As previously discussed in RFC [1],
this topology is not suitable for implementing scaling.
This series brings the integration of the DFSDM driver with the new
IIO backend framework [2], enabling the DFSDM IIO device to offer
scaling feature based on reference voltage data obtained from the
IIO SD modulator backend. This generic SD modulator backend takes the
place of the former SD modulator, used with legacy implementation.
The DFSDM driver has been updated to adopt the generic ADC channel
binding [3]. The reasons for this include:
- Reducing the use of proprietary properties
- Simplifying the coexistence of legacy and new backend bindings
- Prepare the support of the MDF peripheral on STM32MP25 SoC
Backward compatibility is maintained through legacy support.
This series extends the backend framework with the following APIs:
- iio_backend_read_raw:
This API is intented to retrieve channel attributes from the
backend. It is based on IIO framework read_raw API.
- iio_backend_read_scale / iio_backend_read_offset
Dedicated APIs to read scale and offset channel values.
- iio_backend_disable / iio_backend_enable:
backend enable/disable to be used for PM management
- devm_iio_backend_fwnode_get
Intended for parsing DT subnodes to allow generic channel binding
support, as generic channel DT nodes are not populated as devices.
[1]: https://lore.kernel.org/lkml/20200204101008.11411-1-olivier.moysan@st.com/
[2]: https://lore.kernel.org/all/20240206-iio-backend-v9-0-df66d159c000@analog.c…
[3]: devicetree/bindings/iio/adc/adc.yaml
Changes in v2:
- Update enable/disable backend API
- Rename devm_iio_backend_subnode_get(), as devm_iio_backend_fwnode_get()
- Update iio_backend_read_raw() prototype to fully match IIO framework
read_raw callback prototype.
- Change st,adc-channel-type property name and type in DFSDM binding
- Remove sd-backend and rename ads1201 compatibles in SD binding
Changes in v3:
- Add iio_backend_read_scale and iio_backend_read_offset
- Remove sd-backend compatible. Adapt existing sd modulator driver and
binding to support backend topology.
- Misc corrections in DFSDM binding & minor changes in DFSDM driver
Changes in v4:
- Remove allOf and rework examples in SD modulator binding
- Wrap lines to 80 characters in IIO code
Changes in v5:
- Move iio_backend_read_scale and iio_backend_read_offset to inline
and update prototype
- Fix channel number & remove legacy binding example in DFSDM binding
- Rearrange DFSDM patches to fix build issue in serie
- Split SD modulator binding patch.
Move reference voltage change in a separate patch
Changes in v6:
- Minor cleanup in DFSDM binding
- Fix vref-supply dependency condition in SD modulator binding
Olivier Moysan (9):
iio: add read scale and offset services to iio backend framework
iio: add enable and disable services to iio backend framework
iio: add child nodes support in iio backend framework
dt-bindings: iio: dfsdm: move to backend framework
dt-bindings: iio: add backend support to sd modulator
dt-bindings: iio: add vref support to sd modulator
iio: adc: stm32-dfsdm: adopt generic channels bindings
iio: add iio backend support to sd modulator
iio: adc: stm32-dfsdm: add scaling support to dfsdm
.../iio/adc/sigma-delta-modulator.yaml | 25 +-
.../bindings/iio/adc/st,stm32-dfsdm-adc.yaml | 122 +++++++-
drivers/iio/adc/Kconfig | 2 +
drivers/iio/adc/sd_adc_modulator.c | 92 +++++-
drivers/iio/adc/stm32-dfsdm-adc.c | 293 +++++++++++++++---
drivers/iio/industrialio-backend.c | 101 +++++-
include/linux/iio/backend.h | 29 +-
7 files changed, 592 insertions(+), 72 deletions(-)
base-commit: bf829a98bc4bb9076a2fd70f4a69ea7e281863fa
--
2.25.1
2
3

06 Aug '24
Raw spinlock is needed here, because with enabled PREEMPT_RT,
spinlock_t become preemptible, but this regmap lock could be
acquired in IRQ handler. Found by lockdep:
[ ] =============================
[ ] [ BUG: Invalid wait context ]
[ ] 6.9.9-sdkernel #1 Tainted: G O
[ ] -----------------------------
[ ] aplay/413 is trying to lock:
[ ] ffff000003930018 (axg_fifo:356:(&axg_fifo_regmap_cfg)->lock){....}-{3:3},c
[ ] other info that might help us debug this:
[ ] context-{2:2}
[ ] no locks held by aplay/413.
[ ] stack backtrace:
[ ] CPU: 0 PID: 413 Comm: aplay Tainted: G O 6.9.9-kernel #1
[ ] Hardware name: SberDevices SberBoom Mini (DT)
[ ] Call trace:
[ ] dump_backtrace+0x98/0xf0
[ ] show_stack+0x18/0x24
[ ] dump_stack_lvl+0x90/0xd0
[ ] dump_stack+0x18/0x24
[ ] __lock_acquire+0x9dc/0x1f10
[ ] lock_acquire.part.0+0xe8/0x228
[ ] lock_acquire+0x68/0x84
[ ] _raw_spin_lock_irqsave+0x60/0x88
[ ] regmap_lock_spinlock+0x18/0x2c
[ ] regmap_read+0x3c/0x78
[ ] axg_fifo_pcm_irq_block+0x4c/0xc8
[ ] __handle_irq_event_percpu+0xa4/0x2f8
[ ] handle_irq_event+0x4c/0xbc
[ ] handle_fasteoi_irq+0xa4/0x23c
[ ] generic_handle_domain_irq+0x2c/0x44
[ ] gic_handle_irq+0x40/0xc4
[ ] call_on_irq_stack+0x24/0x4c
[ ] do_interrupt_handler+0x80/0x84
[ ] el0_interrupt+0x5c/0x124
[ ] __el0_irq_handler_common+0x18/0x24
[ ] el0t_32_irq_handler+0x10/0x1c
[ ] el0t_32_irq+0x194/0x198
Signed-off-by: Arseniy Krasnov <avkrasnov(a)salutedevices.com>
---
sound/soc/meson/axg-fifo.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c
index ecb3eb7a9723d..a22298f74b35a 100644
--- a/sound/soc/meson/axg-fifo.c
+++ b/sound/soc/meson/axg-fifo.c
@@ -328,6 +328,7 @@ static const struct regmap_config axg_fifo_regmap_cfg = {
.val_bits = 32,
.reg_stride = 4,
.max_register = FIFO_CTRL2,
+ .use_raw_spinlock = true,
};
int axg_fifo_probe(struct platform_device *pdev)
--
2.30.1
4
12
Recent changes that started checking the codec version broke audio on
the Lenovo ThinkPad X13s:
wsa_macro 3240000.codec: Unsupported Codec version (0)
wsa_macro 3240000.codec: probe with driver wsa_macro failed with error -22
rx_macro 3200000.rxmacro: Unsupported Codec version (0)
rx_macro 3200000.rxmacro: probe with driver rx_macro failed with error -22
Add the missing codec version to the lookup table so that the codec
drivers probe successfully.
Note that I'm just assuming that this is a 2.0 codec based on the fact
that this device uses the older register layout.
Fixes: 378918d59181 ("ASoC: codecs: lpass-macro: add helpers to get codec version")
Fixes: dbacef05898d ("ASoC: codec: lpass-rx-macro: prepare driver to accomdate new codec versions")
Fixes: 727de4fbc546 ("ASoC: codecs: lpass-wsa-macro: Correct support for newer v2.5 version")
Signed-off-by: Johan Hovold <johan+linaro(a)kernel.org>
---
Cc: regressions(a)lists.linux.dev
#regzbot introduced: 378918d59181
sound/soc/codecs/lpass-va-macro.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index b852cc7ffad9..a62ccd09bacd 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -1472,6 +1472,8 @@ static void va_macro_set_lpass_codec_version(struct va_macro *va)
if ((core_id_0 == 0x01) && (core_id_1 == 0x0F))
version = LPASS_CODEC_VERSION_2_0;
+ if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && core_id_2 == 0x01)
+ version = LPASS_CODEC_VERSION_2_0;
if ((core_id_0 == 0x02) && (core_id_1 == 0x0E))
version = LPASS_CODEC_VERSION_2_1;
if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x50 || core_id_2 == 0x51))
--
2.44.2
3
2