cregit-Linux how code gets into the kernel

Release 4.7 sound/soc/zte/zx296702-spdif.c

Directory: sound/soc/zte
/*
 * Copyright (C) 2015 Linaro
 *
 * Author: Jun Nie <jun.nie@linaro.org>
 *
 * License terms: GNU General Public License (GPL) version 2
 */

#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <sound/asoundef.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>


#define ZX_CTRL				0x04

#define ZX_FIFOCTRL			0x08

#define ZX_INT_STATUS			0x10

#define ZX_INT_MASK			0x14

#define ZX_DATA				0x18

#define ZX_VALID_BIT			0x1c

#define ZX_CH_STA_1			0x20

#define ZX_CH_STA_2			0x24

#define ZX_CH_STA_3			0x28

#define ZX_CH_STA_4			0x2c

#define ZX_CH_STA_5			0x30

#define ZX_CH_STA_6			0x34


#define ZX_CTRL_MODA_16			(0 << 6)

#define ZX_CTRL_MODA_18			BIT(6)

#define ZX_CTRL_MODA_20			(2 << 6)

#define ZX_CTRL_MODA_24			(3 << 6)

#define ZX_CTRL_MODA_MASK		(3 << 6)


#define ZX_CTRL_ENB			BIT(4)

#define ZX_CTRL_DNB			(0 << 4)

#define ZX_CTRL_ENB_MASK		BIT(4)


#define ZX_CTRL_TX_OPEN			BIT(0)

#define ZX_CTRL_TX_CLOSE		(0 << 0)

#define ZX_CTRL_TX_MASK			BIT(0)


#define ZX_CTRL_OPEN			(ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)

#define ZX_CTRL_CLOSE			(ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)


#define ZX_CTRL_DOUBLE_TRACK		(0 << 8)

#define ZX_CTRL_LEFT_TRACK		BIT(8)

#define ZX_CTRL_RIGHT_TRACK		(2 << 8)

#define ZX_CTRL_TRACK_MASK		(3 << 8)


#define ZX_FIFOCTRL_TXTH_MASK		(0x1f << 8)

#define ZX_FIFOCTRL_TXTH(x)		(x << 8)

#define ZX_FIFOCTRL_TX_DMA_EN		BIT(2)

#define ZX_FIFOCTRL_TX_DMA_DIS		(0 << 2)

#define ZX_FIFOCTRL_TX_DMA_EN_MASK	BIT(2)

#define ZX_FIFOCTRL_TX_FIFO_RST		BIT(0)

#define ZX_FIFOCTRL_TX_FIFO_RST_MASK	BIT(0)


#define ZX_VALID_DOUBLE_TRACK		(0 << 0)

#define ZX_VALID_LEFT_TRACK		BIT(1)

#define ZX_VALID_RIGHT_TRACK		(2 << 0)

#define ZX_VALID_TRACK_MASK		(3 << 0)


#define ZX_SPDIF_CLK_RAT		(4 * 32)


struct zx_spdif_info {
	
struct snd_dmaengine_dai_dma_data	dma_data;
	
struct clk				*dai_clk;
	
void __iomem				*reg_base;
	
resource_size_t				mapbase;
};


static int zx_spdif_dai_probe(struct snd_soc_dai *dai) { struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); snd_soc_dai_set_drvdata(dai, zx_spdif); zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA; zx_spdif->dma_data.maxburst = 8; snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie65100.00%1100.00%
Total65100.00%1100.00%


static int zx_spdif_chanstats(void __iomem *base, unsigned int rate) { u32 cstas1; switch (rate) { case 22050: cstas1 = IEC958_AES3_CON_FS_22050; break; case 24000: cstas1 = IEC958_AES3_CON_FS_24000; break; case 32000: cstas1 = IEC958_AES3_CON_FS_32000; break; case 44100: cstas1 = IEC958_AES3_CON_FS_44100; break; case 48000: cstas1 = IEC958_AES3_CON_FS_48000; break; case 88200: cstas1 = IEC958_AES3_CON_FS_88200; break; case 96000: cstas1 = IEC958_AES3_CON_FS_96000; break; case 176400: cstas1 = IEC958_AES3_CON_FS_176400; break; case 192000: cstas1 = IEC958_AES3_CON_FS_192000; break; default: return -EINVAL; } cstas1 = cstas1 << 24; cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT; writel_relaxed(cstas1, base + ZX_CH_STA_1); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie123100.00%1100.00%
Total123100.00%1100.00%


static int zx_spdif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) { struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev); struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai); struct snd_dmaengine_dai_dma_data *dma_data = &zx_spdif->dma_data; u32 val, ch_num, rate; int ret; dma_data = snd_soc_dai_get_dma_data(socdai, substream); dma_data->addr_width = params_width(params) >> 3; val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL); val &= ~ZX_CTRL_MODA_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: val |= ZX_CTRL_MODA_16; break; case SNDRV_PCM_FORMAT_S18_3LE: val |= ZX_CTRL_MODA_18; break; case SNDRV_PCM_FORMAT_S20_3LE: val |= ZX_CTRL_MODA_20; break; case SNDRV_PCM_FORMAT_S24_LE: val |= ZX_CTRL_MODA_24; break; default: dev_err(socdai->dev, "Format not support!\n"); return -EINVAL; } ch_num = params_channels(params); if (ch_num == 2) val |= ZX_CTRL_DOUBLE_TRACK; else val |= ZX_CTRL_LEFT_TRACK; writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL); val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT); val &= ~ZX_VALID_TRACK_MASK; if (ch_num == 2) val |= ZX_VALID_DOUBLE_TRACK; else val |= ZX_VALID_RIGHT_TRACK; writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT); rate = params_rate(params); ret = zx_spdif_chanstats(zx_spdif->reg_base, rate); if (ret) return ret; return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT); }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie26799.63%150.00%
fengguang wufengguang wu10.37%150.00%
Total268100.00%2100.00%


static void zx_spdif_cfg_tx(void __iomem *base, int on) { u32 val; val = readl_relaxed(base + ZX_CTRL); val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK); val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE; writel_relaxed(val, base + ZX_CTRL); val = readl_relaxed(base + ZX_FIFOCTRL); val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK; if (on) val |= ZX_FIFOCTRL_TX_DMA_EN; writel_relaxed(val, base + ZX_FIFOCTRL); }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie83100.00%1100.00%
Total83100.00%1100.00%


static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { u32 val; struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL); val |= ZX_FIFOCTRL_TX_FIFO_RST; writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL); /* fall thru */ case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: zx_spdif_cfg_tx(zx_spdif->reg_base, true); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: zx_spdif_cfg_tx(zx_spdif->reg_base, false); break; default: ret = -EINVAL; break; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie120100.00%1100.00%
Total120100.00%1100.00%


static int zx_spdif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); return clk_prepare_enable(zx_spdif->dai_clk); }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie36100.00%1100.00%
Total36100.00%1100.00%


static void zx_spdif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); clk_disable_unprepare(zx_spdif->dai_clk); }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie35100.00%1100.00%
Total35100.00%1100.00%

#define ZX_RATES \ (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) #define ZX_FORMAT \ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \ | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) static struct snd_soc_dai_ops zx_spdif_dai_ops = { .trigger = zx_spdif_trigger, .startup = zx_spdif_startup, .shutdown = zx_spdif_shutdown, .hw_params = zx_spdif_hw_params, }; static struct snd_soc_dai_driver zx_spdif_dai = { .name = "spdif", .id = 0, .probe = zx_spdif_dai_probe, .playback = { .channels_min = 1, .channels_max = 2, .rates = ZX_RATES, .formats = ZX_FORMAT, }, .ops = &zx_spdif_dai_ops, }; static const struct snd_soc_component_driver zx_spdif_component = { .name = "spdif", };
static void zx_spdif_dev_init(void __iomem *base) { u32 val; writel_relaxed(0, base + ZX_CTRL); writel_relaxed(0, base + ZX_INT_MASK); writel_relaxed(0xf, base + ZX_INT_STATUS); writel_relaxed(0x1, base + ZX_FIFOCTRL); val = readl_relaxed(base + ZX_FIFOCTRL); val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK); val |= ZX_FIFOCTRL_TXTH(8); writel_relaxed(val, base + ZX_FIFOCTRL); }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie84100.00%1100.00%
Total84100.00%1100.00%


static int zx_spdif_probe(struct platform_device *pdev) { struct resource *res; struct zx_spdif_info *zx_spdif; int ret; zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL); if (!zx_spdif) return -ENOMEM; zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx"); if (IS_ERR(zx_spdif->dai_clk)) { dev_err(&pdev->dev, "Fail to get clk\n"); return PTR_ERR(zx_spdif->dai_clk); } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); zx_spdif->mapbase = res->start; zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(zx_spdif->reg_base)) { dev_err(&pdev->dev, "ioremap failed!\n"); return PTR_ERR(zx_spdif->reg_base); } zx_spdif_dev_init(zx_spdif->reg_base); platform_set_drvdata(pdev, zx_spdif); ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component, &zx_spdif_dai, 1); if (ret) { dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); return ret; } ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie22894.21%133.33%
krzysztof kozlowskikrzysztof kozlowski93.72%133.33%
mark brownmark brown52.07%133.33%
Total242100.00%3100.00%

static const struct of_device_id zx_spdif_dt_ids[] = { { .compatible = "zte,zx296702-spdif", }, {} }; MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids); static struct platform_driver spdif_driver = { .probe = zx_spdif_probe, .driver = { .name = "zx-spdif", .of_match_table = zx_spdif_dt_ids, }, }; module_platform_driver(spdif_driver); MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>"); MODULE_DESCRIPTION("ZTE SPDIF SoC DAI"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
jun niejun nie145498.98%125.00%
krzysztof kozlowskikrzysztof kozlowski90.61%125.00%
mark brownmark brown50.34%125.00%
fengguang wufengguang wu10.07%125.00%
Total1469100.00%4100.00%
Directory: sound/soc/zte
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}