blob: 86bdc1f463d49e0c824a5d8477c0cd4dbed03f75 [file] [log] [blame]
/*
* rt5670.c -- RT5670 ALSA SoC DSP driver
*
* Copyright 2011 Realtek Semiconductor Corp.
* Author: Johnny Hsu <johnnyhsu@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#define RTK_IOCTL
#ifdef RTK_IOCTL
#include <linux/spi/spi.h>
#include "rt_codec_ioctl.h"
#endif
#include "rt5670.h"
#include "rt5670-dsp.h"
#define DSP_CLK_RATE RT5670_DSP_CLK_96K
static unsigned short rt5670_dsp_patch[][2] = {
{0xe1, 0x0010}, {0xe2, 0x0000}, {0xe0, 0x6ac9},
{0xe1, 0x0064}, {0xe2, 0x0000}, {0xe0, 0x68c5},
{0xe1, 0x3f00}, {0xe2, 0x8301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f01}, {0xe2, 0x9212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f02}, {0xe2, 0x830f}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f03}, {0xe2, 0x9301}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f04}, {0xe2, 0x81cc}, {0xe3, 0x008c}, {0xe0, 0x0dcf},
{0xe1, 0x3f05}, {0xe2, 0x4009}, {0xe3, 0x000a}, {0xe0, 0x0dcf},
{0xe1, 0x3f06}, {0xe2, 0x267c}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f07}, {0xe2, 0x23a2}, {0xe3, 0x00d0}, {0xe0, 0x0dcf},
{0xe1, 0x3f08}, {0xe2, 0x9212}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f09}, {0xe2, 0x93ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f0a}, {0xe2, 0x83ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f0b}, {0xe2, 0x278a}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f0c}, {0xe2, 0x1bf0}, {0xe3, 0x00a1}, {0xe0, 0x0dcf},
{0xe1, 0x3f0d}, {0xe2, 0x8212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f0e}, {0xe2, 0x9301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f0f}, {0xe2, 0x81cc}, {0xe3, 0x008c}, {0xe0, 0x0dcf},
{0xe1, 0x3f10}, {0xe2, 0x1918}, {0xe3, 0x004f}, {0xe0, 0x0dcf},
{0xe1, 0x3f11}, {0xe2, 0x8301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f12}, {0xe2, 0x9212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f13}, {0xe2, 0x830f}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f14}, {0xe2, 0x9301}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f15}, {0xe2, 0x8212}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f16}, {0xe2, 0x93ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f17}, {0xe2, 0x83ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f18}, {0xe2, 0x278a}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f19}, {0xe2, 0x1bf1}, {0xe3, 0x0071}, {0xe0, 0x0dcf},
{0xe1, 0x3f1a}, {0xe2, 0x8212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f1b}, {0xe2, 0x9301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f1c}, {0xe2, 0x8117}, {0xe3, 0x00e5}, {0xe0, 0x0dcf},
{0xe1, 0x3f1d}, {0xe2, 0x191b}, {0xe3, 0x004f}, {0xe0, 0x0dcf},
{0xe1, 0x3f1e}, {0xe2, 0x8301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f1f}, {0xe2, 0x9212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f20}, {0xe2, 0x830f}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f21}, {0xe2, 0x9301}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f22}, {0xe2, 0x8212}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f23}, {0xe2, 0x93ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f24}, {0xe2, 0x83ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f25}, {0xe2, 0x278a}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f26}, {0xe2, 0x1bf2}, {0xe3, 0x0041}, {0xe0, 0x0dcf},
{0xe1, 0x3f27}, {0xe2, 0x8212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f28}, {0xe2, 0x9301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f29}, {0xe2, 0x8117}, {0xe3, 0x00e5}, {0xe0, 0x0dcf},
{0xe1, 0x3f2a}, {0xe2, 0x1921}, {0xe3, 0x007f}, {0xe0, 0x0dcf},
{0xe1, 0x3f2b}, {0xe2, 0x8301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f2c}, {0xe2, 0x9212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f2d}, {0xe2, 0x8307}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f2e}, {0xe2, 0x9301}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f2f}, {0xe2, 0x81cc}, {0xe3, 0x008c}, {0xe0, 0x0dcf},
{0xe1, 0x3f30}, {0xe2, 0x4009}, {0xe3, 0x000a}, {0xe0, 0x0dcf},
{0xe1, 0x3f31}, {0xe2, 0x267c}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f32}, {0xe2, 0x23a2}, {0xe3, 0x00d0}, {0xe0, 0x0dcf},
{0xe1, 0x3f33}, {0xe2, 0x9212}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f34}, {0xe2, 0x93ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f35}, {0xe2, 0x83ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f36}, {0xe2, 0x278a}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f37}, {0xe2, 0x1bf3}, {0xe3, 0x0051}, {0xe0, 0x0dcf},
{0xe1, 0x3f38}, {0xe2, 0x8212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f39}, {0xe2, 0x9301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f3a}, {0xe2, 0x81cc}, {0xe3, 0x008c}, {0xe0, 0x0dcf},
{0xe1, 0x3f3b}, {0xe2, 0x3400}, {0xe3, 0x004e}, {0xe0, 0x0dcf},
{0xe1, 0x3f3c}, {0xe2, 0x1a09}, {0xe3, 0x00ef}, {0xe0, 0x0dcf},
{0xe1, 0x3f3d}, {0xe2, 0x8301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f3e}, {0xe2, 0x9212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f3f}, {0xe2, 0x8307}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f40}, {0xe2, 0x9301}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f41}, {0xe2, 0x8212}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f42}, {0xe2, 0x93ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f43}, {0xe2, 0x83ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f44}, {0xe2, 0x278a}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f45}, {0xe2, 0x1bf4}, {0xe3, 0x0031}, {0xe0, 0x0dcf},
{0xe1, 0x3f46}, {0xe2, 0x8212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f47}, {0xe2, 0x9301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f48}, {0xe2, 0x8117}, {0xe3, 0x00e5}, {0xe0, 0x0dcf},
{0xe1, 0x3f49}, {0xe2, 0x3400}, {0xe3, 0x004e}, {0xe0, 0x0dcf},
{0xe1, 0x3f4a}, {0xe2, 0x1a0c}, {0xe3, 0x00ef}, {0xe0, 0x0dcf},
{0xe1, 0x3f4b}, {0xe2, 0x8301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f4c}, {0xe2, 0x9212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f4d}, {0xe2, 0x8307}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f4e}, {0xe2, 0x9301}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f4f}, {0xe2, 0x8212}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f50}, {0xe2, 0x93ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f51}, {0xe2, 0x83ff}, {0xe3, 0x00ea}, {0xe0, 0x0dcf},
{0xe1, 0x3f52}, {0xe2, 0x278a}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f53}, {0xe2, 0x1bf5}, {0xe3, 0x0011}, {0xe0, 0x0dcf},
{0xe1, 0x3f54}, {0xe2, 0x8212}, {0xe3, 0x0098}, {0xe0, 0x0dcf},
{0xe1, 0x3f55}, {0xe2, 0x9301}, {0xe3, 0x00f8}, {0xe0, 0x0dcf},
{0xe1, 0x3f56}, {0xe2, 0x8117}, {0xe3, 0x00e5}, {0xe0, 0x0dcf},
{0xe1, 0x3f57}, {0xe2, 0x3400}, {0xe3, 0x004e}, {0xe0, 0x0dcf},
{0xe1, 0x3f58}, {0xe2, 0x1a13}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f59}, {0xe2, 0x8e77}, {0xe3, 0x00c5}, {0xe0, 0x0dcf},
{0xe1, 0x3f5a}, {0xe2, 0x34b8}, {0xe3, 0x0001}, {0xe0, 0x0dcf},
{0xe1, 0x3f5b}, {0xe2, 0x3960}, {0xe3, 0x0002}, {0xe0, 0x0dcf},
{0xe1, 0x3f5c}, {0xe2, 0x17f6}, {0xe3, 0x000e}, {0xe0, 0x0dcf},
{0xe1, 0x3f5d}, {0xe2, 0x6000}, {0xe3, 0x0016}, {0xe0, 0x0dcf},
{0xe1, 0x3f5e}, {0xe2, 0x7000}, {0xe3, 0x005a}, {0xe0, 0x0dcf},
{0xe1, 0x3f5f}, {0xe2, 0x6800}, {0xe3, 0x0055}, {0xe0, 0x0dcf},
{0xe1, 0x3f60}, {0xe2, 0x7800}, {0xe3, 0x0019}, {0xe0, 0x0dcf},
{0xe1, 0x3f61}, {0xe2, 0x1859}, {0xe3, 0x00bf}, {0xe0, 0x0dcf},
{0xe1, 0x3f62}, {0xe2, 0x8230}, {0xe3, 0x0010}, {0xe0, 0x0dcf},
{0xe1, 0x3f63}, {0xe2, 0x26e0}, {0xe3, 0x00df}, {0xe0, 0x0dcf},
{0xe1, 0x3f64}, {0xe2, 0x1bf6}, {0xe3, 0x0072}, {0xe0, 0x0dcf},
{0xe1, 0x3f65}, {0xe2, 0x3c00}, {0xe3, 0x0015}, {0xe0, 0x0dcf},
{0xe1, 0x3f66}, {0xe2, 0x194f}, {0xe3, 0x00df}, {0xe0, 0x0dcf},
{0xe1, 0x3f67}, {0xe2, 0x0c20}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f68}, {0xe2, 0x8240}, {0xe3, 0x0003}, {0xe0, 0x0dcf},
{0xe1, 0x3f69}, {0xe2, 0x8324}, {0xe3, 0x0007}, {0xe0, 0x0dcf},
{0xe1, 0x3f6a}, {0xe2, 0x2029}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f6b}, {0xe2, 0x9240}, {0xe3, 0x000c}, {0xe0, 0x0dcf},
{0xe1, 0x3f6c}, {0xe2, 0x824c}, {0xe3, 0x0003}, {0xe0, 0x0dcf},
{0xe1, 0x3f6d}, {0xe2, 0x2029}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f6e}, {0xe2, 0x924c}, {0xe3, 0x000c}, {0xe0, 0x0dcf},
{0xe1, 0x3f6f}, {0xe2, 0x0c30}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f70}, {0xe2, 0x1950}, {0xe3, 0x002f}, {0xe0, 0x0dcf},
{0xe1, 0x3f71}, {0xe2, 0x962c}, {0xe3, 0x0076}, {0xe0, 0x0dcf},
{0xe1, 0x3f72}, {0xe2, 0x962c}, {0xe3, 0x0086}, {0xe0, 0x0dcf},
{0xe1, 0x3f73}, {0xe2, 0x4001}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f74}, {0xe2, 0x922c}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f75}, {0xe2, 0x3521}, {0xe3, 0x0091}, {0xe0, 0x0dcf},
{0xe1, 0x3f76}, {0xe2, 0x3521}, {0xe3, 0x0062}, {0xe0, 0x0dcf},
{0xe1, 0x3f77}, {0xe2, 0x3521}, {0xe3, 0x00c0}, {0xe0, 0x0dcf},
{0xe1, 0x3f78}, {0xe2, 0x3c00}, {0xe3, 0x00c5}, {0xe0, 0x0dcf},
{0xe1, 0x3f79}, {0xe2, 0x0c0c}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f7a}, {0xe2, 0x17f8}, {0xe3, 0x00ee}, {0xe0, 0x0dcf},
{0xe1, 0x3f7b}, {0xe2, 0x6000}, {0xe3, 0x00a5}, {0xe0, 0x0dcf},
{0xe1, 0x3f7c}, {0xe2, 0x22fa}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f7d}, {0xe2, 0x6000}, {0xe3, 0x0049}, {0xe0, 0x0dcf},
{0xe1, 0x3f7e}, {0xe2, 0x66e2}, {0xe3, 0x0051}, {0xe0, 0x0dcf},
{0xe1, 0x3f7f}, {0xe2, 0x1bf8}, {0xe3, 0x00c3}, {0xe0, 0x0dcf},
{0xe1, 0x3f80}, {0xe2, 0x26ea}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f81}, {0xe2, 0x1bf8}, {0xe3, 0x00c3}, {0xe0, 0x0dcf},
{0xe1, 0x3f82}, {0xe2, 0x822c}, {0xe3, 0x008a}, {0xe0, 0x0dcf},
{0xe1, 0x3f83}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f84}, {0xe2, 0x822c}, {0xe3, 0x0094}, {0xe0, 0x0dcf},
{0xe1, 0x3f85}, {0xe2, 0x26e2}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f86}, {0xe2, 0x1bf8}, {0xe3, 0x00a0}, {0xe0, 0x0dcf},
{0xe1, 0x3f83}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f84}, {0xe2, 0x822c}, {0xe3, 0x0094}, {0xe0, 0x0dcf},
{0xe1, 0x3f85}, {0xe2, 0x26e2}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f86}, {0xe2, 0x1bf8}, {0xe3, 0x00a0}, {0xe0, 0x0dcf},
{0xe1, 0x3f87}, {0xe2, 0x822c}, {0xe3, 0x007a}, {0xe0, 0x0dcf},
{0xe1, 0x3f88}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f89}, {0xe2, 0x922c}, {0xe3, 0x007a}, {0xe0, 0x0dcf},
{0xe1, 0x3f8a}, {0xe2, 0x822c}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f8b}, {0xe2, 0x922c}, {0xe3, 0x008a}, {0xe0, 0x0dcf},
{0xe1, 0x3f8c}, {0xe2, 0x822c}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f8d}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f8e}, {0xe2, 0x922c}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f8f}, {0xe2, 0x0c08}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f90}, {0xe2, 0x8230}, {0xe3, 0x0030}, {0xe0, 0x0dcf},
{0xe1, 0x3f91}, {0xe2, 0x2398}, {0xe3, 0x005f}, {0xe0, 0x0dcf},
{0xe1, 0x3f92}, {0xe2, 0x1bfa}, {0xe3, 0x0020}, {0xe0, 0x0dcf},
{0xe1, 0x3f93}, {0xe2, 0x822c}, {0xe3, 0x007a}, {0xe0, 0x0dcf},
{0xe1, 0x3f94}, {0xe2, 0x822c}, {0xe3, 0x00c4}, {0xe0, 0x0dcf},
{0xe1, 0x3f95}, {0xe2, 0x26e2}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f96}, {0xe2, 0x1bf9}, {0xe3, 0x00e5}, {0xe0, 0x0dcf},
{0xe1, 0x3f97}, {0xe2, 0x822c}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f98}, {0xe2, 0x22e2}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f99}, {0xe2, 0x922c}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f9a}, {0xe2, 0x1bfa}, {0xe3, 0x0022}, {0xe0, 0x0dcf},
{0xe1, 0x3f9b}, {0xe2, 0x962c}, {0xe3, 0x00a6}, {0xe0, 0x0dcf},
{0xe1, 0x3f9c}, {0xe2, 0x962c}, {0xe3, 0x00b6}, {0xe0, 0x0dcf},
{0xe1, 0x3f9d}, {0xe2, 0x1bfa}, {0xe3, 0x002f}, {0xe0, 0x0dcf},
{0xe1, 0x3f9e}, {0xe2, 0x4100}, {0xe3, 0x0014}, {0xe0, 0x0dcf},
{0xe1, 0x3f9f}, {0xe2, 0x922c}, {0xe3, 0x00b4}, {0xe0, 0x0dcf},
{0xe1, 0x3fa0}, {0xe2, 0x4001}, {0xe3, 0x0044}, {0xe0, 0x0dcf},
{0xe1, 0x3fa1}, {0xe2, 0x922c}, {0xe3, 0x00a4}, {0xe0, 0x0dcf},
{0xe1, 0x3fa2}, {0xe2, 0x3c00}, {0xe3, 0x0075}, {0xe0, 0x0dcf},
{0xe1, 0x3fa3}, {0xe2, 0x193c}, {0xe3, 0x00af}, {0xe0, 0x0dcf},
{0xe1, 0x3fa4}, {0xe2, 0x8230}, {0xe3, 0x0030}, {0xe0, 0x0dcf},
{0xe1, 0x3fa5}, {0xe2, 0x2398}, {0xe3, 0x005f}, {0xe0, 0x0dcf},
{0xe1, 0x3fa6}, {0xe2, 0x1bfb}, {0xe3, 0x0050}, {0xe0, 0x0dcf},
{0xe1, 0x3fa7}, {0xe2, 0x822c}, {0xe3, 0x00ba}, {0xe0, 0x0dcf},
{0xe1, 0x3fa8}, {0xe2, 0x267a}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3fa9}, {0xe2, 0x1bfb}, {0xe3, 0x0050}, {0xe0, 0x0dcf},
{0xe1, 0x3faa}, {0xe2, 0x8230}, {0xe3, 0x001a}, {0xe0, 0x0dcf},
{0xe1, 0x3fab}, {0xe2, 0x267a}, {0xe3, 0x007f}, {0xe0, 0x0dcf},
{0xe1, 0x3fac}, {0xe2, 0x4001}, {0xe3, 0x006a}, {0xe0, 0x0dcf},
{0xe1, 0x3fad}, {0xe2, 0x4001}, {0xe3, 0x00f1}, {0xe0, 0x0dcf},
{0xe1, 0x3fae}, {0xe2, 0x2279}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3faf}, {0xe2, 0x0d04}, {0xe3, 0x007a}, {0xe0, 0x0dcf},
{0xe1, 0x3fb0}, {0xe2, 0x3724}, {0xe3, 0x0001}, {0xe0, 0x0dcf},
{0xe1, 0x3fb1}, {0xe2, 0x0900}, {0xe3, 0x0007}, {0xe0, 0x0dcf},
{0xe1, 0x3fb2}, {0xe2, 0xa7ff}, {0xe3, 0x00f5}, {0xe0, 0x0dcf},
{0xe1, 0x3fb3}, {0xe2, 0xa7ff}, {0xe3, 0x00f5}, {0xe0, 0x0dcf},
{0xe1, 0x3fb4}, {0xe2, 0xa7ff}, {0xe3, 0x00f5}, {0xe0, 0x0dcf},
{0xe1, 0x3fb5}, {0xe2, 0x3b24}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3fb6}, {0xe2, 0x194f}, {0xe3, 0x003f}, {0xe0, 0x0dcf},
{0xe1, 0x3fb7}, {0xe2, 0x822e}, {0xe3, 0x00a0}, {0xe0, 0x0dcf},
{0xe1, 0x3fb8}, {0xe2, 0x2780}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3fb9}, {0xe2, 0x1bfb}, {0xe3, 0x00e0}, {0xe0, 0x0dcf},
{0xe1, 0x3fba}, {0xe2, 0x3c00}, {0xe3, 0x0025}, {0xe0, 0x0dcf},
{0xe1, 0x3fbb}, {0xe2, 0x3916}, {0xe3, 0x0012}, {0xe0, 0x0dcf},
{0xe1, 0x3fbc}, {0xe2, 0x3501}, {0xe3, 0x00a1}, {0xe0, 0x0dcf},
{0xe1, 0x3fbd}, {0xe2, 0x1dbe}, {0xe3, 0x008f}, {0xe0, 0x0dcf},
{0xe1, 0x3fbe}, {0xe2, 0x810b}, {0xe3, 0x00f1}, {0xe0, 0x0dcf},
{0xe1, 0x3fbf}, {0xe2, 0x1831}, {0xe3, 0x00df}, {0xe0, 0x0dcf},
{0xe1, 0x0064}, {0xe2, 0x0000}, {0xe0, 0x68c5},
{0xe1, 0x3fa0}, {0xe2, 0x9183}, {0xe0, 0x3bcb},
{0xe1, 0x3fb0}, {0xe2, 0x3f00}, {0xe0, 0x3bcb},
{0xe1, 0x3fa1}, {0xe2, 0x91b3}, {0xe0, 0x3bcb},
{0xe1, 0x3fb1}, {0xe2, 0x3f11}, {0xe0, 0x3bcb},
{0xe1, 0x3fa2}, {0xe2, 0x9216}, {0xe0, 0x3bcb},
{0xe1, 0x3fb2}, {0xe2, 0x3f1e}, {0xe0, 0x3bcb},
{0xe1, 0x3fa3}, {0xe2, 0xe09d}, {0xe0, 0x3bcb},
{0xe1, 0x3fb3}, {0xe2, 0x3f2b}, {0xe0, 0x3bcb},
{0xe1, 0x3fa4}, {0xe2, 0xe0cd}, {0xe0, 0x3bcb},
{0xe1, 0x3fb4}, {0xe2, 0x3f3d}, {0xe0, 0x3bcb},
{0xe1, 0x3fa5}, {0xe2, 0xe130}, {0xe0, 0x3bcb},
{0xe1, 0x3fb5}, {0xe2, 0x3f4b}, {0xe0, 0x3bcb},
{0xe1, 0x3fa6}, {0xe2, 0x859a}, {0xe0, 0x3bcb},
{0xe1, 0x3fb6}, {0xe2, 0x3f59}, {0xe0, 0x3bcb},
{0xe1, 0x3fa7}, {0xe2, 0x94fc}, {0xe0, 0x3bcb},
{0xe1, 0x3fb7}, {0xe2, 0x3f62}, {0xe0, 0x3bcb},
{0xe1, 0x3fa8}, {0xe2, 0x93c9}, {0xe0, 0x3bcb},
{0xe1, 0x3fb8}, {0xe2, 0x3f71}, {0xe0, 0x3bcb},
{0xe1, 0x3fa9}, {0xe2, 0x94f2}, {0xe0, 0x3bcb},
{0xe1, 0x3fb9}, {0xe2, 0x3fa4}, {0xe0, 0x3bcb},
{0xe1, 0x22cc}, {0xe2, 0x0001}, {0xe0, 0x3bcb},
{0xe1, 0x3faa}, {0xe2, 0x823a}, {0xe0, 0x3bcb},
{0xe1, 0x3fba}, {0xe2, 0x023e}, {0xe0, 0x3bcb},
{0xe1, 0x3fab}, {0xe2, 0x831c}, {0xe0, 0x3bcb},
{0xe1, 0x3fbb}, {0xe2, 0x3fb7}, {0xe0, 0x3bcb},
{0xe1, 0x0010}, {0xe2, 0x0001}, {0xe0, 0x6ac9},
{0xe1, 0x0064}, {0xe2, 0x0000}, {0xe0, 0x68c5},
{0xe1, 0x3f00}, {0xe2, 0x26e1}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f01}, {0xe2, 0x1924}, {0xe3, 0x009f}, {0xe0, 0x0dcf},
{0xe1, 0x3f02}, {0xe2, 0x82f5}, {0xe3, 0x0050}, {0xe0, 0x0dcf},
{0xe1, 0x3f03}, {0xe2, 0x26e0}, {0xe3, 0x00df}, {0xe0, 0x0dcf},
{0xe1, 0x3f04}, {0xe2, 0x1bf0}, {0xe3, 0x0072}, {0xe0, 0x0dcf},
{0xe1, 0x3f05}, {0xe2, 0x3400}, {0xe3, 0x0008}, {0xe0, 0x0dcf},
{0xe1, 0x3f06}, {0xe2, 0x198e}, {0xe3, 0x003f}, {0xe0, 0x0dcf},
{0xe1, 0x3f07}, {0xe2, 0x0c20}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f08}, {0xe2, 0x80f5}, {0xe3, 0x00b3}, {0xe0, 0x0dcf},
{0xe1, 0x3f09}, {0xe2, 0x8149}, {0xe3, 0x00b7}, {0xe0, 0x0dcf},
{0xe1, 0x3f0a}, {0xe2, 0x2029}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f0b}, {0xe2, 0x90f5}, {0xe3, 0x00bc}, {0xe0, 0x0dcf},
{0xe1, 0x3f0c}, {0xe2, 0x8101}, {0xe3, 0x00b3}, {0xe0, 0x0dcf},
{0xe1, 0x3f0d}, {0xe2, 0x2029}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f0e}, {0xe2, 0x9101}, {0xe3, 0x00bc}, {0xe0, 0x0dcf},
{0xe1, 0x3f0f}, {0xe2, 0x0c30}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f10}, {0xe2, 0x198e}, {0xe3, 0x009f}, {0xe0, 0x0dcf},
{0xe1, 0x3f11}, {0xe2, 0x9433}, {0xe3, 0x0006}, {0xe0, 0x0dcf},
{0xe1, 0x3f12}, {0xe2, 0x9433}, {0xe3, 0x0016}, {0xe0, 0x0dcf},
{0xe1, 0x3f13}, {0xe2, 0x4001}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f14}, {0xe2, 0x9033}, {0xe3, 0x002a}, {0xe0, 0x0dcf},
{0xe1, 0x3f15}, {0xe2, 0x3527}, {0xe3, 0x0041}, {0xe0, 0x0dcf},
{0xe1, 0x3f16}, {0xe2, 0x3527}, {0xe3, 0x0012}, {0xe0, 0x0dcf},
{0xe1, 0x3f17}, {0xe2, 0x3527}, {0xe3, 0x0070}, {0xe0, 0x0dcf},
{0xe1, 0x3f18}, {0xe2, 0x3c00}, {0xe3, 0x00c5}, {0xe0, 0x0dcf},
{0xe1, 0x3f19}, {0xe2, 0x0c0c}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f1a}, {0xe2, 0x17f2}, {0xe3, 0x00ee}, {0xe0, 0x0dcf},
{0xe1, 0x3f1b}, {0xe2, 0x6000}, {0xe3, 0x00a5}, {0xe0, 0x0dcf},
{0xe1, 0x3f1c}, {0xe2, 0x22fa}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f1d}, {0xe2, 0x6000}, {0xe3, 0x0049}, {0xe0, 0x0dcf},
{0xe1, 0x3f1e}, {0xe2, 0x66e2}, {0xe3, 0x0051}, {0xe0, 0x0dcf},
{0xe1, 0x3f1f}, {0xe2, 0x1bf2}, {0xe3, 0x00c3}, {0xe0, 0x0dcf},
{0xe1, 0x3f20}, {0xe2, 0x26ea}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f21}, {0xe2, 0x1bf2}, {0xe3, 0x00c3}, {0xe0, 0x0dcf},
{0xe1, 0x3f22}, {0xe2, 0x8033}, {0xe3, 0x001a}, {0xe0, 0x0dcf},
{0xe1, 0x3f23}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f24}, {0xe2, 0x8033}, {0xe3, 0x0024}, {0xe0, 0x0dcf},
{0xe1, 0x3f25}, {0xe2, 0x26e2}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f26}, {0xe2, 0x1bf2}, {0xe3, 0x00a0}, {0xe0, 0x0dcf},
{0xe1, 0x3f27}, {0xe2, 0x8033}, {0xe3, 0x000a}, {0xe0, 0x0dcf},
{0xe1, 0x3f28}, {0xe2, 0x2262}, {0xe3, 0x621f}, {0xe0, 0x0dcf},
{0xe1, 0x3f29}, {0xe2, 0x9033}, {0xe3, 0x000a}, {0xe0, 0x0dcf},
{0xe1, 0x3f2a}, {0xe2, 0x8033}, {0xe3, 0x002a}, {0xe0, 0x0dcf},
{0xe1, 0x3f2b}, {0xe2, 0x9033}, {0xe3, 0x001a}, {0xe0, 0x0dcf},
{0xe1, 0x3f2c}, {0xe2, 0x8033}, {0xe3, 0x002a}, {0xe0, 0x0dcf},
{0xe1, 0x3f2d}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f2e}, {0xe2, 0x9033}, {0xe3, 0x002a}, {0xe0, 0x0dcf},
{0xe1, 0x3f2f}, {0xe2, 0x0c08}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f30}, {0xe2, 0x82f5}, {0xe3, 0x0060}, {0xe0, 0x0dcf},
{0xe1, 0x3f31}, {0xe2, 0x2398}, {0xe3, 0x005f}, {0xe0, 0x0dcf},
{0xe1, 0x3f32}, {0xe2, 0x1bf4}, {0xe3, 0x0020}, {0xe0, 0x0dcf},
{0xe1, 0x3f33}, {0xe2, 0x8033}, {0xe3, 0x000a}, {0xe0, 0x0dcf},
{0xe1, 0x3f34}, {0xe2, 0x8033}, {0xe3, 0x0054}, {0xe0, 0x0dcf},
{0xe1, 0x3f35}, {0xe2, 0x26e2}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f36}, {0xe2, 0x1bf3}, {0xe3, 0x00e5}, {0xe0, 0x0dcf},
{0xe1, 0x3f37}, {0xe2, 0x8033}, {0xe3, 0x003a}, {0xe0, 0x0dcf},
{0xe1, 0x3f38}, {0xe2, 0x22e2}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f39}, {0xe2, 0x9033}, {0xe3, 0x003a}, {0xe0, 0x0dcf},
{0xe1, 0x3f3a}, {0xe2, 0x1bf4}, {0xe3, 0x0022}, {0xe0, 0x0dcf},
{0xe1, 0x3f3b}, {0xe2, 0x9433}, {0xe3, 0x0036}, {0xe0, 0x0dcf},
{0xe1, 0x3f3c}, {0xe2, 0x9433}, {0xe3, 0x0046}, {0xe0, 0x0dcf},
{0xe1, 0x3f3d}, {0xe2, 0x1bf4}, {0xe3, 0x002f}, {0xe0, 0x0dcf},
{0xe1, 0x3f3e}, {0xe2, 0x4100}, {0xe3, 0x0014}, {0xe0, 0x0dcf},
{0xe1, 0x3f3f}, {0xe2, 0x9033}, {0xe3, 0x0044}, {0xe0, 0x0dcf},
{0xe1, 0x3f40}, {0xe2, 0x4001}, {0xe3, 0x0044}, {0xe0, 0x0dcf},
{0xe1, 0x3f41}, {0xe2, 0x9033}, {0xe3, 0x0034}, {0xe0, 0x0dcf},
{0xe1, 0x3f42}, {0xe2, 0x3c00}, {0xe3, 0x0075}, {0xe0, 0x0dcf},
{0xe1, 0x3f43}, {0xe2, 0x192f}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f44}, {0xe2, 0x82f5}, {0xe3, 0x0060}, {0xe0, 0x0dcf},
{0xe1, 0x3f45}, {0xe2, 0x2398}, {0xe3, 0x005f}, {0xe0, 0x0dcf},
{0xe1, 0x3f46}, {0xe2, 0x1bf5}, {0xe3, 0x0050}, {0xe0, 0x0dcf},
{0xe1, 0x3f47}, {0xe2, 0x8033}, {0xe3, 0x004a}, {0xe0, 0x0dcf},
{0xe1, 0x3f48}, {0xe2, 0x267a}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f49}, {0xe2, 0x1bf5}, {0xe3, 0x0050}, {0xe0, 0x0dcf},
{0xe1, 0x3f4a}, {0xe2, 0x82f5}, {0xe3, 0x005a}, {0xe0, 0x0dcf},
{0xe1, 0x3f4b}, {0xe2, 0x267a}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f4c}, {0xe2, 0x4001}, {0xe3, 0x006a}, {0xe0, 0x0dcf},
{0xe1, 0x3f4d}, {0xe2, 0x4001}, {0xe3, 0x00f1}, {0xe0, 0x0dcf},
{0xe1, 0x3f4e}, {0xe2, 0x2279}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f4f}, {0xe2, 0x0d04}, {0xe3, 0x007a}, {0xe0, 0x0dcf},
{0xe1, 0x3f50}, {0xe2, 0x3549}, {0xe3, 0x00b1}, {0xe0, 0x0dcf},
{0xe1, 0x3f51}, {0xe2, 0x0900}, {0xe3, 0x0007}, {0xe0, 0x0dcf},
{0xe1, 0x3f52}, {0xe2, 0xa7ff}, {0xe3, 0x00f5}, {0xe0, 0x0dcf},
{0xe1, 0x3f53}, {0xe2, 0xa7ff}, {0xe3, 0x00f5}, {0xe0, 0x0dcf},
{0xe1, 0x3f54}, {0xe2, 0xa7ff}, {0xe3, 0x00f5}, {0xe0, 0x0dcf},
{0xe1, 0x3f55}, {0xe2, 0x3949}, {0xe3, 0x00b0}, {0xe0, 0x0dcf},
{0xe1, 0x3f56}, {0xe2, 0x1984}, {0xe3, 0x003f}, {0xe0, 0x0dcf},
{0xe1, 0x3f57}, {0xe2, 0x82b6}, {0xe3, 0x0061}, {0xe0, 0x0dcf},
{0xe1, 0x3f58}, {0xe2, 0x17f8}, {0xe3, 0x006e}, {0xe0, 0x0dcf},
{0xe1, 0x3f59}, {0xe2, 0x8291}, {0xe3, 0x006a}, {0xe0, 0x0dcf},
{0xe1, 0x3f5a}, {0xe2, 0x602a}, {0xe3, 0x0065}, {0xe0, 0x0dcf},
{0xe1, 0x3f5b}, {0xe2, 0x2084}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f5c}, {0xe2, 0x0d00}, {0xe3, 0x00fc}, {0xe0, 0x0dcf},
{0xe1, 0x3f5d}, {0xe2, 0x0d00}, {0xe3, 0x00eb}, {0xe0, 0x0dcf},
{0xe1, 0x3f5e}, {0xe2, 0x2058}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f5f}, {0xe2, 0x1067}, {0xe3, 0x00be}, {0xe0, 0x0dcf},
{0xe1, 0x3f60}, {0xe2, 0x1073}, {0xe3, 0x0087}, {0xe0, 0x0dcf},
{0xe1, 0x3f61}, {0xe2, 0x1047}, {0xe3, 0x00a9}, {0xe0, 0x0dcf},
{0xe1, 0x3f62}, {0xe2, 0x0e5b}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f63}, {0xe2, 0x2262}, {0xe3, 0x009f}, {0xe0, 0x0dcf},
{0xe1, 0x3f64}, {0xe2, 0x902f}, {0xe3, 0x009f}, {0xe0, 0x0dcf},
{0xe1, 0x3f65}, {0xe2, 0x902f}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f66}, {0xe2, 0x1c95}, {0xe3, 0x00cf}, {0xe0, 0x0dcf},
{0xe1, 0x3f67}, {0xe2, 0x1c50}, {0xe3, 0x00cf}, {0xe0, 0x0dcf},
{0xe1, 0x3f68}, {0xe2, 0x0f22}, {0xe3, 0x00ff}, {0xe0, 0x0dcf},
{0xe1, 0x3f69}, {0xe2, 0x802f}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f6a}, {0xe2, 0x0d00}, {0xe3, 0x005f}, {0xe0, 0x0dcf},
{0xe1, 0x3f6b}, {0xe2, 0x4000}, {0xe3, 0x0004}, {0xe0, 0x0dcf},
{0xe1, 0x3f6c}, {0xe2, 0x060a}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f6d}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f6e}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f6f}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f70}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f71}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f72}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f73}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f74}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f75}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f76}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f77}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f78}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f79}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f7a}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f7b}, {0xe2, 0x0712}, {0xe3, 0x0000}, {0xe0, 0x0dcf},
{0xe1, 0x3f7c}, {0xe2, 0x802f}, {0xe3, 0x00aa}, {0xe0, 0x0dcf},
{0xe1, 0x3f7d}, {0xe2, 0x2b3a}, {0xe3, 0x00b4}, {0xe0, 0x0dcf},
{0xe1, 0x3f7e}, {0xe2, 0x2262}, {0xe3, 0x001f}, {0xe0, 0x0dcf},
{0xe1, 0x3f7f}, {0xe2, 0x0d00}, {0xe3, 0x009a}, {0xe0, 0x0dcf},
{0xe1, 0x3f80}, {0xe2, 0x1023}, {0xe3, 0x0061}, {0xe0, 0x0dcf},
{0xe1, 0x3f81}, {0xe2, 0x2027}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f82}, {0xe2, 0x428b}, {0xe3, 0x00e6}, {0xe0, 0x0dcf},
{0xe1, 0x3f83}, {0xe2, 0x2024}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x3f84}, {0xe2, 0x82b7}, {0xe3, 0x0084}, {0xe0, 0x0dcf},
{0xe1, 0x3f85}, {0xe2, 0x2b24}, {0xe3, 0x0078}, {0xe0, 0x0dcf},
{0xe1, 0x3f86}, {0xe2, 0x92b7}, {0xe3, 0x008a}, {0xe0, 0x0dcf},
{0xe1, 0x3f87}, {0xe2, 0x1a20}, {0xe3, 0x007f}, {0xe0, 0x0dcf},
{0xe1, 0x3f88}, {0xe2, 0x47ff}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f89}, {0xe2, 0x92b5}, {0xe3, 0x00fa}, {0xe0, 0x0dcf},
{0xe1, 0x3f8a}, {0xe2, 0x356d}, {0xe3, 0x00b1}, {0xe0, 0x0dcf},
{0xe1, 0x3f8b}, {0xe2, 0x19e4}, {0xe3, 0x000f}, {0xe0, 0x0dcf},
{0xe1, 0x0064}, {0xe2, 0x0000}, {0xe0, 0x68c5},
{0xe1, 0x3fa0}, {0xe2, 0x9248}, {0xe0, 0x3bcb},
{0xe1, 0x3fb0}, {0xe2, 0x3f00}, {0xe0, 0x3bcb},
{0xe1, 0x3fa1}, {0xe2, 0x98e2}, {0xe0, 0x3bcb},
{0xe1, 0x3fb1}, {0xe2, 0x3f02}, {0xe0, 0x3bcb},
{0xe1, 0x3fa2}, {0xe2, 0x92f0}, {0xe0, 0x3bcb},
{0xe1, 0x3fb2}, {0xe2, 0x3f11}, {0xe0, 0x3bcb},
{0xe1, 0x3fa3}, {0xe2, 0x9842}, {0xe0, 0x3bcb},
{0xe1, 0x3fb3}, {0xe2, 0x3f44}, {0xe0, 0x3bcb},
{0xe1, 0x0335}, {0xe2, 0x0001}, {0xe0, 0x3bcb},
{0xe1, 0x3fa4}, {0xe2, 0xa1d6}, {0xe0, 0x3bcb},
{0xe1, 0x3fb4}, {0xe2, 0x3f57}, {0xe0, 0x3bcb},
{0xe1, 0x3fa5}, {0xe2, 0x9e3f}, {0xe0, 0x3bcb},
{0xe1, 0x3fb5}, {0xe2, 0x3f88}, {0xe0, 0x3bcb},
{0xe1, 0x0010}, {0xe2, 0x0000}, {0xe0, 0x6ac9}
};
#define RT5670_DSP_PATCH_NUM \
(sizeof(rt5670_dsp_patch) / sizeof(rt5670_dsp_patch[0]))
/* DSP init */
static unsigned short rt5670_dsp_init[][2] = {
{0x2260, 0x30d9}, {0x2261, 0x30d9}, {0x2289, 0x7fff}, {0x2290, 0x7fff},
{0x2288, 0x0002}, {0x22b2, 0x0002}, {0x2295, 0x0001}, {0x22b3, 0x0001},
{0x22d7, 0x0008}, {0x22d8, 0x0009}, {0x22d9, 0x0000}, {0x22da, 0x0001},
{0x22fd, 0x009e}, {0x22c1, 0x1006}, {0x22c2, 0x1006}, {0x22c3, 0x1007},
{0x22c4, 0x1007}
};
#define RT5670_DSP_INIT_NUM \
(sizeof(rt5670_dsp_init) / sizeof(rt5670_dsp_init[0]))
/* MCLK rate */
static unsigned short rt5670_dsp_4096000[][2] = {
{0x226c, 0x000c}, {0x226d, 0x000c}, {0x226e, 0x0022},
};
#define RT5670_DSP_4096000_NUM \
(sizeof(rt5670_dsp_4096000) / sizeof(rt5670_dsp_4096000[0]))
static unsigned short rt5670_dsp_12288000[][2] = {
{0x226c, 0x000c}, {0x226d, 0x000c}, {0x226e, 0x0026},
};
#define RT5670_DSP_12288000_NUM \
(sizeof(rt5670_dsp_12288000) / sizeof(rt5670_dsp_12288000[0]))
static unsigned short rt5670_dsp_11289600[][2] = {
{0x226c, 0x0031}, {0x226d, 0x0050}, {0x226e, 0x0009},
};
#define RT5670_DSP_11289600_NUM \
(sizeof(rt5670_dsp_11289600) / sizeof(rt5670_dsp_11289600[0]))
static unsigned short rt5670_dsp_24576000[][2] = {
{0x226c, 0x000c}, {0x226d, 0x000c}, {0x226e, 0x002c},
};
#define RT5670_DSP_24576000_NUM \
(sizeof(rt5670_dsp_24576000) / sizeof(rt5670_dsp_24576000[0]))
/* sample rate */
static unsigned short rt5670_dsp_48_441[][2] = {
{0x22f2, 0x0058}, {0x2301, 0x0016}
};
#define RT5670_DSP_48_441_NUM \
(sizeof(rt5670_dsp_48_441) / sizeof(rt5670_dsp_48_441[0]))
static unsigned short rt5670_dsp_24[][2] = {
{0x22f2, 0x0058}, {0x2301, 0x0004}
};
#define RT5670_DSP_24_NUM (sizeof(rt5670_dsp_24) / sizeof(rt5670_dsp_24[0]))
static unsigned short rt5670_dsp_16[][2] = {
{0x22f2, 0x004c}, {0x2301, 0x0002}
};
#define RT5670_DSP_16_NUM (sizeof(rt5670_dsp_16) / sizeof(rt5670_dsp_16[0]))
static unsigned short rt5670_dsp_8[][2] = {
{0x22f2, 0x004c}, {0x2301, 0x0000}
};
#define RT5670_DSP_8_NUM (sizeof(rt5670_dsp_8) / sizeof(rt5670_dsp_8[0]))
/* DSP mode */
static unsigned short rt5670_dsp_ns[][2] = {
{0x22f8, 0x8005}, {0x2375, 0x7ff0}, {0x2376, 0x7990}, {0x2377, 0x7332},
{0x2388, 0x7fff}, {0x2389, 0x6000}, {0x238a, 0x0000}, {0x238b, 0x1000},
{0x238c, 0x1000}, {0x23a1, 0x2000}, {0x2303, 0x0200}, {0x2304, 0x0032},
{0x2305, 0x0000}, {0x230c, 0x0200}, {0x22fb, 0x0000}
};
#define RT5670_DSP_NS_NUM \
(sizeof(rt5670_dsp_ns) / sizeof(rt5670_dsp_ns[0]))
static unsigned short rt5670_dsp_aec[][2] = {
{0x22f8, 0x8003}, {0x232f, 0x00d0}, {0x2355, 0x2666}, {0x2356, 0x2666},
{0x2357, 0x2666}, {0x2358, 0x6666}, {0x2359, 0x6666}, {0x235a, 0x6666},
{0x235b, 0x7fff}, {0x235c, 0x7fff}, {0x235d, 0x7fff}, {0x235e, 0x7fff},
{0x235f, 0x7fff}, {0x2360, 0x7fff}, {0x2361, 0x7fff}, {0x2362, 0x1000},
{0x2367, 0x0007}, {0x2368, 0x4000}, {0x2369, 0x0008}, {0x236a, 0x2000},
{0x236b, 0x0009}, {0x236c, 0x003c}, {0x236d, 0x0000}, {0x236f, 0x2000},
{0x2370, 0x0008}, {0x2371, 0x000a}, {0x2373, 0x0000}, {0x2374, 0x7fff},
{0x2375, 0x7ff0}, {0x2376, 0x7990}, {0x2377, 0x7332}, {0x2379, 0x1000},
{0x237a, 0x1000}, {0x2388, 0x7fff}, {0x2389, 0x6000}, {0x238a, 0x4000},
{0x238b, 0x1000}, {0x238c, 0x1000}, {0x2398, 0x4668}, {0x23a1, 0x2000},
{0x23a3, 0x4000}, {0x23ad, 0x2000}, {0x23ae, 0x2000}, {0x23af, 0x2000},
{0x23b4, 0x2000}, {0x23b5, 0x2000}, {0x23b6, 0x2000}, {0x23bb, 0x6000},
{0x2303, 0x0710}, {0x2304, 0x0332}, {0x230c, 0x0200}, {0x230d, 0x0080},
{0x2310, 0x0010}, {0x22fb, 0x0000}
};
#define RT5670_DSP_AEC_NUM \
(sizeof(rt5670_dsp_aec) / sizeof(rt5670_dsp_aec[0]))
static unsigned short rt5670_dsp_vt[][2] = {
{0x22f8, 0x8003}, {0x2371, 0x000a}, {0x2373, 0x0000}, {0x2374, 0x7fff},
{0x2375, 0x7ff0}, {0x2376, 0x7990}, {0x2377, 0x7332}, {0x2379, 0x1000},
{0x237a, 0x1000}, {0x2388, 0x7fff}, {0x2389, 0x6000}, {0x238b, 0x1000},
{0x238c, 0x1000}, {0x23a1, 0x2000}, {0x2304, 0x0332}, {0x230c, 0x0200},
{0x22fb, 0x0000}
};
#define RT5670_DSP_VT_NUM (sizeof(rt5670_dsp_vt) / sizeof(rt5670_dsp_vt[0]))
static unsigned short rt5670_dsp_vr[][2] = {
{0x22f8, 0x8003}, {0x2304, 0x0332}, {0x2305, 0x0000}, {0x2309, 0x0400},
{0x230c, 0x0200}, {0x230d, 0x0080}, {0x2310, 0x0004}, {0x232f, 0x0100},
{0x2371, 0x000a}, {0x2373, 0x3000}, {0x2374, 0x5000}, {0x2375, 0x7ff0},
{0x2376, 0x7990}, {0x2377, 0x7332}, {0x2379, 0x1000}, {0x237a, 0x1000},
{0x2386, 0x0200}, {0x2388, 0x4000}, {0x2389, 0x4000}, {0x238a, 0x0000},
{0x238b, 0x2000}, {0x238c, 0x1800}, {0x239b, 0x0000}, {0x239c, 0x0a00},
{0x239d, 0x0000}, {0x239e, 0x7fff}, {0x239f, 0x0001}, {0x23a1, 0x3000},
{0x23a2, 0x1000}, {0x23ad, 0x0000}, {0x23ae, 0x0000}, {0x23af, 0x0000},
{0x23c4, 0x2000}, {0x23b0, 0x0000}, {0x23b1, 0x0000}, {0x23b2, 0x0000},
{0x23b3, 0x0000}, {0x23b4, 0x0000}, {0x23b5, 0x0000}, {0x23b6, 0x0000},
{0x23b7, 0x0000}, {0x23b8, 0x0000}, {0x23b9, 0x0000}, {0x23ba, 0x0000},
{0x23bb, 0x0000}, {0x22fb, 0x0000}
};
#define RT5670_DSP_VR_NUM (sizeof(rt5670_dsp_vr) / sizeof(rt5670_dsp_vr[0]))
static unsigned short rt5670_dsp_ffp_ns[][2] = {
{0x22f8, 0x8003}, {0x2304, 0x8332}, {0x2371, 0x000a}, {0x2373, 0x0000},
{0x2374, 0x7fff}, {0x2379, 0x1800}, {0x237a, 0x1800}, {0x230c, 0x0200},
{0x23a2, 0x1000}, {0x2388, 0x7000}, {0x238b, 0x2000}, {0x238c, 0x2000},
{0x23a8, 0x2000}, {0x23a9, 0x4000}, {0x23aa, 0x0100}, {0x23ab, 0x7800},
{0x22fb, 0x0000}
};
#define RT5670_DSP_FFP_NS_NUM \
(sizeof(rt5670_dsp_ffp_ns) / sizeof(rt5670_dsp_ffp_ns[0]))
static unsigned short rt5670_dsp_48k_sto_ffp[][2] = {
{0x22c1, 0x1025}, {0x22c2, 0x1026}, {0x22f8, 0x8004}, {0x22ea, 0x0001},
{0x230c, 0x0100}, {0x230d, 0x0100}, {0x2301, 0x0010}, {0x2303, 0x0200},
{0x2304, 0x8000}, {0x2305, 0x0000}, {0x2388, 0x6500}, {0x238b, 0x4000},
{0x238c, 0x4000}, {0x23a9, 0x2000}, {0x23aa, 0x0200}, {0x23ab, 0x7c00},
{0x22fb, 0x0000}
};
#define RT5670_DSP_48K_STO_FFP_NUM \
(sizeof(rt5670_dsp_48k_sto_ffp) / sizeof(rt5670_dsp_48k_sto_ffp[0]))
static unsigned short rt5670_dsp_2mic_handset[][2] = {
{0x22f8, 0x8002}, {0x2301, 0x0002}, {0x2302, 0x0002}, {0x2303, 0x0710},
{0x2304, 0x4332}, {0x2305, 0x206c}, {0x236e, 0x0000}, {0x236f, 0x0001},
{0x237e, 0x0001}, {0x237f, 0x3800}, {0x2380, 0x3000}, {0x2381, 0x0005},
{0x2382, 0x0040}, {0x2383, 0x7fff}, {0x2388, 0x2c00}, {0x2389, 0x2800},
{0x238b, 0x1800}, {0x238c, 0x1800}, {0x238f, 0x2000}, {0x239b, 0x0002},
{0x239c, 0x0a00}, {0x239f, 0x0001}, {0x230c, 0x0200}, {0x22fb, 0x0000}
};
#define RT5670_DSP_2MIC_HANDSET_NUM \
(sizeof(rt5670_dsp_2mic_handset) / sizeof(rt5670_dsp_2mic_handset[0]))
static unsigned short rt5670_dsp_2mic_handsfree[][2] = {
{0x22f8, 0x8003}, {0x2371, 0x000a}, {0x2373, 0x0000}, {0x2374, 0x7fff},
{0x2375, 0x7ff0}, {0x2376, 0x7990}, {0x2377, 0x7332}, {0x2379, 0x1000},
{0x237a, 0x1000}, {0x2388, 0x7fff}, {0x2389, 0x6000}, {0x238b, 0x1000},
{0x238c, 0x1000}, {0x23a1, 0x2000}, {0x2304, 0x0332}, {0x230c, 0x0200},
{0x22fb, 0x0000}
};
#define RT5670_DSP_2MIC_HANDSFREE_NUM \
(sizeof(rt5670_dsp_2mic_handsfree) / \
sizeof(rt5670_dsp_2mic_handsfree[0]))
static unsigned short rt5670_dsp_aec_handsfree[][2] = {
{0x22f8, 0x8003}, {0x232f, 0x00d0}, {0x2355, 0x2666}, {0x2356, 0x2666},
{0x2357, 0x2666}, {0x2358, 0x6666}, {0x2359, 0x6666}, {0x235a, 0x6666},
{0x235b, 0x7fff}, {0x235c, 0x7fff}, {0x235d, 0x7fff}, {0x235e, 0x7fff},
{0x235f, 0x7fff}, {0x2360, 0x7fff}, {0x2361, 0x7fff}, {0x2362, 0x1000},
{0x2367, 0x0007}, {0x2368, 0x4000}, {0x2369, 0x0008}, {0x236a, 0x2000},
{0x236b, 0x0009}, {0x236c, 0x003c}, {0x236d, 0x0000}, {0x236f, 0x2000},
{0x2370, 0x0008}, {0x2371, 0x000a}, {0x2373, 0x0000}, {0x2374, 0x7fff},
{0x2375, 0x7ff0}, {0x2376, 0x7990}, {0x2377, 0x7332}, {0x2379, 0x1000},
{0x237a, 0x1000}, {0x2388, 0x7fff}, {0x2389, 0x6000}, {0x238a, 0x4000},
{0x238b, 0x1000}, {0x238c, 0x1000}, {0x2398, 0x4668}, {0x23a1, 0x2000},
{0x23a3, 0x4000}, {0x23ad, 0x2000}, {0x23ae, 0x2000}, {0x23af, 0x2000},
{0x23b4, 0x2000}, {0x23b5, 0x2000}, {0x23b6, 0x2000}, {0x23bb, 0x6000},
{0x2303, 0x0710}, {0x2304, 0x0332}, {0x230c, 0x0200}, {0x230d, 0x0080},
{0x2310, 0x0010}, {0x22fb, 0x0000}
};
#define RT5670_DSP_AEC_HANDSFREE_NUM \
(sizeof(rt5670_dsp_aec_handsfree) / sizeof(rt5670_dsp_aec_handsfree[0]))
/**
* rt5670_dsp_done - Wait until DSP is ready.
* @codec: SoC Audio Codec device.
*
* To check voice DSP status and confirm it's ready for next work.
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_done(struct snd_soc_codec *codec)
{
unsigned int count = 0, dsp_val;
dsp_val = snd_soc_read(codec, RT5670_DSP_CTRL1);
while (dsp_val & RT5670_DSP_BUSY_MASK) {
if (count > 10)
return -EBUSY;
dsp_val = snd_soc_read(codec, RT5670_DSP_CTRL1);
count++;
}
return 0;
}
/**
* rt5670_dsp_write - Write DSP register.
* @codec: SoC audio codec device.
* @param: DSP parameters.
*
* Modify voice DSP register for sound effect. The DSP can be controlled
* through DSP command format (0xfc), addr (0xc4), data (0xc5) and cmd (0xc6)
* register. It has to wait until the DSP is ready.
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_write(struct snd_soc_codec *codec,
unsigned int addr, unsigned int data)
{
unsigned int dsp_val;
int ret;
ret = snd_soc_write(codec, RT5670_DSP_CTRL2, addr);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
goto err;
}
ret = snd_soc_write(codec, RT5670_DSP_CTRL3, data);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP data reg: %d\n", ret);
goto err;
}
dsp_val = RT5670_DSP_I2C_AL_16 | RT5670_DSP_DL_2 |
RT5670_DSP_CMD_MW | DSP_CLK_RATE | RT5670_DSP_CMD_EN;
ret = snd_soc_write(codec, RT5670_DSP_CTRL1, dsp_val);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
goto err;
}
ret = rt5670_dsp_done(codec);
if (ret < 0) {
dev_err(codec->dev, "DSP is busy: %d\n", ret);
goto err;
}
return 0;
err:
return ret;
}
/**
* rt5670_dsp_read - Read DSP register.
* @codec: SoC audio codec device.
* @reg: DSP register index.
*
* Read DSP setting value from voice DSP. The DSP can be controlled
* through DSP addr (0xc4), data (0xc5) and cmd (0xc6) register. Each
* command has to wait until the DSP is ready.
*
* Returns DSP register value or negative error code.
*/
static unsigned int rt5670_dsp_read(
struct snd_soc_codec *codec, unsigned int reg)
{
unsigned int value;
unsigned int dsp_val;
int ret = 0;
ret = rt5670_dsp_done(codec);
if (ret < 0) {
dev_err(codec->dev, "DSP is busy: %d\n", ret);
goto err;
}
ret = snd_soc_write(codec, RT5670_DSP_CTRL2, reg);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
goto err;
}
dsp_val = RT5670_DSP_I2C_AL_16 | RT5670_DSP_DL_0 | RT5670_DSP_RW_MASK |
RT5670_DSP_CMD_MR | DSP_CLK_RATE | RT5670_DSP_CMD_EN;
ret = snd_soc_write(codec, RT5670_DSP_CTRL1, dsp_val);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
goto err;
}
ret = rt5670_dsp_done(codec);
if (ret < 0) {
dev_err(codec->dev, "DSP is busy: %d\n", ret);
goto err;
}
ret = snd_soc_write(codec, RT5670_DSP_CTRL2, 0x26);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
goto err;
}
dsp_val = RT5670_DSP_DL_1 | RT5670_DSP_CMD_RR | RT5670_DSP_RW_MASK |
DSP_CLK_RATE | RT5670_DSP_CMD_EN;
ret = snd_soc_write(codec, RT5670_DSP_CTRL1, dsp_val);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
goto err;
}
ret = rt5670_dsp_done(codec);
if (ret < 0) {
dev_err(codec->dev, "DSP is busy: %d\n", ret);
goto err;
}
ret = snd_soc_write(codec, RT5670_DSP_CTRL2, 0x25);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP addr reg: %d\n", ret);
goto err;
}
dsp_val = RT5670_DSP_DL_1 | RT5670_DSP_CMD_RR | RT5670_DSP_RW_MASK |
DSP_CLK_RATE | RT5670_DSP_CMD_EN;
ret = snd_soc_write(codec, RT5670_DSP_CTRL1, dsp_val);
if (ret < 0) {
dev_err(codec->dev, "Failed to write DSP cmd reg: %d\n", ret);
goto err;
}
ret = rt5670_dsp_done(codec);
if (ret < 0) {
dev_err(codec->dev, "DSP is busy: %d\n", ret);
goto err;
}
ret = snd_soc_read(codec, RT5670_DSP_CTRL5);
if (ret < 0) {
dev_err(codec->dev, "Failed to read DSP data reg: %d\n", ret);
goto err;
}
value = ret;
return value;
err:
return ret;
}
static int rt5670_dsp_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = rt5670->dsp_sw;
return 0;
}
static int rt5670_dsp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
if (rt5670->dsp_sw != ucontrol->value.integer.value[0])
rt5670->dsp_sw = ucontrol->value.integer.value[0];
return 0;
}
/* DSP Path Control 1 */
static const char * const rt5670_src_rxdp_mode[] = {
"Normal", "Divided by 3"
};
static const SOC_ENUM_SINGLE_DECL(
rt5670_src_rxdp_enum, RT5670_DSP_PATH1,
RT5670_RXDP_SRC_SFT, rt5670_src_rxdp_mode);
static const char * const rt5670_src_txdp_mode[] = {
"Normal", "Multiplied by 3"
};
static const SOC_ENUM_SINGLE_DECL(
rt5670_src_txdp_enum, RT5670_DSP_PATH1,
RT5670_TXDP_SRC_SFT, rt5670_src_txdp_mode);
/* Sound Effect */
static const char *rt5670_dsp_mode[] = {
"Disable", "NS", "AEC", "VT", "VR", "FFP+NS", "48K-stereo+FFP",
"2MIC Handset", "2MIC Handsfree", "AEC Handsfree"
};
static const SOC_ENUM_SINGLE_DECL(rt5670_dsp_enum, 0, 0,
rt5670_dsp_mode);
static const struct snd_kcontrol_new rt5670_dsp_snd_controls[] = {
/* AEC */
SOC_ENUM_EXT("DSP Function Switch", rt5670_dsp_enum,
rt5670_dsp_get, rt5670_dsp_put),
};
/**
* rt5670_dsp_conf - Set DSP basic setting.
*
* @codec: SoC audio codec device.
*
* Set parameters of basic setting to DSP.
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_conf(struct snd_soc_codec *codec)
{
int ret, i;
for (i = 0; i < RT5670_DSP_INIT_NUM; i++) {
ret = rt5670_dsp_write(codec, rt5670_dsp_init[i][0],
rt5670_dsp_init[i][1]);
if (ret < 0) {
dev_err(codec->dev, "Fail to config Dsp: %d\n", ret);
goto conf_err;
}
}
return 0;
conf_err:
return ret;
}
/**
* rt5670_dsp_rate - Set DSP rate setting.
*
* @codec: SoC audio codec device.
* @sys_clk: System clock.
* @srate: Sampling rate.
*
* Set parameters of system clock and sampling rate to DSP.
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_rate(struct snd_soc_codec *codec, int sys_clk,
int srate)
{
int ret, i, tab_num;
unsigned short (*rate_tab)[2];
dev_dbg(codec->dev,"rt5670_dsp_rate sys:%d srate:%d\n", sys_clk, srate);
switch(sys_clk) {
case 4096000:
rate_tab = rt5670_dsp_4096000;
tab_num = RT5670_DSP_4096000_NUM;
break;
case 11289600:
rate_tab = rt5670_dsp_11289600;
tab_num = RT5670_DSP_11289600_NUM;
break;
case 12288000:
rate_tab = rt5670_dsp_12288000;
tab_num = RT5670_DSP_12288000_NUM;
break;
case 24576000:
rate_tab = rt5670_dsp_24576000;
tab_num = RT5670_DSP_24576000_NUM;
break;
default:
return -EINVAL;
break;
}
for (i = 0; i < tab_num; i++) {
ret = rt5670_dsp_write(codec, rate_tab[i][0], rate_tab[i][1]);
if (ret < 0)
goto rate_err;
}
switch(srate) {
case 8000:
rate_tab = rt5670_dsp_8;
tab_num = RT5670_DSP_8_NUM;
break;
case 16000:
rate_tab = rt5670_dsp_16;
tab_num = RT5670_DSP_16_NUM;
break;
case 24000:
rate_tab = rt5670_dsp_24;
tab_num = RT5670_DSP_24_NUM;
break;
case 44100:
case 48000:
rate_tab = rt5670_dsp_48_441;
tab_num = RT5670_DSP_48_441_NUM;
break;
default:
return -EINVAL;
break;
}
for (i = 0; i < tab_num; i++) {
ret = rt5670_dsp_write(codec, rate_tab[i][0], rate_tab[i][1]);
if (ret < 0)
goto rate_err;
}
return 0;
rate_err:
dev_err(codec->dev, "Fail to set rate parameters: %d\n", ret);
return ret;
}
/**
* rt5670_dsp_do_patch - Write DSP patch code.
*
* @codec: SoC audio codec device.
*
* Write patch codes to DSP.
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_do_patch(struct snd_soc_codec *codec)
{
int ret, i;
for (i = 0; i < RT5670_DSP_PATCH_NUM; i++) {
ret = snd_soc_write(codec, rt5670_dsp_patch[i][0],
rt5670_dsp_patch[i][1]);
if (ret < 0)
goto patch_err;
if (rt5670_dsp_patch[i][0] == 0xe0) {
ret = rt5670_dsp_done(codec);
if (ret < 0) {
dev_err(codec->dev, "DSP is busy: %d\n", ret);
goto patch_err;
}
}
}
return 0;
patch_err:
return ret;
}
/**
* rt5670_dsp_set_mode - Set DSP mode parameters.
*
* @codec: SoC audio codec device.
* @mode: DSP mode.
*
* Set parameters of mode to DSP.
* There are three modes which includes " mic AEC + NS + FENS",
* "HFBF" and "Far-field pickup".
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_set_mode(struct snd_soc_codec *codec, int mode)
{
int ret, i, tab_num;
unsigned short (*mode_tab)[2];
switch (mode) {
case RT5670_DSP_NS:
dev_info(codec->dev, "NS\n");
mode_tab = rt5670_dsp_ns;
tab_num = RT5670_DSP_NS_NUM;
break;
case RT5670_DSP_AEC:
dev_info(codec->dev, "AEC\n");
mode_tab = rt5670_dsp_aec;
tab_num = RT5670_DSP_AEC_NUM;
break;
case RT5670_DSP_VT:
dev_info(codec->dev, "VT\n");
mode_tab = rt5670_dsp_vt;
tab_num = RT5670_DSP_VT_NUM;
break;
case RT5670_DSP_VR:
dev_info(codec->dev, "VR\n");
mode_tab = rt5670_dsp_vr;
tab_num = RT5670_DSP_VR_NUM;
break;
case RT5670_DSP_FFP_NS:
dev_info(codec->dev, "FFP_NS\n");
mode_tab = rt5670_dsp_ffp_ns;
tab_num = RT5670_DSP_FFP_NS_NUM;
break;
case RT5670_DSP_48K_STO_FFP:
dev_info(codec->dev, "48K_STO_FFP\n");
mode_tab = rt5670_dsp_48k_sto_ffp;
tab_num = RT5670_DSP_48K_STO_FFP_NUM;
break;
case RT5670_DSP_2MIC_HANDSET:
dev_info(codec->dev, "2MIC_HANDSET\n");
mode_tab = rt5670_dsp_2mic_handset;
tab_num = RT5670_DSP_2MIC_HANDSET_NUM;
break;
case RT5670_DSP_2MIC_HANDSFREE:
dev_info(codec->dev, "2MIC_HANDSFREE\n");
mode_tab = rt5670_dsp_2mic_handsfree;
tab_num = RT5670_DSP_2MIC_HANDSFREE_NUM;
break;
case RT5670_DSP_AEC_HANDSFREE:
dev_info(codec->dev, "AEC_HANDSFREE\n");
mode_tab = rt5670_dsp_aec_handsfree;
tab_num = RT5670_DSP_AEC_HANDSFREE_NUM;
break;
case RT5670_DSP_DIS:
default:
dev_info(codec->dev, "Disable\n");
return 0;
}
for (i = 0; i < tab_num; i++) {
ret = rt5670_dsp_write(codec, mode_tab[i][0], mode_tab[i][1]);
if (ret < 0)
goto mode_err;
}
return 0;
mode_err:
dev_err(codec->dev, "Fail to set mode %d parameters: %d\n", mode, ret);
return ret;
}
/**
* rt5670_dsp_snd_effect - Set DSP sound effect.
*
* Set parameters of sound effect to DSP.
*
* Returns 0 for success or negative error code.
*/
static int rt5670_dsp_snd_effect(struct snd_soc_codec *codec)
{
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
int ret;
snd_soc_update_bits(codec, RT5670_DIG_MISC, RT5670_RST_DSP,
RT5670_RST_DSP);
snd_soc_update_bits(codec, RT5670_DIG_MISC, RT5670_RST_DSP, 0);
mdelay(10);
/* Expend 1.6 seconds
ret = rt5670_dsp_do_patch(codec);
if (ret < 0)
goto effect_err;
*/
ret = rt5670_dsp_rate(codec,
rt5670->sysclk ?
rt5670->sysclk : 11289600,
rt5670->lrck[rt5670->aif_pu] ?
rt5670->lrck[rt5670->aif_pu] : 44100);
if (ret < 0)
goto effect_err;
ret = rt5670_dsp_conf(codec);
if (ret < 0)
goto effect_err;
ret = rt5670_dsp_set_mode(codec, rt5670->dsp_sw);
if (ret < 0)
goto effect_err;
return 0;
effect_err:
return ret;
}
static int rt5670_dsp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_codec *codec = w->codec;
switch (event) {
case SND_SOC_DAPM_POST_PMD:
dev_dbg(codec->dev, "%s(): PMD\n", __func__);
rt5670_dsp_write(codec, 0x22f9, 1);
break;
case SND_SOC_DAPM_POST_PMU:
dev_dbg(codec->dev, "%s(): PMU\n", __func__);
rt5670_dsp_snd_effect(codec);
break;
default:
return 0;
}
return 0;
}
static const struct snd_soc_dapm_widget rt5670_dsp_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY_S("Voice DSP", 1, SND_SOC_NOPM,
0, 0, rt5670_dsp_event,
SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA("DSP Downstream", SND_SOC_NOPM,
0, 0, NULL, 0),
SND_SOC_DAPM_PGA("DSP Upstream", SND_SOC_NOPM,
0, 0, NULL, 0),
};
static const struct snd_soc_dapm_route rt5670_dsp_dapm_routes[] = {
{"DSP Downstream", NULL, "Voice DSP"},
{"DSP Downstream", NULL, "RxDP Mux"},
{"DSP Upstream", NULL, "Voice DSP"},
{"DSP Upstream", NULL, "8CH TDM Data"},
{"DSP DL Mux", "DSP", "DSP Downstream"},
{"DSP UL Mux", "DSP", "DSP Upstream"},
};
/**
* rt5670_dsp_show - Dump DSP registers.
* @dev: codec device.
* @attr: device attribute.
* @buf: buffer for display.
*
* To show non-zero values of all DSP registers.
*
* Returns buffer length.
*/
static ssize_t rt5670_dsp_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct rt5670_priv *rt5670 = i2c_get_clientdata(client);
struct snd_soc_codec *codec = rt5670->codec;
unsigned short (*rt5670_dsp_tab)[2];
unsigned int val;
int cnt = 0, i, tab_num;
switch (rt5670->dsp_sw) {
case RT5670_DSP_NS:
cnt += sprintf(buf, "[ RT5642 DSP 'NS' ]\n");
rt5670_dsp_tab = rt5670_dsp_ns;
tab_num = RT5670_DSP_NS_NUM;
break;
case RT5670_DSP_AEC:
cnt += sprintf(buf, "[ RT5642 DSP 'AEC' ]\n");
rt5670_dsp_tab = rt5670_dsp_aec;
tab_num = RT5670_DSP_AEC_NUM;
break;
case RT5670_DSP_VT:
cnt += sprintf(buf, "[ RT5642 DSP 'VT' ]\n");
rt5670_dsp_tab = rt5670_dsp_vt;
tab_num = RT5670_DSP_VT_NUM;
break;
case RT5670_DSP_VR:
cnt += sprintf(buf, "[ RT5642 DSP 'VR' ]\n");
rt5670_dsp_tab = rt5670_dsp_vr;
tab_num = RT5670_DSP_VR_NUM;
break;
case RT5670_DSP_FFP_NS:
cnt += sprintf(buf, "[ RT5642 DSP 'FFP_NS' ]\n");
rt5670_dsp_tab = rt5670_dsp_ffp_ns;
tab_num = RT5670_DSP_FFP_NS_NUM;
break;
case RT5670_DSP_48K_STO_FFP:
cnt += sprintf(buf, "[ RT5642 DSP '48K_STO_FFP' ]\n");
rt5670_dsp_tab = rt5670_dsp_48k_sto_ffp;
tab_num = RT5670_DSP_48K_STO_FFP_NUM;
break;
case RT5670_DSP_2MIC_HANDSET:
cnt += sprintf(buf, "[ RT5642 DSP '2MIC_HANDSET' ]\n");
rt5670_dsp_tab = rt5670_dsp_2mic_handset;
tab_num = RT5670_DSP_2MIC_HANDSET_NUM;
break;
case RT5670_DSP_2MIC_HANDSFREE:
cnt += sprintf(buf, "[ RT5642 DSP '2MIC_HANDSFREE' ]\n");
rt5670_dsp_tab = rt5670_dsp_2mic_handsfree;
tab_num = RT5670_DSP_2MIC_HANDSFREE_NUM;
break;
case RT5670_DSP_AEC_HANDSFREE:
cnt += sprintf(buf, "[ RT5642 DSP 'AEC_HANDSFREE' ]\n");
rt5670_dsp_tab = rt5670_dsp_aec_handsfree;
tab_num = RT5670_DSP_AEC_HANDSFREE_NUM;
break;
case RT5670_DSP_DIS:
default:
cnt += sprintf(buf, "RT5642 DSP Disabled\n");
goto dsp_done;
}
for (i = 0; i < tab_num; i++) {
if (cnt + RT5670_DSP_REG_DISP_LEN >= PAGE_SIZE)
break;
val = rt5670_dsp_read(codec, rt5670_dsp_tab[i][0]);
if (!val)
continue;
cnt += snprintf(buf + cnt, RT5670_DSP_REG_DISP_LEN,
"%04x: %04x\n", rt5670_dsp_tab[i][0], val);
}
rt5670_dsp_tab = rt5670_dsp_init;
tab_num = RT5670_DSP_INIT_NUM;
for (i = 0; i < tab_num; i++) {
if (cnt + RT5670_DSP_REG_DISP_LEN >= PAGE_SIZE)
break;
val = rt5670_dsp_read(codec, rt5670_dsp_tab[i][0]);
if (!val)
continue;
cnt += snprintf(buf + cnt, RT5670_DSP_REG_DISP_LEN,
"%04x: %04x\n",
rt5670_dsp_tab[i][0], val);
}
dsp_done:
if (cnt >= PAGE_SIZE)
cnt = PAGE_SIZE - 1;
return cnt;
}
static ssize_t dsp_reg_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct rt5670_priv *rt5670 = i2c_get_clientdata(client);
struct snd_soc_codec *codec = rt5670->codec;
unsigned int val = 0, addr = 0;
int i;
pr_debug("register \"%s\" count = %d\n", buf, count);
/* address */
for (i = 0; i < count; i++)
if (*(buf + i) <= '9' && *(buf + i) >= '0')
addr = (addr << 4) | (*(buf + i) - '0');
else if (*(buf + i) <= 'f' && *(buf + i) >= 'a')
addr = (addr << 4) | ((*(buf + i) - 'a') + 0xa);
else if (*(buf + i) <= 'A' && *(buf + i) >= 'A')
addr = (addr << 4) | ((*(buf + i) - 'A') + 0xa);
else
break;
/* Value*/
for (i = i + 1; i < count; i++)
if (*(buf + i) <= '9' && *(buf + i) >= '0')
val = (val << 4) | (*(buf + i) - '0');
else if (*(buf + i) <= 'f' && *(buf + i) >= 'a')
val = (val << 4) | ((*(buf + i) - 'a') + 0xa);
else if (*(buf + i) <= 'F' && *(buf + i) >= 'A')
val = (val << 4) | ((*(buf + i) - 'A') + 0xa);
else
break;
pr_debug("addr=0x%x val=0x%x\n", addr, val);
if (i == count)
pr_debug("0x%04x = 0x%04x\n",
addr, rt5670_dsp_read(codec, addr));
else
rt5670_dsp_write(codec, addr, val);
return count;
}
static DEVICE_ATTR(dsp_reg, 0666, rt5670_dsp_show, dsp_reg_store);
/**
* rt5670_dsp_probe - register DSP for rt5670
* @codec: audio codec
*
* To register DSP function for rt5670.
*
* Returns 0 for success or negative error code.
*/
int rt5670_dsp_probe(struct snd_soc_codec *codec)
{
int ret;
if (codec == NULL)
return -EINVAL;
snd_soc_update_bits(codec, RT5670_PWR_DIG2,
RT5670_PWR_I2S_DSP, RT5670_PWR_I2S_DSP);
snd_soc_update_bits(codec, RT5670_DIG_MISC, RT5670_RST_DSP,
RT5670_RST_DSP);
snd_soc_update_bits(codec, RT5670_DIG_MISC, RT5670_RST_DSP, 0);
mdelay(10);
rt5670_dsp_write(codec, 0x22fb, 0);
/* power down DSP*/
rt5670_dsp_write(codec, 0x22f9, 1);
snd_soc_update_bits(codec, RT5670_PWR_DIG2,
RT5670_PWR_I2S_DSP, 0);
snd_soc_add_codec_controls(codec, rt5670_dsp_snd_controls,
ARRAY_SIZE(rt5670_dsp_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, rt5670_dsp_dapm_widgets,
ARRAY_SIZE(rt5670_dsp_dapm_widgets));
snd_soc_dapm_add_routes(&codec->dapm, rt5670_dsp_dapm_routes,
ARRAY_SIZE(rt5670_dsp_dapm_routes));
ret = device_create_file(codec->dev, &dev_attr_dsp_reg);
if (ret != 0) {
dev_err(codec->dev,
"Failed to create index_reg sysfs files: %d\n", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(rt5670_dsp_probe);
#ifdef RTK_IOCTL
int rt5670_dsp_ioctl_common(struct snd_hwdep *hw,
struct file *file, unsigned int cmd, unsigned long arg)
{
struct rt_codec_cmd rt_codec;
int *buf;
int *p;
int ret;
struct rt_codec_cmd __user *_rt_codec = (struct rt_codec_cmd *)arg;
struct snd_soc_codec *codec = hw->private_data;
struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec))) {
dev_err(codec->dev, "copy_from_user faild\n");
return -EFAULT;
}
dev_dbg(codec->dev, "rt_codec.number=%d\n", rt_codec.number);
buf = kmalloc(sizeof(*buf) * rt_codec.number, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
if (copy_from_user(buf, rt_codec.buf, sizeof(*buf) * rt_codec.number))
goto err;
ret = snd_soc_update_bits(codec, RT5670_PWR_DIG2,
RT5670_PWR_I2S_DSP, RT5670_PWR_I2S_DSP);
if (ret < 0) {
dev_err(codec->dev,
"Failed to power up DSP IIS interface: %d\n", ret);
goto err;
}
switch (cmd) {
case RT_READ_CODEC_DSP_IOCTL:
for (p = buf; p < buf + rt_codec.number / 2; p++)
*(p + rt_codec.number / 2) = rt5670_dsp_read(codec, *p);
if (copy_to_user(rt_codec.buf, buf,
sizeof(*buf) * rt_codec.number))
goto err;
break;
case RT_WRITE_CODEC_DSP_IOCTL:
if (codec == NULL) {
dev_dbg(codec->dev, "codec is null\n");
break;
}
for (p = buf; p < buf + rt_codec.number / 2; p++)
rt5670_dsp_write(codec, *p, *(p + rt_codec.number / 2));
break;
case RT_GET_CODEC_DSP_MODE_IOCTL:
*buf = rt5670->dsp_sw;
if (copy_to_user(rt_codec.buf, buf,
sizeof(*buf) * rt_codec.number))
goto err;
break;
default:
dev_info(codec->dev, "unsported dsp command\n");
break;
}
kfree(buf);
return 0;
err:
kfree(buf);
return -EFAULT;
}
EXPORT_SYMBOL_GPL(rt5670_dsp_ioctl_common);
#endif
#ifdef CONFIG_PM
int rt5670_dsp_suspend(struct snd_soc_codec *codec)
{
return 0;
}
EXPORT_SYMBOL_GPL(rt5670_dsp_suspend);
int rt5670_dsp_resume(struct snd_soc_codec *codec)
{
return 0;
}
EXPORT_SYMBOL_GPL(rt5670_dsp_resume);
#endif