4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
33 * \author Daniele Basile <asterix@develer.com>
35 * \brief WM8731 Audio codec 2 wire driver.
41 #include "hw/hw_wm8731.h"
42 #include "cfg/cfg_wm8731.h"
44 // Define logging setting (for cfg/log.h module).
45 #define LOG_LEVEL WM8731_LOG_LEVEL
46 #define LOG_FORMAT WM8731_LOG_FORMAT
48 #include <cfg/macros.h>
55 static void wm8731_write(Wm8731 *ctx, uint8_t reg, uint16_t value)
58 uint16_t tmp = ((reg & 0x7F) << 9) | (value & 0x1FF);
60 i2c_start_w(ctx->i2c, ctx->addr, 2, I2C_STOP);
61 i2c_putc(ctx->i2c, (uint8_t)((tmp & 0xFF00) >> 8));
62 i2c_putc(ctx->i2c, (uint8_t)(tmp & 0xFF));
64 if (i2c_error(ctx->i2c))
65 LOG_ERR("Error while send command to codec.\n");
69 #define RANGECONV(data, y1, y2) (((((int32_t)(data)) * ((y2) - (y1))) / ((1 << 8) - 1)) + (y1))
70 void wm8731_setVolume(Wm8731 *ctx, uint16_t device, uint8_t volume)
74 if (device & WM8731_LINE_IN)
78 wm8731_write(ctx, WM8731_REG_RIGHT_LINEIN, BV(WM8731_LINMUTE_BIT) | BV(WM8731_RLINBOTH_BIT));
79 wm8731_write(ctx, WM8731_REG_LEFT_LINEIN, BV(WM8731_LINMUTE_BIT) | BV(WM8731_LRINBOTH_BIT));
82 value = DIV_ROUND(volume * WM8731_LINVOL_BITS_MASK, 100);
84 wm8731_write(ctx, WM8731_REG_RIGHT_LINEIN, ~BV(WM8731_LINMUTE_BIT) | value);
85 wm8731_write(ctx, WM8731_REG_LEFT_LINEIN, ~BV(WM8731_RINMUTE_BIT) | value);
86 LOG_INFO("Set LINE IN vol[%d]%% raw[%d]\n", volume, value);
89 if (device & WM8731_HEADPHONE)
91 value = DIV_ROUND(volume * WM8731_RHPVOL_BITS_MASK, 100);
93 wm8731_write(ctx, WM8731_REG_RIGHT_HPOUT, value | BV(WM8731_RZCEN_BIT) | BV(WM8731_RLHPBOTH_BIT));
94 wm8731_write(ctx, WM8731_REG_LEFT_HPOUT, value | BV(WM8731_LZCEN_BIT) | BV(WM8731_LRHPBOTH_BIT));
95 LOG_INFO("Set HEADPHONE vol[%d]%% raw[%d]\n", volume, value);
100 void wm8731_powerOn(Wm8731 *ctx)
102 LOG_INFO("Power on codec\n");
103 wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, ~BV(WM8731_POWEROFF_BIT) & 0x7F);
106 void wm8731_powerOff(Wm8731 *ctx)
108 LOG_INFO("Power off codec\n");
109 wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, BV(WM8731_POWEROFF_BIT) & 0x7F);
112 void wm8731_powerOnDevices(Wm8731 *ctx, uint16_t device)
114 wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, ~device & 0x7F);
115 LOG_INFO("Turn on the devices[%x]\n", ~device & 0x7F);
118 void wm8731_powerOffDevices(Wm8731 *ctx, uint16_t device)
120 wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, device & 0x7F);
121 LOG_INFO("Turn off the devices[%x]\n", device);
124 void wm8731_init(Wm8731 *ctx, I2c *i2c, uint8_t codec_addr)
127 ctx->addr = codec_addr;
132 LOG_INFO("Init WM8731 codec.\n");
134 /* Reset codec and active it */
135 wm8731_write(ctx, WM8731_REG_RESET, 0);
138 /* Configure the codec */
139 wm8731_write(ctx, WM8731_REG_DIGITAL_PATH_CTRL, CONFIG_WM8731_DEEMP | CONFIG_WM8731_DAPC |
140 (CONFIG_WM8731_DACMU << WM8731_DACMU));
141 wm8731_write(ctx, WM8731_REG_ANALOGUE_PATH_CTRL, (CONFIG_WM8731_MICBOOST ? BV(WM8731_MICBOOST) : ~BV(WM8731_MICBOOST)) |
142 CONFIG_WM8731_INSEL | CONFIG_WM8731_BYPASS | CONFIG_WM8731_SIDEATT);
143 wm8731_write(ctx, WM8731_REG_DA_INTERFACE_FORMAT, CONFIG_WM8731_INTERFACE_FORMAT | CONFIG_WM8731_IWL_BITS |
144 (CONFIG_WM8731_MS ? BV(WM8731_MS_BIT) : ~BV(WM8731_MS_BIT)));
145 wm8731_write(ctx, WM8731_REG_SAMPLECTRL, CONFIG_WM8731_SAMPLING_RATES);
147 /* By default we turn on all devices and disable only the outclock */
148 wm8731_write(ctx, WM8731_REG_ACTIVE_CTRL, 1);
149 wm8731_write(ctx, WM8731_REG_PWDOWN_CTRL, 0x40);