240 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// Copyright(c) 2022 Intel Corporation4 5/*6 * sof_ssp_amp.c - ASoc Machine driver for Intel platforms7 * with RT1308/CS35L41 codec.8 */9 10#include <linux/acpi.h>11#include <linux/delay.h>12#include <linux/dmi.h>13#include <linux/module.h>14#include <linux/platform_device.h>15#include <sound/core.h>16#include <sound/jack.h>17#include <sound/pcm.h>18#include <sound/pcm_params.h>19#include <sound/sof.h>20#include "sof_board_helpers.h"21#include "sof_realtek_common.h"22#include "sof_cirrus_common.h"23 24/* Driver-specific board quirks: from bit 0 to 7 */25#define SOF_HDMI_PLAYBACK_PRESENT BIT(0)26 27/* Default: SSP2 */28static unsigned long sof_ssp_amp_quirk = SOF_SSP_PORT_AMP(2);29 30static const struct dmi_system_id chromebook_platforms[] = {31 {32 .ident = "Google Chromebooks",33 .matches = {34 DMI_MATCH(DMI_SYS_VENDOR, "Google"),35 }36 },37 {},38};39 40static int sof_card_late_probe(struct snd_soc_card *card)41{42 return sof_intel_board_card_late_probe(card);43}44 45static struct snd_soc_card sof_ssp_amp_card = {46 .name = "ssp_amp",47 .owner = THIS_MODULE,48 .fully_routed = true,49 .late_probe = sof_card_late_probe,50};51 52/* BE ID defined in sof-tgl-rt1308-hdmi-ssp.m4 */53#define HDMI_IN_BE_ID 054#define SPK_BE_ID 255#define DMIC01_BE_ID 356#define INTEL_HDMI_BE_ID 557/* extra BE links to support no-hdmi-in boards */58#define DMIC16K_BE_ID 459#define BT_OFFLOAD_BE_ID 860 61#define SSP_AMP_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_HDMI_IN, \62 SOF_LINK_AMP, \63 SOF_LINK_DMIC01, \64 SOF_LINK_DMIC16K, \65 SOF_LINK_IDISP_HDMI, \66 SOF_LINK_BT_OFFLOAD, \67 SOF_LINK_NONE)68 69#define SSP_AMP_LINK_IDS SOF_LINK_ORDER(HDMI_IN_BE_ID, \70 SPK_BE_ID, \71 DMIC01_BE_ID, \72 DMIC16K_BE_ID, \73 INTEL_HDMI_BE_ID, \74 BT_OFFLOAD_BE_ID, \75 0)76 77static int78sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,79 struct sof_card_private *ctx)80{81 int ret;82 83 ret = sof_intel_board_set_dai_link(dev, card, ctx);84 if (ret)85 return ret;86 87 if (ctx->amp_type == CODEC_NONE)88 return 0;89 90 if (!ctx->amp_link) {91 dev_err(dev, "amp link not available");92 return -EINVAL;93 }94 95 /* codec-specific fields for speaker amplifier */96 switch (ctx->amp_type) {97 case CODEC_CS35L41:98 cs35l41_set_dai_link(ctx->amp_link);99 break;100 case CODEC_RT1308:101 sof_rt1308_dai_link(ctx->amp_link);102 break;103 default:104 dev_err(dev, "invalid amp type %d\n", ctx->amp_type);105 return -EINVAL;106 }107 108 return 0;109}110 111static int sof_ssp_amp_probe(struct platform_device *pdev)112{113 struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;114 struct sof_card_private *ctx;115 int ret;116 117 if (pdev->id_entry && pdev->id_entry->driver_data)118 sof_ssp_amp_quirk = (unsigned long)pdev->id_entry->driver_data;119 120 dev_dbg(&pdev->dev, "sof_ssp_amp_quirk = %lx\n", sof_ssp_amp_quirk);121 122 /* initialize ctx with board quirk */123 ctx = sof_intel_board_get_ctx(&pdev->dev, sof_ssp_amp_quirk);124 if (!ctx)125 return -ENOMEM;126 127 if (!dmi_check_system(chromebook_platforms) &&128 (mach->mach_params.dmic_num == 0))129 ctx->dmic_be_num = 0;130 131 if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) {132 if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)133 ctx->hdmi.idisp_codec = true;134 } else {135 ctx->hdmi_num = 0;136 }137 138 ctx->link_order_overwrite = SSP_AMP_LINK_ORDER;139 140 if (ctx->ssp_mask_hdmi_in) {141 /* the topology supports HDMI-IN uses fixed BE ID for DAI links */142 ctx->link_id_overwrite = SSP_AMP_LINK_IDS;143 }144 145 /* update dai_link */146 ret = sof_card_dai_links_create(&pdev->dev, &sof_ssp_amp_card, ctx);147 if (ret)148 return ret;149 150 /* update codec_conf */151 switch (ctx->amp_type) {152 case CODEC_CS35L41:153 cs35l41_set_codec_conf(&sof_ssp_amp_card);154 break;155 case CODEC_RT1308:156 case CODEC_NONE:157 /* no codec conf required */158 break;159 default:160 dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);161 return -EINVAL;162 }163 164 sof_ssp_amp_card.dev = &pdev->dev;165 166 /* set platform name for each dailink */167 ret = snd_soc_fixup_dai_links_platform_name(&sof_ssp_amp_card,168 mach->mach_params.platform);169 if (ret)170 return ret;171 172 snd_soc_card_set_drvdata(&sof_ssp_amp_card, ctx);173 174 return devm_snd_soc_register_card(&pdev->dev, &sof_ssp_amp_card);175}176 177static const struct platform_device_id board_ids[] = {178 {179 .name = "sof_ssp_amp",180 },181 {182 .name = "tgl_rt1308_hdmi_ssp",183 .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_AMP(2) |184 SOF_SSP_MASK_HDMI_CAPTURE(0x22)),185 /* SSP 1 and SSP 5 are used for HDMI IN */186 },187 {188 .name = "adl_cs35l41",189 .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_AMP(1) |190 SOF_NUM_IDISP_HDMI(4) |191 SOF_HDMI_PLAYBACK_PRESENT |192 SOF_SSP_PORT_BT_OFFLOAD(2) |193 SOF_BT_OFFLOAD_PRESENT),194 },195 {196 .name = "adl_lt6911_hdmi_ssp",197 .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) |198 /* SSP 0 and SSP 2 are used for HDMI IN */199 SOF_HDMI_PLAYBACK_PRESENT),200 },201 {202 .name = "rpl_lt6911_hdmi_ssp",203 .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) |204 /* SSP 0 and SSP 2 are used for HDMI IN */205 SOF_HDMI_PLAYBACK_PRESENT),206 },207 {208 .name = "mtl_lt6911_hdmi_ssp",209 .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) |210 /* SSP 0 and SSP 2 are used for HDMI IN */211 SOF_HDMI_PLAYBACK_PRESENT),212 },213 {214 .name = "arl_lt6911_hdmi_ssp",215 .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) |216 /* SSP 0 and SSP 2 are used for HDMI IN */217 SOF_HDMI_PLAYBACK_PRESENT),218 },219 { }220};221MODULE_DEVICE_TABLE(platform, board_ids);222 223static struct platform_driver sof_ssp_amp_driver = {224 .probe = sof_ssp_amp_probe,225 .driver = {226 .name = "sof_ssp_amp",227 .pm = &snd_soc_pm_ops,228 },229 .id_table = board_ids,230};231module_platform_driver(sof_ssp_amp_driver);232 233MODULE_DESCRIPTION("ASoC Intel(R) SOF Amplifier Machine driver");234MODULE_AUTHOR("Balamurugan C <balamurugan.c@intel.com>");235MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");236MODULE_LICENSE("GPL");237MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);238MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);239MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_CIRRUS_COMMON);240