Rockbox Technical Forums

Support and General Use => Hardware => Topic started by: no_one on December 23, 2017, 10:43:47 PM

Title: iPod gen 5.5, made capless output mod, need to modify driver
Post by: no_one on December 23, 2017, 10:43:47 PM
Hi all,
Decided to make the capless output mod, using VMID as common. Basically the alternative from the datasheet. I can't figure out how to mute L/ROUT2 (so they go VMID). Any ideas would be appreciated.
There was a guy, beyondwind, that had a modified rockbox firmware online. But that website is gone now, and I can't figure out how to do it.
The chipset is wm8758. Right now I'm trying to modify firmware/drivers/audio/wm8758.c and recompile and hope to somehow get it to work.
Title: Re: iPod gen 5.5, made capless output mod, need to modify driver
Post by: saratoga on December 24, 2017, 02:00:10 AM
Very quickly skinning that datasheet (I'm not familiar with that dac), it looks like you just set the mute bits in r54 and r55, and presuming you routed the common pin to either left or right output pin, it should work.
Title: Re: iPod gen 5.5, made capless output mod, need to modify driver
Post by: KhronX on December 24, 2017, 05:35:43 AM
Fortunately, the Wayback Machine has indeed archived his pages. That's where i found the patched FW so Rockbox wouldn't crap out after my mSATA SSD mod.

https://web.archive.org/web/20150307065100/http://beyondwind.duckdns.org/?page_id=51

There was a guy, beyondwind, that had a modified rockbox firmware online. But that website is gone now, and I can't figure out how to do it.
Title: Re: iPod gen 5.5, made capless output mod, need to modify driver
Post by: no_one on December 24, 2017, 12:13:55 PM
I removed the two output capacitors from Lout2 and Rout2. I bridged them together and made that the common line for theadphones. That wire goes to the audio jack's ground/common connection.
(https://i.imgur.com/ByCflrV.jpg)
I also removed the two big 220uF output caps from Lout1 and Rout1. I tapped the pads coming from the chip, and those go directly to the left/right connections on the audio jack. I also removed the HP_COM and LINE_COM caps.
(https://i.imgur.com/w1pBtG8.jpg)
I used "litz" wire from some older broken headphones. great way to do this mod as it's very soft and shapes well.
I measured for shorts and everything is ok.
Now, looking at the two versions for implementation in the datasheet:
(https://i.imgur.com/Z5Z7mCM.png)
I modified according to the DC Coupled Headphone output version.
Now I need to make the software modifications as well. I used the latest rockbox (3.14 - great build!)
I found 2 files in the rockbox sources, that are of interest.
wm8758.c at this location 'firmware/drivers/audio/'
wm8758.h at this location '´╗┐firmware/export/
Here's an example of what's in the .h file:
Code: [Select]
#define LOUT2VOL                0x36 /* default 039 */
#define LOUT2VOL_MASK           0x3f
#define LOUT2VOL_LOUT2MUTE      (1 << 6)
#define LOUT2VOL_LOUT2ZC        (1 << 7)
#define LOUT2VOL_OUT2VU         (1 << 8)

#define ROUT2VOL                0x37 /* default 039 */
#define ROUT2VOL_MASK           0x3f
#define ROUT2VOL_ROUT2MUTE      (1 << 6)
#define ROUT2VOL_ROUT2ZC        (1 << 7)
#define ROUT2VOL_OUT2VU         (1 << 8)

So I already have that defined, I just need to call it somehow in the .c file. I also attached both files to this post.
Here's the init sequence as recommended in the datasheet (from .c file):
Code: [Select]
void audiohw_preinit(void)
{
    /* Set low bias mode */
    wmcodec_write(BIASCTRL, BIASCTRL_BIASCUT);
    /* Enable HPCOM, LINECOM */
    wmcodec_write(OUTCTRL, OUTCTRL_HP_COM | OUTCTRL_LINE_COM
                         | OUTCTRL_TSOPCTRL | OUTCTRL_TSDEN | OUTCTRL_VROI);
    /* Mute all Outputs and set PGAs minimum gain */
    wmcodec_write(LOUT1VOL, 0x140);
    wmcodec_write(ROUT1VOL, 0x140);
    wmcodec_write(LOUT2VOL, 0x140);
    wmcodec_write(ROUT2VOL, 0x140);
    wmcodec_write(OUT3MIX,  0x40);
    wmcodec_write(OUT4MIX,  0x40);
    /* Enable L/ROUT1 */
    wmcodec_write(PWRMGMT2, PWRMGMT2_ROUT1EN | PWRMGMT2_LOUT1EN);
    /* Enable VMID independent current bias */
    wmcodec_write(OUT4TOADC, OUT4TOADC_POBCTRL);
    /* Enable required DACs and mixers */
    wmcodec_write(PWRMGMT3, PWRMGMT3_RMIXEN | PWRMGMT3_LMIXEN
                          | PWRMGMT3_DACENR | PWRMGMT3_DACENL);
    /* Enable VMIDSEL, BIASEN, BUFIOEN */
    wmcodec_write(PWRMGMT1, PWRMGMT1_PLLEN | PWRMGMT1_BIASEN
                          | PWRMGMT1_BUFIOEN | PWRMGMT1_VMIDSEL_10K);
    /* Setup digital interface, input amplifiers, PLL, ADCs and DACs */
    wmcodec_write(AINTFCE, AINTFCE_IWL_16BIT | AINTFCE_FORMAT_I2S);
    wmcodec_write(CLKCTRL, CLKCTRL_MS); /* WM8758 is clock master */

    audiohw_set_frequency(HW_FREQ_44);

    wmcodec_write(LOUTMIX, LOUTMIX_DACL2LMIX);
    wmcodec_write(ROUTMIX, ROUTMIX_DACR2RMIX);
    /* Disable VMID independent current bias */
    wmcodec_write(OUT4TOADC, 0);
}

void audiohw_postinit(void)
{
    wmcodec_write(PWRMGMT1, PWRMGMT1_PLLEN | PWRMGMT1_BIASEN
                          | PWRMGMT1_BUFIOEN | PWRMGMT1_VMIDSEL_500K);
                          /* lower the VMID power consumption */
    wmcodec_write(BIASCTRL, 0);
    audiohw_mute(false);
}

I think I can call it with something like:
Code: [Select]
    wmcodec_write(LOUT2VOL, LOUT2VOL_LOUT2MUTE);
    wmcodec_write(ROUT2VOL, ROUT2VOL_ROUT2MUTE);

I am not sure if this is enough. Here's the available volume control:
(https://i.imgur.com/AhAQyFz.png)

A normal volume change is called like this:
Code: [Select]
void audiohw_set_lineout_volume(int vol_l, int vol_r)
{
    int dac_l, amp_l, dac_r, amp_r;

    vol_l = vol_tenthdb2hw(vol_l);
    vol_r = vol_tenthdb2hw(vol_r);

    get_volume_params(vol_l, &dac_l, &amp_l);
    get_volume_params(vol_r, &dac_r, &amp_r);

    /* set lineout amp OUT2 */
    wmcodec_write(LOUT2VOL, amp_l | LOUT2VOL_LOUT2ZC);
    wmcodec_write(ROUT2VOL, amp_r | ROUT2VOL_ROUT2ZC | ROUT2VOL_OUT2VU);
}

And the datasheet says this:
Quote
LOUT2 and ROUT2 volumes do not
update until a 1 is written to SPKVU
(in reg 54 or 55)

I'm not sure if muting is considered volume change, and need to call zero-crossing with LOUT2VOL_LOUT2ZC/ROUT2VOL_ROUT2ZC and set the ROUT2VOL_OUT2VU for Output2 to go to VMID.

Right now it sounds like crap. I don't have any DC between common and each channel. But there's no Left/Right separation. and it makes sense as Lout2 and Rout2 are tied together. If they don't go to VMID, it sounds like crap.
Here's exactly what the LOUT2VOL_LOUT2MUTE and ROUT2VOL_ROUT2MUTE bits do with the outputs:
(https://i.imgur.com/eaNxwlw.png)
Title: Re: iPod gen 5.5, made capless output mod, need to modify driver
Post by: no_one on December 24, 2017, 12:24:32 PM
Fortunately, the Wayback Machine has indeed archived his pages. That's where i found the patched FW so Rockbox wouldn't crap out after my mSATA SSD mod.

https://web.archive.org/web/20150307065100/http://beyondwind.duckdns.org/?page_id=51


I have the text for my mod, but no pictures and no hosted files, like the modified rockbox firmware he had. Also, he didn't detail anything about the kind of mod he did to the wm driver.
I'm pretty sure I have the hardware mod just right, only need to modify the software.
Also I'm thinking of adding extra filtering for AVDD. But I need a low profile cap, and author recommended a 47uF cap. I only have a 220uF that's that small, one used for the dc filtering on the output1. Seems kind of large, I'm not sure if it's ok to go that big.

*edit
Also I'm interested if there's a way to work live with this. Can I ssh into Rockbox, and recompile only the driver, and reload it? Would be faster than compiling the whole rockbox and having to switch back and forth with the firmware.

*update
I seem to have figured out why I didn't notice any change in my tests. When I unarchived the rockbox.zip file in the root of ipod, I just double clicked the archive file and presumed it overwrites the old folder. Nope, they were added as .rockbox2 .rockbox3 etc folders. So right now I did manage to make it work. I just called the mute bits in both enabling of L/R Out2 and setting it's volume.
Code: [Select]
void audiohw_set_lineout_volume(int vol_l, int vol_r)
{
    int dac_l, amp_l, dac_r, amp_r;
    wmcodec_write(LOUT2VOL, LOUT2VOL_LOUT2MUTE);
    wmcodec_write(ROUT2VOL, ROUT2VOL_ROUT2MUTE);
}

void audiohw_enable_lineout(bool enable)
{
    /* Initialize data without lineout enabling. */
    int pwrmgmt3_data  = PWRMGMT3_RMIXEN  | PWRMGMT3_LMIXEN
                       | PWRMGMT3_DACENR  | PWRMGMT3_DACENL;
    /* Set lineout (OUT2), if enabled. */
    if (enable)
        pwrmgmt3_data |= PWRMGMT3_LOUT2EN | PWRMGMT3_ROUT2EN;
         
    /* Set register. */
    wmcodec_write(PWRMGMT3, pwrmgmt3_data);
    wmcodec_write(LOUT2VOL, LOUT2VOL_LOUT2MUTE);
    wmcodec_write(ROUT2VOL, ROUT2VOL_ROUT2MUTE);
}

This way I am sure that whenever those functions are called, they get OUT2 to VMID.

I do like how it sounds, it's all there somehow. The bad thing is that I can hear some background noise, not much but it's there. maybe I can make most of it go away with some extra filtering on AVDD1.
Anyone knows if I can use on of those DC filtering caps that I removed from OUT1? Are they good enough for ps filtering on AVDD1?
The mod guy used a 47uF slim tantalum cap. Can't find tantalum caps that low profile. I don't know the type of the signal line dc blocking cap. Does the ps filtering cap type matter? voltage rating should be ok.