wm8731.c
Go to the documentation of this file.
00001
00039 #include "wm8731.h"
00040
00041 #include "hw/hw_wm8731.h"
00042 #include "cfg/cfg_wm8731.h"
00043
00044 // Define logging setting (for cfg/log.h module).
00045 #define LOG_LEVEL   WM8731_LOG_LEVEL
00046 #define LOG_FORMAT  WM8731_LOG_FORMAT
00047 #include <cfg/log.h>
00048 #include <cfg/macros.h>
00049
00050 #include <cpu/irq.h>
00051
00052 #include <drv/i2c.h>
00053
00054
00055 static void wm8731_write(Wm8731 *ctx, uint8_t reg, uint16_t value)
00056 {
00057
00058     uint16_t tmp = ((reg & 0x7F) << 9) | (value & 0x1FF);
00059
00060     i2c_start_w(ctx->i2c, ctx->addr, 2, I2C_STOP);
00061     i2c_putc(ctx->i2c, (uint8_t)((tmp & 0xFF00) >> 8));
00062     i2c_putc(ctx->i2c, (uint8_t)(tmp & 0xFF));
00063
00064     int err = i2c_error(ctx->i2c);
00065     if (err)
00066         LOG_ERR("Error[%d] while send command to codec.\n", err);
00067
00068 }
00069
00070 #define RANGECONV(data, y1, y2) (((((int32_t)(data)) * ((y2) - (y1))) / ((1 << 8) - 1)) + (y1))
00071 void wm8731_setVolume(Wm8731 *ctx, uint16_t device, uint8_t volume)
00072 {
00073     uint16_t value;
00074
00075     if (device & WM8731_LINE_IN)
00076     {
00077         if (!volume)
00078         {
00079             wm8731_write(ctx, WM8731_REG_RIGHT_LINEIN, BV(WM8731_LINMUTE_BIT) | BV(WM8731_RLINBOTH_BIT));
00080             wm8731_write(ctx, WM8731_REG_LEFT_LINEIN, BV(WM8731_LINMUTE_BIT) | BV(WM8731_LRINBOTH_BIT));
00081         }
00082
00083         value = DIV_ROUND(volume * WM8731_LINVOL_BITS_MASK, 100);
00084
00085         wm8731_write(ctx, WM8731_REG_RIGHT_LINEIN, ~BV(WM8731_LINMUTE_BIT) | value);
00086         wm8731_write(ctx, WM8731_REG_LEFT_LINEIN, ~BV(WM8731_RINMUTE_BIT) | value);
00087         LOG_INFO("Set LINE IN vol[%d]%% raw[%d]\n", volume, value);
00088     }
00089
00090     if (device & WM8731_HEADPHONE)
00091     {
00092         value = DIV_ROUND(volume * WM8731_RHPVOL_BITS_MASK, 100);
00093
00094         wm8731_write(ctx, WM8731_REG_RIGHT_HPOUT, value | BV(WM8731_RZCEN_BIT) | BV(WM8731_RLHPBOTH_BIT));
00095         wm8731_write(ctx, WM8731_REG_LEFT_HPOUT, value  | BV(WM8731_LZCEN_BIT) | BV(WM8731_LRHPBOTH_BIT));
00096         LOG_INFO("Set HEADPHONE vol[%d]%% raw[%d]\n", volume, value);
00097     }
00098
00099 }
00100
00101 void wm8731_powerOn(Wm8731 *ctx)
00102 {
00103     LOG_INFO("Power on codec\n");
00104     wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, ~BV(WM8731_POWEROFF_BIT) & 0x7F);
00105 }
00106
00107 void wm8731_powerOff(Wm8731 *ctx)
00108 {
00109     LOG_INFO("Power off codec\n");
00110     wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, BV(WM8731_POWEROFF_BIT) & 0x7F);
00111 }
00112
00113 void wm8731_powerOnDevices(Wm8731 *ctx, uint16_t device)
00114 {
00115     wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, ~device & 0x7F);
00116     LOG_INFO("Turn on the devices[%x]\n", ~device & 0x7F);
00117 }
00118
00119 void wm8731_powerOffDevices(Wm8731 *ctx, uint16_t device)
00120 {
00121     wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, device & 0x7F);
00122     LOG_INFO("Turn off the devices[%x]\n", device);
00123 }
00124
00125 void wm8731_init(Wm8731 *ctx, I2c *i2c, uint8_t codec_addr)
00126 {
00127     ctx->i2c = i2c;
00128     ctx->addr = codec_addr;
00129
00130     WM8731_PIN_INIT();
00131     WM8731_MCLK_INIT();
00132
00133     LOG_INFO("Init WM8731 codec.\n");
00134
00135     /* Reset codec and active it */
00136     wm8731_write(ctx, WM8731_REG_RESET, 0);
00137
00138
00139     /* Configure the codec */
00140     wm8731_write(ctx, WM8731_REG_DIGITAL_PATH_CTRL, CONFIG_WM8731_DEEMP | CONFIG_WM8731_DAPC | (CONFIG_WM8731_DACMU << WM8731_DACMU));
00141
00142     #if CONFIG_WM8731_MICBOOST
00143     wm8731_write(ctx, WM8731_REG_ANALOGUE_PATH_CTRL, BV(WM8731_MICBOOST) | CONFIG_WM8731_INSEL | CONFIG_WM8731_BYPASS | CONFIG_WM8731_SIDEATT);
00144     #else
00145     wm8731_write(ctx, WM8731_REG_ANALOGUE_PATH_CTRL, (CONFIG_WM8731_INSEL | CONFIG_WM8731_BYPASS | CONFIG_WM8731_SIDEATT) & ~BV(WM8731_MICBOOST));
00146     #endif
00147 
00148     #if CONFIG_WM8731_MS
00149     wm8731_write(ctx, WM8731_REG_DA_INTERFACE_FORMAT, CONFIG_WM8731_INTERFACE_FORMAT | CONFIG_WM8731_IWL_BITS | BV(WM8731_MS_BIT));
00150     #else
00151     wm8731_write(ctx, WM8731_REG_DA_INTERFACE_FORMAT,
00152         (CONFIG_WM8731_INTERFACE_FORMAT | CONFIG_WM8731_IWL_BITS | BV(WM8731_MS_BIT)) & ~BV(WM8731_MS_BIT));
00153     #endif
00154 
00155     wm8731_write(ctx, WM8731_REG_SAMPLECTRL, CONFIG_WM8731_SAMPLING_RATES);
00156
00157     /* By default we turn on all devices and disable only the outclock */
00158     wm8731_write(ctx, WM8731_REG_ACTIVE_CTRL, 1);
00159     wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, 0x40);
00160 }