2 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * storm.c -- ALSA SoC machine driver for QTi ipq806x-based Storm board
16 #include <linux/device.h>
17 #include <linux/module.h>
19 #include <linux/mod_devicetable.h>
20 #include <linux/platform_device.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
25 #define STORM_SYSCLK_MULT 4
27 static int storm_ops_hw_params(struct snd_pcm_substream
*substream
,
28 struct snd_pcm_hw_params
*params
)
30 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
31 struct snd_soc_card
*card
= soc_runtime
->card
;
32 snd_pcm_format_t format
= params_format(params
);
33 unsigned int rate
= params_rate(params
);
34 unsigned int sysclk_freq
;
37 bitwidth
= snd_pcm_format_width(format
);
39 dev_err(card
->dev
, "%s() invalid bit width given: %d\n",
45 * as the CPU DAI is the I2S bus master and no system clock is needed by
46 * the MAX98357a DAC, simply set the system clock to be a constant
47 * multiple of the bit clock for the clock divider
49 sysclk_freq
= rate
* bitwidth
* 2 * STORM_SYSCLK_MULT
;
51 ret
= snd_soc_dai_set_sysclk(soc_runtime
->cpu_dai
, 0, sysclk_freq
, 0);
53 dev_err(card
->dev
, "%s() error setting sysclk to %u: %d\n",
54 __func__
, sysclk_freq
, ret
);
61 static const struct snd_soc_ops storm_soc_ops
= {
62 .hw_params
= storm_ops_hw_params
,
65 static struct snd_soc_dai_link storm_dai_link
= {
67 .stream_name
= "Primary",
68 .codec_dai_name
= "HiFi",
69 .ops
= &storm_soc_ops
,
72 static int storm_parse_of(struct snd_soc_card
*card
)
74 struct snd_soc_dai_link
*dai_link
= card
->dai_link
;
75 struct device_node
*np
= card
->dev
->of_node
;
77 dai_link
->cpu_of_node
= of_parse_phandle(np
, "cpu", 0);
78 if (!dai_link
->cpu_of_node
) {
79 dev_err(card
->dev
, "%s() error getting cpu phandle\n",
83 dai_link
->platform_of_node
= dai_link
->cpu_of_node
;
85 dai_link
->codec_of_node
= of_parse_phandle(np
, "codec", 0);
86 if (!dai_link
->codec_of_node
) {
87 dev_err(card
->dev
, "%s() error getting codec phandle\n",
95 static int storm_platform_probe(struct platform_device
*pdev
)
97 struct snd_soc_card
*card
;
100 card
= devm_kzalloc(&pdev
->dev
, sizeof(*card
), GFP_KERNEL
);
104 card
->dev
= &pdev
->dev
;
105 platform_set_drvdata(pdev
, card
);
107 ret
= snd_soc_of_parse_card_name(card
, "qcom,model");
109 dev_err(&pdev
->dev
, "%s() error parsing card name: %d\n",
114 card
->dai_link
= &storm_dai_link
;
117 ret
= storm_parse_of(card
);
119 dev_err(&pdev
->dev
, "%s() error resolving dai links: %d\n",
124 ret
= devm_snd_soc_register_card(&pdev
->dev
, card
);
126 dev_err(&pdev
->dev
, "%s() error registering soundcard: %d\n",
134 static const struct of_device_id storm_device_id
[] = {
135 { .compatible
= "google,storm-audio" },
138 MODULE_DEVICE_TABLE(of
, storm_device_id
);
141 static struct platform_driver storm_platform_driver
= {
143 .name
= "storm-audio",
145 of_match_ptr(storm_device_id
),
147 .probe
= storm_platform_probe
,
149 module_platform_driver(storm_platform_driver
);
151 MODULE_DESCRIPTION("QTi IPQ806x-based Storm Machine Driver");
152 MODULE_LICENSE("GPL v2");