10ed275efSAlexander Shiyan /* 20ed275efSAlexander Shiyan * SoC audio for EDB93xx 30ed275efSAlexander Shiyan * 40ed275efSAlexander Shiyan * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> 50ed275efSAlexander Shiyan * 60ed275efSAlexander Shiyan * This program is free software; you can redistribute it and/or 70ed275efSAlexander Shiyan * modify it under the terms of the GNU General Public License 80ed275efSAlexander Shiyan * as published by the Free Software Foundation; either version 2 90ed275efSAlexander Shiyan * of the License, or (at your option) any later version. 100ed275efSAlexander Shiyan * 110ed275efSAlexander Shiyan * This program is distributed in the hope that it will be useful, 120ed275efSAlexander Shiyan * but WITHOUT ANY WARRANTY; without even the implied warranty of 130ed275efSAlexander Shiyan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 140ed275efSAlexander Shiyan * GNU General Public License for more details. 150ed275efSAlexander Shiyan * 160ed275efSAlexander Shiyan * This driver support CS4271 codec being master or slave, working 170ed275efSAlexander Shiyan * in control port mode, connected either via SPI or I2C. 180ed275efSAlexander Shiyan * The data format accepted is I2S or left-justified. 190ed275efSAlexander Shiyan * DAPM support not implemented. 200ed275efSAlexander Shiyan */ 210ed275efSAlexander Shiyan 220ed275efSAlexander Shiyan #include <linux/platform_device.h> 230ed275efSAlexander Shiyan #include <linux/gpio.h> 240ed275efSAlexander Shiyan #include <linux/module.h> 250ed275efSAlexander Shiyan #include <sound/core.h> 260ed275efSAlexander Shiyan #include <sound/pcm.h> 270ed275efSAlexander Shiyan #include <sound/soc.h> 280ed275efSAlexander Shiyan #include <asm/mach-types.h> 290ed275efSAlexander Shiyan #include <mach/hardware.h> 300ed275efSAlexander Shiyan 310ed275efSAlexander Shiyan static int edb93xx_hw_params(struct snd_pcm_substream *substream, 320ed275efSAlexander Shiyan struct snd_pcm_hw_params *params) 330ed275efSAlexander Shiyan { 340ed275efSAlexander Shiyan struct snd_soc_pcm_runtime *rtd = substream->private_data; 350ed275efSAlexander Shiyan struct snd_soc_dai *codec_dai = rtd->codec_dai; 360ed275efSAlexander Shiyan struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 370ed275efSAlexander Shiyan int err; 380ed275efSAlexander Shiyan unsigned int mclk_rate; 390ed275efSAlexander Shiyan unsigned int rate = params_rate(params); 400ed275efSAlexander Shiyan 410ed275efSAlexander Shiyan /* 420ed275efSAlexander Shiyan * According to CS4271 datasheet we use MCLK/LRCK=256 for 430ed275efSAlexander Shiyan * rates below 50kHz and 128 for higher sample rates 440ed275efSAlexander Shiyan */ 450ed275efSAlexander Shiyan if (rate < 50000) 460ed275efSAlexander Shiyan mclk_rate = rate * 64 * 4; 470ed275efSAlexander Shiyan else 480ed275efSAlexander Shiyan mclk_rate = rate * 64 * 2; 490ed275efSAlexander Shiyan 500ed275efSAlexander Shiyan err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, 510ed275efSAlexander Shiyan SND_SOC_CLOCK_IN); 520ed275efSAlexander Shiyan if (err) 530ed275efSAlexander Shiyan return err; 540ed275efSAlexander Shiyan 550ed275efSAlexander Shiyan return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, 560ed275efSAlexander Shiyan SND_SOC_CLOCK_OUT); 570ed275efSAlexander Shiyan } 580ed275efSAlexander Shiyan 597f8159acSBhumika Goyal static const struct snd_soc_ops edb93xx_ops = { 600ed275efSAlexander Shiyan .hw_params = edb93xx_hw_params, 610ed275efSAlexander Shiyan }; 620ed275efSAlexander Shiyan 630ed275efSAlexander Shiyan static struct snd_soc_dai_link edb93xx_dai = { 640ed275efSAlexander Shiyan .name = "CS4271", 650ed275efSAlexander Shiyan .stream_name = "CS4271 HiFi", 666f2032a1SStephen Warren .platform_name = "ep93xx-i2s", 670ed275efSAlexander Shiyan .cpu_dai_name = "ep93xx-i2s", 680ed275efSAlexander Shiyan .codec_name = "spi0.0", 690ed275efSAlexander Shiyan .codec_dai_name = "cs4271-hifi", 700ed275efSAlexander Shiyan .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | 710ed275efSAlexander Shiyan SND_SOC_DAIFMT_CBS_CFS, 720ed275efSAlexander Shiyan .ops = &edb93xx_ops, 730ed275efSAlexander Shiyan }; 740ed275efSAlexander Shiyan 750ed275efSAlexander Shiyan static struct snd_soc_card snd_soc_edb93xx = { 760ed275efSAlexander Shiyan .name = "EDB93XX", 770ed275efSAlexander Shiyan .owner = THIS_MODULE, 780ed275efSAlexander Shiyan .dai_link = &edb93xx_dai, 790ed275efSAlexander Shiyan .num_links = 1, 800ed275efSAlexander Shiyan }; 810ed275efSAlexander Shiyan 82145e2879SBill Pemberton static int edb93xx_probe(struct platform_device *pdev) 830ed275efSAlexander Shiyan { 840ed275efSAlexander Shiyan struct snd_soc_card *card = &snd_soc_edb93xx; 850ed275efSAlexander Shiyan int ret; 860ed275efSAlexander Shiyan 870ed275efSAlexander Shiyan ret = ep93xx_i2s_acquire(); 880ed275efSAlexander Shiyan if (ret) 890ed275efSAlexander Shiyan return ret; 900ed275efSAlexander Shiyan 910ed275efSAlexander Shiyan card->dev = &pdev->dev; 920ed275efSAlexander Shiyan 930ed275efSAlexander Shiyan ret = snd_soc_register_card(card); 940ed275efSAlexander Shiyan if (ret) { 950ed275efSAlexander Shiyan dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", 960ed275efSAlexander Shiyan ret); 970ed275efSAlexander Shiyan ep93xx_i2s_release(); 980ed275efSAlexander Shiyan } 990ed275efSAlexander Shiyan 1000ed275efSAlexander Shiyan return ret; 1010ed275efSAlexander Shiyan } 1020ed275efSAlexander Shiyan 103145e2879SBill Pemberton static int edb93xx_remove(struct platform_device *pdev) 1040ed275efSAlexander Shiyan { 1050ed275efSAlexander Shiyan struct snd_soc_card *card = platform_get_drvdata(pdev); 1060ed275efSAlexander Shiyan 1070ed275efSAlexander Shiyan snd_soc_unregister_card(card); 1080ed275efSAlexander Shiyan ep93xx_i2s_release(); 1090ed275efSAlexander Shiyan 1100ed275efSAlexander Shiyan return 0; 1110ed275efSAlexander Shiyan } 1120ed275efSAlexander Shiyan 1130ed275efSAlexander Shiyan static struct platform_driver edb93xx_driver = { 1140ed275efSAlexander Shiyan .driver = { 1150ed275efSAlexander Shiyan .name = "edb93xx-audio", 1160ed275efSAlexander Shiyan }, 1170ed275efSAlexander Shiyan .probe = edb93xx_probe, 118145e2879SBill Pemberton .remove = edb93xx_remove, 1190ed275efSAlexander Shiyan }; 1200ed275efSAlexander Shiyan 1210ed275efSAlexander Shiyan module_platform_driver(edb93xx_driver); 1220ed275efSAlexander Shiyan 1230ed275efSAlexander Shiyan MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); 1240ed275efSAlexander Shiyan MODULE_DESCRIPTION("ALSA SoC EDB93xx"); 1250ed275efSAlexander Shiyan MODULE_LICENSE("GPL"); 1260ed275efSAlexander Shiyan MODULE_ALIAS("platform:edb93xx-audio"); 127