rk27xx codec: mix in only the tuner's line, keep the DAC

audiohw_set_monitor() switched the output mixer from the DAC to both line
bypasses: voice and beeps went silent while the radio played, and a line
nobody listened to was mixed in, with its noise. Both line inputs were
also powered from start-up on.

- the target names the line its tuner is on, RK27XX_CODEC_FM_LINE (1 or
  2); both are used where it does not say
- monitoring adds that line's bypass to the DAC instead of replacing it
- the line inputs stay in standby until monitored, and go back after

Only rk27generic uses the internal codec - the other rk27xx targets
have external DACs or codecs.

Tested on rk27generic: the radio plays through the monitored line, key
clicks stay audible over it, and playback is unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I177fdf605e4d997159898c868b2186c9584eb19a
This commit is contained in:
Marcin Bukat 2026-09-30 07:57:50 +02:00
parent 88f3d21890
commit 19caf27567

View file

@ -39,8 +39,28 @@ static int codec_read(uint8_t reg, uint8_t *val)
}
#endif
/* The line input the FM tuner is wired to: RK27XX_CODEC_FM_LINE, 1 or 2,
* from the target config; both when the target does not say. Only the
* tuner's line is bypassed to the output mixer and powered, and only while
* it is being listened to. */
#if defined(RK27XX_CODEC_FM_LINE) && RK27XX_CODEC_FM_LINE == 1
#define FM_BYPASS BYPASS1
#define FM_IN_SB SB_IN1
#elif defined(RK27XX_CODEC_FM_LINE) && RK27XX_CODEC_FM_LINE == 2
#define FM_BYPASS BYPASS2
#define FM_IN_SB SB_IN2
#else
#define FM_BYPASS (BYPASS1|BYPASS2)
#define FM_IN_SB (SB_IN1|SB_IN2)
#endif
/* what feeds the output mixer: the DAC, and the tuner's line while the
* radio plays - the DAC stays in the mix, for voice and beeps */
static uint8_t cr1_sel = DACSEL;
/* power: the line inputs in standby unless monitored */
static uint8_t pmr1 = SB_ADC|SB_MIC|SB_IND|SB_IN1|SB_IN2;
static void audiohw_mute(bool mute)
{
if (mute)
@ -95,7 +115,7 @@ void audiohw_postinit(void)
udelay(1000);
/* power up output stage */
codec_write(PMR1, SB_ADC|SB_MIC|SB_IND);
codec_write(PMR1, pmr1);
sleep(HZ/10);
GPIO_PDDR |= (1<<7); /* PD7 high */
@ -152,6 +172,20 @@ void audiohw_set_volume(int vol_l, int vol_r)
void audiohw_set_monitor(bool enable)
{
cr1_sel = enable ? BYPASS1|BYPASS2 : DACSEL;
codec_write(CR1, cr1_sel|SB_MICBIAS);
if (enable)
{
/* input up before it is mixed in */
pmr1 &= ~FM_IN_SB;
codec_write(PMR1, pmr1);
cr1_sel = DACSEL|FM_BYPASS;
codec_write(CR1, cr1_sel|SB_MICBIAS);
}
else
{
/* out of the mix before the input goes down */
cr1_sel = DACSEL;
codec_write(CR1, cr1_sel|SB_MICBIAS);
pmr1 |= FM_IN_SB;
codec_write(PMR1, pmr1);
}
}