blob: 8fdcc16d90e8d6d8796107afe54c928284d8c8bc [file] [log] [blame]
/*
* qca-cus227.c -- ALSA machine code for CUS227 board ref design (and relatives)
*
* Copyright (c) 2013 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <asm/delay.h>
#include <linux/types.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <linux/module.h>
/* Driver include */
#include <asm/mach-ath79/ar71xx_regs.h>
#include <asm/mach-ath79/ath79.h>
#include "ath79-i2s.h"
#include "ath79-pcm.h"
#include "../codecs/wm8988.h"
static struct platform_device *cus227_snd_device;
static int cus227_hifi_hw_params(struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = ss->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec;
unsigned int clk = 0;
int ret;
u16 vol_reg;
switch (params_rate(params)) {
case 8000:
case 16000:
case 32000:
case 48000:
case 96000:
clk = 12288000;
break;
case 11025:
case 22050:
case 44100:
case 88200:
clk = 11289600;
break;
}
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, WM8988_SYSCLK, clk,
SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
if (ss->stream == SNDRV_PCM_STREAM_CAPTURE) {
/*Disable Left&Right Channel Input Analogue Mute,
* and wm8988 datasheet says we should also set bit8
* for WM8988_LINVOL&WM8988_RINVOL concurrently.*/
vol_reg = snd_soc_read(codec, WM8988_LINVOL) & 0x7f;
snd_soc_write(codec, WM8988_LINVOL, 0x100 | vol_reg);
vol_reg = snd_soc_read(codec, WM8988_RINVOL) & 0x7f;
snd_soc_write(codec, WM8988_RINVOL, 0x100 | vol_reg);
}
return 0;
}
static int cus227_late_probe(struct snd_soc_card *card)
{
struct snd_soc_dai *codec_dai = card->rtd->codec_dai;
int ret;
ret = snd_soc_dai_set_sysclk(codec_dai, WM8988_SYSCLK,
11289600, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops cus227_dai_ops = {
.hw_params = cus227_hifi_hw_params,
};
static struct snd_soc_dai_link cus227_dai = {
.name = "CUS227 audio",
.stream_name = "CUS227 audio",
.cpu_dai_name = "ath79-i2s",
.codec_dai_name = "wm8988-hifi",
.platform_name = "ath79-pcm-audio",
.codec_name = "spi0.1",
/* use ops to check startup state */
.ops = &cus227_dai_ops,
};
static struct snd_soc_card snd_soc_cus227 = {
.name = "QCA CUS227",
.long_name = "CUS227 - ath79-pcm/ath79-i2s/wm8988",
.dai_link = &cus227_dai,
.num_links = 1,
.late_probe = cus227_late_probe,
};
static int __init cus227_init(void)
{
int ret;
cus227_snd_device = platform_device_alloc("soc-audio", -1);
if(!cus227_snd_device)
return -ENOMEM;
platform_set_drvdata(cus227_snd_device, &snd_soc_cus227);
ret = platform_device_add(cus227_snd_device);
if (ret) {
platform_device_put(cus227_snd_device);
}
return ret;
}
static void __exit cus227_exit(void)
{
platform_device_unregister(cus227_snd_device);
}
module_init(cus227_init);
module_exit(cus227_exit);
MODULE_AUTHOR("Qualcomm-Atheros Inc.");
MODULE_AUTHOR("Mathieu Olivari <mathieu@qca.qualcomm.com>");
MODULE_DESCRIPTION("QCA Audio Machine module");
MODULE_LICENSE("Dual BSD/GPL");