* [RFC PATCH 0/1] ASoC: codecs: rk3308: add support for codec revision B
@ 2026-09-18 12:57 Mizuno Miotsuki
2026-09-18 12:57 ` [RFC PATCH 1/1] " Mizuno Miotsuki
2026-09-18 12:58 ` [RFC PATCH 0/1] " Mark Brown
0 siblings, 2 replies; 3+ messages in thread
From: Mizuno Miotsuki @ 2026-09-18 12:57 UTC (permalink / raw)
To: Luca Ceresoli, Mark Brown
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Heiko Stuebner,
linux-sound, linux-kernel, linux-arm-kernel, linux-rockchip
Hi,
The current RK3308 internal codec driver detects codec revision B
(chip ID 0x3308) but explicitly rejects it. The initial 2022 driver
supported revision B with a monolithic power sequence; the later DAPM
rewrite left it unsupported.
This RFC restores the revision-specific DAC output VCM/current sequence
as a playback-only DAPM supply shared by HPOUT and LINEOUT. Per-channel
LINEOUT events override the shared DC baseline only while LINEOUT is
enabled. It does not restore the old codec-global power-on/off
functions, and capture-only streams do not touch DAC_ANA_CON14/15.
The original 2022 upstream v1 selected LINEOUT_FROM_INTERNAL for
revision B even for HPOUT-only playback. A newer Rockchip 6.1
downstream driver instead keeps CON15 at DC_FROM_INTERNAL for
HPOUT-only and selects LINEOUT_FROM_INTERNAL only for LINEOUT or
LINEOUT+HPOUT. This RFC follows the newer behaviour. Is that a hardware
sequencing fix that should be preserved?
On a DFRobot UNIHIKER M10 V1.2, revision-B probe, the board MICBIAS1
route, capture/playback PCM operation, capture isolation from CON14/15,
and the LINEOUT DAPM/register states were verified with the preceding
clean candidate. Physical onboard microphone capture was also
confirmed. A short transient at capture startup is also present with
the Rockchip vendor driver unless a longer wait is added, so it is not
treated as a regression and this RFC does not add a generic 250 ms mute
delay.
The shared-output revision is compile-tested but was not deployed.
Physical LINEOUT and HPOUT audio remain untested because suitable
hardware endpoints were unavailable. In particular, the HPOUT-only
CON15=0x22 choice still needs maintainer guidance or real-hardware
confirmation.
The M10 microphone route, its overly broad output topology, microphone PGA
controls, and capture-startup transient are deliberately kept outside this
codec RFC.
Regards,
Mizuno Miotsuki
Mizuno Miotsuki (1):
ASoC: codecs: rk3308: add support for codec revision B
sound/soc/codecs/rk3308_codec.c | 102 +++++++++++++++++++++++++++++++-
1 file changed, 99 insertions(+), 3 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/1] ASoC: codecs: rk3308: add support for codec revision B
2026-09-18 12:57 [RFC PATCH 0/1] ASoC: codecs: rk3308: add support for codec revision B Mizuno Miotsuki
@ 2026-09-18 12:57 ` Mizuno Miotsuki
2026-09-18 12:58 ` [RFC PATCH 0/1] " Mark Brown
1 sibling, 0 replies; 3+ messages in thread
From: Mizuno Miotsuki @ 2026-09-18 12:57 UTC (permalink / raw)
To: Luca Ceresoli, Mark Brown
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Heiko Stuebner,
linux-sound, linux-kernel, linux-arm-kernel, linux-rockchip
The RK3308 codec driver detects codec revision B (chip ID 0x3308),
but currently rejects it during probe. Revision B needs an additional
DAC output VCM charge and depop sequence using DAC_ANA_CON14 and
DAC_ANA_CON15.
Model the shared revision-B DAC output VCM as a playback-only DAPM
supply used by both HPOUT and LINEOUT. Charge the reference while both
CON15 channels are connected to VCM, then establish DC_FROM_INTERNAL as
the playback baseline. LINEOUT events switch each enabled channel to
LINEOUT_FROM_INTERNAL after its output driver is enabled and return it
to DC_FROM_INTERNAL after disable. When the last analogue output powers
down, return both channels to VCM and disable the shared reference.
All new register writes are conditional on codec revision B.
Capture-only streams do not traverse the new supply, so they do not
touch DAC_ANA_CON14 or DAC_ANA_CON15. Revisions A and C gain no
additional MMIO writes.
For HPOUT-only playback, keep CON15 at DC_FROM_INTERNAL, matching the
newer Rockchip 6.1 downstream driver. Physical HPOUT validation is still
needed.
Tested on a DFRobot UNIHIKER M10 V1.2 with codec revision B.
Revision-B probe, the board MICBIAS1 route, and physical onboard
microphone capture passed. A short capture-startup transient is also
present with the Rockchip vendor driver unless a longer wait is added,
so it is not treated as a regression and no generic 250 ms mute delay is
added here. Capture-only isolation from DAC_ANA_CON14/15 and playback
PCM, DAPM, and LINEOUT register endpoints were verified with the
preceding clean LINEOUT-only candidate. The shared-output revision is
compile-tested only. Physical LINEOUT and HPOUT audio were not tested
because suitable hardware endpoints were unavailable.
Signed-off-by: Mizuno Miotsuki <founder@crepuse.com>
---
sound/soc/codecs/rk3308_codec.c | 102 +++++++++++++++++++++++++++++++-
1 file changed, 99 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c
index 60befe9d37f0..8514d94d4051 100644
--- a/sound/soc/codecs/rk3308_codec.c
+++ b/sound/soc/codecs/rk3308_codec.c
@@ -192,6 +192,90 @@ static int rk3308_codec_pop_sound_set(struct snd_soc_dapm_widget *w,
return 0;
}
+static int rk3308_codec_dac_output_vcm_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
+ unsigned int val;
+
+ if (rk3308->codec_ver != ACODEC_VERSION_B)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Keep the DAC outputs at VCM while their reference is charged. */
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
+ RK3308_DAC_L_SEL_DC_FROM_VCM |
+ RK3308_DAC_R_SEL_DC_FROM_VCM);
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
+ RK3308_DAC_CURRENT_CHARGE_MSK, 1);
+ regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
+ RK3308_DAC_VCM_LINEOUT_EN);
+ for (val = 1; val <= 0xf; val++) {
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
+ RK3308_DAC_CURRENT_CHARGE_MSK, val);
+ usleep_range(200, 400);
+ }
+ msleep(20);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
+ RK3308_DAC_L_SEL_DC_FROM_INTERNAL |
+ RK3308_DAC_R_SEL_DC_FROM_INTERNAL);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
+ RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
+ RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
+ RK3308_DAC_L_SEL_DC_FROM_VCM |
+ RK3308_DAC_R_SEL_DC_FROM_VCM);
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
+ RK3308_DAC_CURRENT_CHARGE_MSK, 1);
+ regmap_clear_bits(rk3308->regmap, RK3308_DAC_ANA_CON14,
+ RK3308_DAC_VCM_LINEOUT_EN);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int rk3308_codec_lineout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
+ unsigned int mask = RK3308_DAC_LINEOUT_POP_SOUND_L_MSK << w->shift;
+ unsigned int val;
+
+ if (rk3308->codec_ver != ACODEC_VERSION_B)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ val = RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL << w->shift;
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ val = RK3308_DAC_L_SEL_DC_FROM_INTERNAL << w->shift;
+ break;
+ default:
+ return 0;
+ }
+
+ regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, mask, val);
+ usleep_range(20, 40);
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget rk3308_codec_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MIC1"),
SND_SOC_DAPM_INPUT("MIC2"),
@@ -322,6 +406,10 @@ static const struct snd_soc_dapm_widget rk3308_codec_dapm_widgets[] = {
SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_R", SND_SOC_NOPM, 4, 0, NULL, 0,
rk3308_codec_pop_sound_set,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("DAC_OUTPUT_VCM", SND_SOC_NOPM, 0, 0,
+ rk3308_codec_dac_output_vcm_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUT_DRV("L_HPOUT_EN", RK3308_DAC_ANA_CON03, 1, 0, NULL, 0),
SND_SOC_DAPM_OUT_DRV("R_HPOUT_EN", RK3308_DAC_ANA_CON03, 5, 0, NULL, 0),
SND_SOC_DAPM_OUT_DRV("L_HPOUT_WORK", RK3308_DAC_ANA_CON03, 2, 0, NULL, 0),
@@ -329,8 +417,12 @@ static const struct snd_soc_dapm_widget rk3308_codec_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("HPOUT_L"),
SND_SOC_DAPM_OUTPUT("HPOUT_R"),
- SND_SOC_DAPM_OUT_DRV("L_LINEOUT_EN", RK3308_DAC_ANA_CON04, 0, 0, NULL, 0),
- SND_SOC_DAPM_OUT_DRV("R_LINEOUT_EN", RK3308_DAC_ANA_CON04, 4, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV_E("L_LINEOUT_EN", RK3308_DAC_ANA_CON04, 0, 0,
+ NULL, 0, rk3308_codec_lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUT_DRV_E("R_LINEOUT_EN", RK3308_DAC_ANA_CON04, 4, 0,
+ NULL, 0, rk3308_codec_lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_OUTPUT("LINEOUT_L"),
SND_SOC_DAPM_OUTPUT("LINEOUT_R"),
};
@@ -466,6 +558,8 @@ static const struct snd_soc_dapm_route rk3308_codec_dapm_routes[] = {
{ "HPOUT_R", NULL, "DAC_BUF_REF_R" },
{ "L_HPOUT_EN", NULL, "DAC_L_HPMIX_SEL" },
{ "R_HPOUT_EN", NULL, "DAC_R_HPMIX_SEL" },
+ { "L_HPOUT_EN", NULL, "DAC_OUTPUT_VCM" },
+ { "R_HPOUT_EN", NULL, "DAC_OUTPUT_VCM" },
{ "L_HPOUT_WORK", NULL, "L_HPOUT_EN" },
{ "R_HPOUT_WORK", NULL, "R_HPOUT_EN" },
{ "HPOUT_POP_SOUND_L", NULL, "L_HPOUT_WORK" },
@@ -475,6 +569,8 @@ static const struct snd_soc_dapm_route rk3308_codec_dapm_routes[] = {
{ "L_LINEOUT_EN", NULL, "DAC_L_HPMIX_SEL" },
{ "R_LINEOUT_EN", NULL, "DAC_R_HPMIX_SEL" },
+ { "L_LINEOUT_EN", NULL, "DAC_OUTPUT_VCM" },
+ { "R_LINEOUT_EN", NULL, "DAC_OUTPUT_VCM" },
{ "LINEOUT_L", NULL, "L_LINEOUT_EN" },
{ "LINEOUT_R", NULL, "R_LINEOUT_EN" },
};
@@ -855,7 +951,7 @@ static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308)
break;
case 0x3308:
rk3308->codec_ver = ACODEC_VERSION_B;
- return dev_err_probe(rk3308->dev, -EINVAL, "Chip version B not supported\n");
+ break;
case 0x3308c:
rk3308->codec_ver = ACODEC_VERSION_C;
break;
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC PATCH 0/1] ASoC: codecs: rk3308: add support for codec revision B
2026-09-18 12:57 [RFC PATCH 0/1] ASoC: codecs: rk3308: add support for codec revision B Mizuno Miotsuki
2026-09-18 12:57 ` [RFC PATCH 1/1] " Mizuno Miotsuki
@ 2026-09-18 12:58 ` Mark Brown
1 sibling, 0 replies; 3+ messages in thread
From: Mark Brown @ 2026-09-18 12:58 UTC (permalink / raw)
To: Mizuno Miotsuki
Cc: Luca Ceresoli, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Heiko Stuebner, linux-sound, linux-kernel, linux-arm-kernel,
linux-rockchip
[-- Attachment #1: Type: text/plain, Size: 596 bytes --]
On Fri, Sep 18, 2026 at 12:57:18PM +0000, Mizuno Miotsuki wrote:
> Hi,
>
> The current RK3308 internal codec driver detects codec revision B
> (chip ID 0x3308) but explicitly rejects it. The initial 2022 driver
> supported revision B with a monolithic power sequence; the later DAPM
Please don't send cover letters for single patches, if there is anything
that needs saying put it in the changelog of the patch or after the ---
if it's administrative stuff. This reduces mail volume and ensures that
any important information is recorded in the changelog rather than being
lost.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-18 12:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-18 12:57 [RFC PATCH 0/1] ASoC: codecs: rk3308: add support for codec revision B Mizuno Miotsuki
2026-09-18 12:57 ` [RFC PATCH 1/1] " Mizuno Miotsuki
2026-09-18 12:58 ` [RFC PATCH 0/1] " Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®