Commit e4c164d6 authored by Mark Brown's avatar Mark Brown

Merge series "Add documentation and machine driver for SC7180 sound card" from...

Merge series "Add documentation and machine driver for SC7180 sound card" from Cheng-Yi Chiang <cychiang@chromium.org>:

Note:
- The machine driver patch is made by the collaboration of
  Cheng-Yi Chiang <cychiang@chromium.org>
  Rohit kumar <rohitkr@codeaurora.org>
  Ajit Pandey <ajitp@codeaurora.org>
  But Ajit has left codeaurora.

Changes from v1 to v2:
- Ducumentation: Addressed all suggestions from Doug.
- Machine driver:
  - Fix comment style for license.
  - Sort includes.
  - Remove sc7180_snd_hw_params.
  - Remove sc7180_dai_init and use aux device instead for headset jack registration.
  - Statically define format for Primary MI2S.
  - Atomic is not a concern because there is mutex in card to make sure
    startup and shutdown happen sequentially.
  - Fix missing return -EINVAL in startup.
  - Use static sound card.
  - Use devm_kzalloc to avoid kfree.

Changes from v2 to v3:
- Ducumentation: Addressed suggestions from Srini.
- Machine driver:
  - Reuse qcom_snd_parse_of to parse properties.
  - Remove playback-only and capture-only.
  - Misc fixes to address comments.

Changes from v3 to v4:
- Ducumentation: Addressed suggestions from Rob.
 - Remove definition of dai.
 - Use 'sound-dai: true' for sound-dai schema.
 - Add reg property to pass 'make dt_binding_check' check although reg is not used in the driver.
- Machine driver:
 - Add Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>

Changes from v4 to v5:
- Documentation: Addressed suggestions from Rob.
 - Add definition for "#address-cells" and "#size-cells".
 - Add additionalProperties: false
 - Add required properties.

Changes from v5 to v6:
- Documentation: Addressed suggestions from Rob.
 - Drop contains in compatible strings.
 - Only allow dai-link@[0-9]
 - Remove reg ref since it has a type definition already.

Changes from v6 to v7
- Documentation:
  - Add headset-jack and hdmi-jack to specify the codec
    responsible for jack detection.
- HDMI codec driver:
  - Use component set_jack ops instead of exporting hdmi_codec_set_jack_detect.
- Machine driver:
  - Removed aux device following Stephan's suggestion.
  - Use headset-jack and hdmi-jack to specify the codec
    responsible for jack detection.
  - Add support for HDMI(actually DP) playback.

Changes from v7 to v8
- Documentation:
  - Remove headset-jack and hdmi-jack.
- Machine driver:
  - Let machine driver decide whether there is a jack on the DAI.

Changes from v8 to v9
- hdmi-codec driver:
  - Fixed the naming.
- Machine driver:
  - Fixed unused fields.
  - Moved snd_soc_card_set_drvdata
  - Keep the naming of HDMI as dai name until v5 of lpass-hdmi patches.

Changes from v9 to v10
- Documentation:
  - Let compatible string be more specific for board configuration to allow
    for future changes.
- Machine driver:
  - Fixed unused include and macro.
  - Add temporary macro SC7180_LPASS_DP for future change in sc7180-lpass.h.
  - Let sound card be dynamically allocated.
  - Change compatible string accordingly.

Changes from v10 to v11
- Machine driver:
  - Use temporary macro LPASS_DP_RX for future change in sc7180-lpass.h.

Changes from v11 to v12
- Documentation:
 - Change the file and title name for new compatible string google,sc7180-trogdor.
 - Change the example of model name.
- Machine driver:
 - Use the definitaion of index LPASS_DP_RX in sc7180-lpass.h.
 - Fix for compatible string.
 - Replace a comma with semicolon.

Ajit Pandey (1):
  ASoC: qcom: sc7180: Add machine driver for sound card registration

Cheng-Yi Chiang (1):
  ASoC: google: dt-bindings: Add sc7180-trogdor machine bindings

 .../bindings/sound/google,sc7180-trogdor.yaml | 130 +++++++++
 sound/soc/qcom/Kconfig                        |  12 +
 sound/soc/qcom/Makefile                       |   2 +
 sound/soc/qcom/sc7180.c                       | 266 ++++++++++++++++++
 4 files changed, 410 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml
 create mode 100644 sound/soc/qcom/sc7180.c

--
2.29.0.rc2.309.g374f81d7ae-goog
parents 023e1b1f 9e3ecb5b
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/google,sc7180-trogdor.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Google SC7180-Trogdor ASoC sound card driver
maintainers:
- Rohit kumar <rohitkr@codeaurora.org>
- Cheng-Yi Chiang <cychiang@chromium.org>
description:
This binding describes the SC7180 sound card which uses LPASS for audio.
properties:
compatible:
const: google,sc7180-trogdor
audio-routing:
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
description:
A list of the connections between audio components. Each entry is a
pair of strings, the first being the connection's sink, the second
being the connection's source.
model:
$ref: /schemas/types.yaml#/definitions/string
description: User specified audio sound card name
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^dai-link(@[0-9])?$":
description:
Each subnode represents a dai link. Subnodes of each dai links would be
cpu/codec dais.
type: object
properties:
link-name:
description: Indicates dai-link name and PCM stream name.
$ref: /schemas/types.yaml#/definitions/string
maxItems: 1
reg:
description: dai link address.
cpu:
description: Holds subnode which indicates cpu dai.
type: object
properties:
sound-dai: true
codec:
description: Holds subnode which indicates codec dai.
type: object
properties:
sound-dai: true
required:
- link-name
- cpu
- codec
additionalProperties: false
required:
- compatible
- model
- "#address-cells"
- "#size-cells"
additionalProperties: false
examples:
- |
sound {
compatible = "google,sc7180-trogdor";
model = "sc7180-rt5682-max98357a-1mic";
audio-routing =
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
#address-cells = <1>;
#size-cells = <0>;
dai-link@0 {
link-name = "MultiMedia0";
reg = <0>;
cpu {
sound-dai = <&lpass_cpu 0>;
};
codec {
sound-dai = <&alc5682 0>;
};
};
dai-link@1 {
link-name = "MultiMedia1";
reg = <1>;
cpu {
sound-dai = <&lpass_cpu 1>;
};
codec {
sound-dai = <&max98357a>;
};
};
dai-link@2 {
link-name = "MultiMedia2";
reg = <2>;
cpu {
sound-dai = <&lpass_hdmi 0>;
};
codec {
sound-dai = <&msm_dp>;
};
};
};
......@@ -138,4 +138,16 @@ config SND_SOC_SM8250
SM8250 SoC-based systems.
Say Y if you want to use audio device on this SoCs.
config SND_SOC_SC7180
tristate "SoC Machine driver for SC7180 boards"
depends on I2C
select SND_SOC_QCOM_COMMON
select SND_SOC_LPASS_SC7180
select SND_SOC_MAX98357A
select SND_SOC_RT5682_I2C
help
To add support for audio on Qualcomm Technologies Inc.
SC7180 SoC-based systems.
Say Y if you want to use audio device on this SoCs.
endif #SND_SOC_QCOM
......@@ -18,6 +18,7 @@ obj-$(CONFIG_SND_SOC_LPASS_SC7180) += snd-soc-lpass-sc7180.o
snd-soc-storm-objs := storm.o
snd-soc-apq8016-sbc-objs := apq8016_sbc.o
snd-soc-apq8096-objs := apq8096.o
snd-soc-sc7180-objs := sc7180.o
snd-soc-sdm845-objs := sdm845.o
snd-soc-sm8250-objs := sm8250.o
snd-soc-qcom-common-objs := common.o
......@@ -25,6 +26,7 @@ snd-soc-qcom-common-objs := common.o
obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o
obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o
obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-apq8096.o
obj-$(CONFIG_SND_SOC_SC7180) += snd-soc-sc7180.o
obj-$(CONFIG_SND_SOC_SDM845) += snd-soc-sdm845.o
obj-$(CONFIG_SND_SOC_SM8250) += snd-soc-sm8250.o
obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o
......
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright (c) 2020, The Linux Foundation. All rights reserved.
//
// sc7180.c -- ALSA SoC Machine driver for SC7180
#include <dt-bindings/sound/sc7180-lpass.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <uapi/linux/input-event-codes.h>
#include "../codecs/rt5682.h"
#include "common.h"
#include "lpass.h"
#define DEFAULT_MCLK_RATE 19200000
#define RT5682_PLL1_FREQ (48000 * 512)
#define DRIVER_NAME "SC7180"
struct sc7180_snd_data {
struct snd_soc_card card;
u32 pri_mi2s_clk_count;
struct snd_soc_jack hs_jack;
struct snd_soc_jack hdmi_jack;
};
static void sc7180_jack_free(struct snd_jack *jack)
{
struct snd_soc_component *component = jack->private_data;
snd_soc_component_set_jack(component, NULL, NULL);
}
static int sc7180_headset_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
struct snd_jack *jack;
int rval;
rval = snd_soc_card_jack_new(
card, "Headset Jack",
SND_JACK_HEADSET |
SND_JACK_HEADPHONE |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
&pdata->hs_jack, NULL, 0);
if (rval < 0) {
dev_err(card->dev, "Unable to add Headset Jack\n");
return rval;
}
jack = pdata->hs_jack.jack;
snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
jack->private_data = component;
jack->private_free = sc7180_jack_free;
return snd_soc_component_set_jack(component, &pdata->hs_jack, NULL);
}
static int sc7180_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_card *card = rtd->card;
struct sc7180_snd_data *pdata = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
struct snd_soc_component *component = codec_dai->component;
struct snd_jack *jack;
int rval;
rval = snd_soc_card_jack_new(
card, "HDMI Jack",
SND_JACK_LINEOUT,
&pdata->hdmi_jack, NULL, 0);
if (rval < 0) {
dev_err(card->dev, "Unable to add HDMI Jack\n");
return rval;
}
jack = pdata->hdmi_jack.jack;
jack->private_data = component;
jack->private_free = sc7180_jack_free;
return snd_soc_component_set_jack(component, &pdata->hdmi_jack, NULL);
}
static int sc7180_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
switch (cpu_dai->id) {
case MI2S_PRIMARY:
return sc7180_headset_init(rtd);
case MI2S_SECONDARY:
return 0;
case LPASS_DP_RX:
return sc7180_hdmi_init(rtd);
default:
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
cpu_dai->id);
return -EINVAL;
}
return 0;
}
static int sc7180_snd_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int ret;
switch (cpu_dai->id) {
case MI2S_PRIMARY:
if (++data->pri_mi2s_clk_count == 1) {
snd_soc_dai_set_sysclk(cpu_dai,
LPASS_MCLK0,
DEFAULT_MCLK_RATE,
SNDRV_PCM_STREAM_PLAYBACK);
}
snd_soc_dai_set_fmt(codec_dai,
SND_SOC_DAIFMT_CBS_CFS |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_I2S);
/* Configure PLL1 for codec */
ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
DEFAULT_MCLK_RATE, RT5682_PLL1_FREQ);
if (ret) {
dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
return ret;
}
/* Configure sysclk for codec */
ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
RT5682_PLL1_FREQ,
SND_SOC_CLOCK_IN);
if (ret)
dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n",
ret);
break;
case MI2S_SECONDARY:
break;
case LPASS_DP_RX:
break;
default:
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
cpu_dai->id);
return -EINVAL;
}
return 0;
}
static void sc7180_snd_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
switch (cpu_dai->id) {
case MI2S_PRIMARY:
if (--data->pri_mi2s_clk_count == 0) {
snd_soc_dai_set_sysclk(cpu_dai,
LPASS_MCLK0,
0,
SNDRV_PCM_STREAM_PLAYBACK);
}
break;
case MI2S_SECONDARY:
break;
case LPASS_DP_RX:
break;
default:
dev_err(rtd->dev, "%s: invalid dai id 0x%x\n", __func__,
cpu_dai->id);
break;
}
}
static const struct snd_soc_ops sc7180_ops = {
.startup = sc7180_snd_startup,
.shutdown = sc7180_snd_shutdown,
};
static const struct snd_soc_dapm_widget sc7180_snd_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
};
static void sc7180_add_ops(struct snd_soc_card *card)
{
struct snd_soc_dai_link *link;
int i;
for_each_card_prelinks(card, i, link) {
link->ops = &sc7180_ops;
link->init = sc7180_init;
}
}
static int sc7180_snd_platform_probe(struct platform_device *pdev)
{
struct snd_soc_card *card;
struct sc7180_snd_data *data;
struct device *dev = &pdev->dev;
int ret;
/* Allocate the private data */
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
card = &data->card;
snd_soc_card_set_drvdata(card, data);
card->owner = THIS_MODULE;
card->driver_name = DRIVER_NAME;
card->dev = dev;
card->dapm_widgets = sc7180_snd_widgets;
card->num_dapm_widgets = ARRAY_SIZE(sc7180_snd_widgets);
ret = qcom_snd_parse_of(card);
if (ret)
return ret;
sc7180_add_ops(card);
return devm_snd_soc_register_card(dev, card);
}
static const struct of_device_id sc7180_snd_device_id[] = {
{ .compatible = "google,sc7180-trogdor"},
{},
};
MODULE_DEVICE_TABLE(of, sc7180_snd_device_id);
static struct platform_driver sc7180_snd_driver = {
.probe = sc7180_snd_platform_probe,
.driver = {
.name = "msm-snd-sc7180",
.of_match_table = sc7180_snd_device_id,
},
};
module_platform_driver(sc7180_snd_driver);
MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment