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
, "invalid bit width given: %d\n", bitwidth
);
44 * as the CPU DAI is the I2S bus master and no system clock is needed by
45 * the MAX98357a DAC, simply set the system clock to be a constant
46 * multiple of the bit clock for the clock divider
48 sysclk_freq
= rate
* bitwidth
* 2 * STORM_SYSCLK_MULT
;
50 ret
= snd_soc_dai_set_sysclk(soc_runtime
->cpu_dai
, 0, sysclk_freq
, 0);
52 dev_err(card
->dev
, "error setting sysclk to %u: %d\n",
60 static const struct snd_soc_ops storm_soc_ops
= {
61 .hw_params
= storm_ops_hw_params
,
64 static struct snd_soc_dai_link storm_dai_link
= {
66 .stream_name
= "Primary",
67 .codec_dai_name
= "HiFi",
68 .ops
= &storm_soc_ops
,
71 static int storm_parse_of(struct snd_soc_card
*card
)
73 struct snd_soc_dai_link
*dai_link
= card
->dai_link
;
74 struct device_node
*np
= card
->dev
->of_node
;
76 dai_link
->cpu_of_node
= of_parse_phandle(np
, "cpu", 0);
77 if (!dai_link
->cpu_of_node
) {
78 dev_err(card
->dev
, "error getting cpu phandle\n");
81 dai_link
->platform_of_node
= dai_link
->cpu_of_node
;
83 dai_link
->codec_of_node
= of_parse_phandle(np
, "codec", 0);
84 if (!dai_link
->codec_of_node
) {
85 dev_err(card
->dev
, "error getting codec phandle\n");
92 static int storm_platform_probe(struct platform_device
*pdev
)
94 struct snd_soc_card
*card
;
97 card
= devm_kzalloc(&pdev
->dev
, sizeof(*card
), GFP_KERNEL
);
101 card
->dev
= &pdev
->dev
;
103 ret
= snd_soc_of_parse_card_name(card
, "qcom,model");
105 dev_err(&pdev
->dev
, "error parsing card name: %d\n", ret
);
109 card
->dai_link
= &storm_dai_link
;
112 ret
= storm_parse_of(card
);
114 dev_err(&pdev
->dev
, "error resolving dai links: %d\n", ret
);
118 ret
= devm_snd_soc_register_card(&pdev
->dev
, card
);
120 dev_err(&pdev
->dev
, "error registering soundcard: %d\n", ret
);
127 static const struct of_device_id storm_device_id
[] = {
128 { .compatible
= "google,storm-audio" },
131 MODULE_DEVICE_TABLE(of
, storm_device_id
);
134 static struct platform_driver storm_platform_driver
= {
136 .name
= "storm-audio",
138 of_match_ptr(storm_device_id
),
140 .probe
= storm_platform_probe
,
142 module_platform_driver(storm_platform_driver
);
144 MODULE_DESCRIPTION("QTi IPQ806x-based Storm Machine Driver");
145 MODULE_LICENSE("GPL v2");