From d4942cc74c82c465ea395637c77ed06565b8b497 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 29 Jun 2018 16:09:28 -0400 Subject: Add Xuelin iHIFI 770/770C/800 support Taken from the xvortex fork (Roman Stolyarov) Ported, rebased, and cleaned up by myself. Change-Id: I7b2bca2d29502f2e4544e42f3d122786dd4b7978 --- firmware/drivers/audio/es9018.c | 134 ++++++++++++++++++++++++++++++++++++++++ firmware/drivers/audio/wm8740.c | 106 +++++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 firmware/drivers/audio/es9018.c create mode 100644 firmware/drivers/audio/wm8740.c (limited to 'firmware/drivers') diff --git a/firmware/drivers/audio/es9018.c b/firmware/drivers/audio/es9018.c new file mode 100644 index 0000000000..89e8c1d46f --- /dev/null +++ b/firmware/drivers/audio/es9018.c @@ -0,0 +1,134 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "system.h" +#include "es9018.h" +#include "config.h" +#include "audio.h" +#include "audiohw.h" + +/* NOTE: The register names are not known, as the register numbering + listed in the ES9018 datasheet does not match what is described below.. */ + +static uint8_t reg0 = 0x00; /* System settings. Default value of register 0 */ +static uint8_t reg1 = 0x80; /* Input settings. Manual input, I2S, 32-bit (?) */ +static uint8_t reg4 = 0x00; /* Automute time. Default = disabled */ +static uint8_t reg5 = 0x68; /* Automute level. Default is some level */ +static uint8_t reg6 = 0x4A; /* Deemphasis. Default = disabled */ +static uint8_t reg7 = 0x83; /* General settings. Default sharp fir, pcm iir and muted */ +static uint8_t reg8 = 0x10; /* GPIO configuration */ +static uint8_t reg10 = 0x05; /* Master Mode Control. Default value: master mode off */ +static uint8_t reg11 = 0x02; /* Channel Mapping. Default stereo is Ch1=left, Ch2=right */ +static uint8_t reg12 = 0x50; /* DPLL Settings. Default = 005 for I2S, OFF for DSD */ +static uint8_t reg13 = 0x40; /* THD Compensation */ +static uint8_t reg14 = 0x8A; /* Soft Start Settings */ +static uint8_t reg21 = 0x00; /* Oversampling filter. Default: oversampling ON */ + +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) + +static int vol_tenthdb2hw(const int tdb) +{ + if (tdb < ES9018_VOLUME_MIN) { + return 0xff; + } else if (tdb > ES9018_VOLUME_MAX) { + return 0x00; + } else { + return (-tdb/5); + } +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + es9018_write_reg(15, vol_tenthdb2hw(vol_l)); + es9018_write_reg(16, vol_tenthdb2hw(vol_r)); +} + +void audiohw_mute(void) +{ + bitSet(reg7, 0); /* Mute Channel 1 */ + bitSet(reg7, 1); /* Mute Channel 2 */ + es9018_write_reg(0x07, reg7); +} + +void audiohw_unmute(void) +{ + bitClear(reg7, 0); /* Unmute Channel 1 */ + bitClear(reg7, 1); /* Unmute Channel 2 */ + es9018_write_reg(0x07, reg7); +} + +void audiohw_init(void) +{ + es9018_write_reg(0x00, reg0); + es9018_write_reg(0x01, reg1); + es9018_write_reg(0x04, reg4); + es9018_write_reg(0x05, reg5); + es9018_write_reg(0x06, reg6); + es9018_write_reg(0x07, reg7); + es9018_write_reg(0x08, reg8); + es9018_write_reg(0x0A, reg10); + es9018_write_reg(0x0B, reg11); + es9018_write_reg(0x0C, reg12); + es9018_write_reg(0x0D, reg13); + es9018_write_reg(0x0E, reg14); + es9018_write_reg(0x15, reg21); +} + +void audiohw_preinit(void) +{ +} + +void audiohw_set_frequency(int fsel) +{ + (void)fsel; +} + +void audiohw_set_filter_roll_off(int value) +{ + /* 0 = Sharp (Default) + 1 = Slow + 2 = Short + 3 = Bypass */ + switch(value) + { + case 0: + bitClear(reg7, 5); + bitClear(reg7, 6); + bitClear(reg21, 0); + break; + case 1: + bitSet(reg7, 5); + bitClear(reg7, 6); + bitClear(reg21, 0); + break; + case 2: + bitClear(reg7, 5); + bitSet(reg7, 6); + bitClear(reg21, 0); + break; + case 3: + bitSet(reg21, 0); + break; + } + es9018_write_reg(0x07, reg7); + es9018_write_reg(0x15, reg21); +} diff --git a/firmware/drivers/audio/wm8740.c b/firmware/drivers/audio/wm8740.c new file mode 100644 index 0000000000..d88f53bd75 --- /dev/null +++ b/firmware/drivers/audio/wm8740.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "system.h" +#include "wm8740.h" +#include "config.h" +#include "audio.h" +#include "audiohw.h" + +static void wm8740_write_reg(const int reg, const unsigned int value) +{ + int i; + + for (i = (1<<15); i; i >>= 1) { + udelay(1); + wm8740_set_mc(0); + if ((reg|value) & i) { + wm8740_set_md(1); + } else { + wm8740_set_md(0); + } + udelay(1); + wm8740_set_mc(1); + } + udelay(1); + wm8740_set_ml(0); + udelay(1); + wm8740_set_mc(0); + udelay(1); + wm8740_set_ml(1); + udelay(1); +} + +static int vol_tenthdb2hw(const int tdb) +{ + if (tdb < WM8740_VOLUME_MIN) { + return 0x00; + } else if (tdb > WM8740_VOLUME_MAX) { + return 0xff; + } else { + return ((tdb / 5 + 0xff) & 0xff); + } +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + wm8740_write_reg(WM8740_REG0, vol_tenthdb2hw(vol_l)); + wm8740_write_reg(WM8740_REG1, vol_tenthdb2hw(vol_r) | WM8740_LDR); +} + +void audiohw_mute(void) +{ + wm8740_write_reg(WM8740_REG2, WM8740_MUT); +} + +void audiohw_unmute(void) +{ + wm8740_write_reg(WM8740_REG2, 0x00); +} + +void audiohw_init(void) +{ + wm8740_write_reg(WM8740_REG0, 0x00); + wm8740_write_reg(WM8740_REG1, 0x00); + wm8740_write_reg(WM8740_REG2, WM8740_MUT); + wm8740_write_reg(WM8740_REG3, WM8740_I2S); + wm8740_write_reg(WM8740_REG4, 0x00); +} + +void audiohw_preinit(void) +{ +} + +void audiohw_set_frequency(int fsel) +{ + (void)fsel; +} + +void audiohw_set_filter_roll_off(int value) +{ + /* 0 = fast (sharp); + 1 = slow */ + if (value == 0) { + wm8740_write_reg(WM8740_REG3, WM8740_I2S); + } else { + wm8740_write_reg(WM8740_REG3, WM8740_I2S | WM8740_SR0); + } +} -- cgit v1.2.3