【i2s】Milk-V Duo添加speaker——max98357a解码器驱动

This is what I have in board.c for Duo 64M:

#if defined(CONFIG_PHY_CVITEK)
static void cv180x_ephy_id_init(void)
{
        // set rg_ephy_apb_rw_sel 0x0804@[0]=1/APB by using APB interface
        mmio_write_32(0x03009804, 0x0001);
        
        // Release 0x0800[0]=0/shutdown
        mmio_write_32(0x03009800, 0x0900);
 
        // Release 0x0800[2]=1/dig_rst_n, Let mii_reg can be accessabile
        mmio_write_32(0x03009800, 0x0904);
        
        // ANA INIT (PD/EN), switch to MII-page5
        mmio_write_32(0x0300907c, 0x0500);
        // Release ANA_PD p5.0x10@[13:8] = 6'b001100
        mmio_write_32(0x03009040, 0x0c00);
        // Release ANA_EN p5.0x10@[7:0] = 8'b01111110
        mmio_write_32(0x03009040, 0x0c7e);
 
        // Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
        //mdelay(1);
        
        // Release 0x0800[1] = 1/ana_rst_n
        mmio_write_32(0x03009800, 0x0906);

        // ANA INIT
        // @Switch to MII-page5
        mmio_write_32(0x0300907c, 0x0500);

        // PHY_ID
        mmio_write_32(0x03009008, 0x0043);
        mmio_write_32(0x0300900c, 0x5649);

        // switch to MDIO control by ETH_MAC
        mmio_write_32(0x03009804, 0x0000);
}

static void cv180x_ephy_led_pinmux(void)
{
        // LED PAD MUX
        mmio_write_32(0x0300109c, 0x05);
        mmio_write_32(0x030010a0, 0x05);
        //(SD1_CLK selphy)
        mmio_write_32(0x050270b0, 0x11111111);
        //(SD1_CMD selphy)
        mmio_write_32(0x050270b4, 0x11111111);
}
#endif


static void cv180x_i2s2_init(void)
{
       printk("cv180x_i2s2_init\n");
       mmio_write_32(0x03009804, 0x0001);
       mmio_write_32(0x03009808, 0x0001);
       mmio_write_32(0x03009800, 0x0905);

       // Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
//       mdelay(1);

       mmio_write_32(0x0300907C, 0x0500);
       mmio_write_32(0x03009078, 0x0F00);
       mmio_write_32(0x03009074, 0x0606);
       mmio_write_32(0x03009070, 0x0606);
}


int board_init(void)
{
        extern uint32_t BOOT0_START_TIME;
        uint16_t start_time = DIV_ROUND_UP(BOOT0_START_TIME, SYS_COUNTER_FREQ_IN_SECOND / 1000);

        // Save uboot start time. time is from boot0.h
        mmio_write_16(TIME_RECORDS_FIELD_UBOOT_START, start_time);

#if defined(CONFIG_PHY_CVITEK) /* config cvitek cv180x eth internal phy on ASIC board */
        cv180x_ephy_id_init();
        cv180x_ephy_led_pinmux();
#endif

       cv180x_i2s2_init();

#if defined(CONFIG_NAND_SUPPORT)
        pinmux_config(PINMUX_SPI_NAND);
#elif defined(CONFIG_SPI_FLASH)
        pinmux_config(PINMUX_SPI_NOR);
#endif
        // pinmux_config(PINMUX_SDIO1);
        pinmux_config(PINMUX_USB);
        //pinmux_config(PINMUX_SPI0);
        //pinmux_config(PINMUX_SPI2);
        cvi_board_init();

        return 0;
}
 

SSH works, audio works without the need to run a user-space program.

The SDK is from January, 2024.

3 Likes

Hi dnech,

I tried that in my board.c and it didn’t seem to work - I still needed to run the userspace prog to set the pinmux correctly. Any chance you could provide a full patch set for the kernel you’re using now, including all the other config and code additions? I’ve been tweaking on my SDK source for so long now that I probably have a lot of stuff in my build that doesn’t match what you’re doing.

Thx!

Hi!

I have uploaded several files which should theoretically contain the clue:

https://drive.google.com/file/d/1aM_m62LY4dT4eIBAdZYRL19E3-qFxh19/view?usp=sharing

I also included my compiled boot.sd and fip.bin files.

1 Like

If I want to use a dac that requires a mclk input, how should I get the mclk?

Unfortunately the I2S2 MCLK signal doesn’t appear as an option on any of the GPIO pins of the Milk-V Duo. I2S1 MCLK is available but I2S1 LRCK is not so AFAICT there’s no pinmux setting that gets you all the I2S signals you’d need including MCLK. There are a lot of I2S DACs available that don’t require an MCLK signal though so you’re limited to those.

Is it possible to use other pin as mclk?

Thanks! I’m currently working on using the CV1800B baremetal, as I talk about in another thread. I was trying to use the ETH pins for SPI1 and found your post.

I had seen this sequence in the spreadsheet file (CV180xb-Pinout-v1.xlsx) but wasn’t too sure it was what was required, or what exactly they meant. But that was it. I implemented that and yep, I can use SPI1 on those pins.

Now a small question. Turns out those pins are 1.8V logic rather than 3.3V. Did you guys use a level shifter, or was your I2S interface 1.8V?

Or (hopeful here), is there a way of switching those pins to 3.3V level?

1 Like

Replying to myself here - I don’t think there’s any way we can switch to 3.3V logic on those ETH pins, it’s 1.8V. (But if anyone knows otherwise…)

And the reason it worked in this thread is that the max98357a, which was what they wanted to drive, has a minimum logic high level of 1.3V on its digital inputs, so 1.8V logic is fine.

1 Like

AFAICT those pins are 1.8V only but from my experience the MAX98357a seems to accept those logic levels w/o problems. I’m currently working on hooking up a TLV320AIC3101 codec which can operate at 1.8V I/O levels and hope to get stereo audio input from that but it will require some new driver work on the receive side.

1 Like

Yes most DACs of this kind should be fine with 1.8V logic.

For other purposes requiring 3.3V, level shifters will be fine. That’s no big deal.

But OTOH, conversely, I was kinda planning to use the SDIO1 controller @1.8V, and on the Duo board it’s in a 3.3V domain as far as I can tell, so yeah. Not a huge deal either. This chip is pretty great!

1 Like

I’ve been fiddling with the latest buildroot SDK and the patches / changes shown above no longer work. The driver code compiles fine and attempts to load at boot time but fails. I need to do some digging to figure out what the error code means (if it’s helpful at all).

On the upside, the built-in codec seems to work out-of-the box.

1 Like