18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// PCM3060 codec driver 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 98c2ecf20Sopenharmony_ci#include <sound/soc.h> 108c2ecf20Sopenharmony_ci#include <sound/tlv.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "pcm3060.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* dai */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic int pcm3060_set_sysclk(struct snd_soc_dai *dai, int clk_id, 178c2ecf20Sopenharmony_ci unsigned int freq, int dir) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci struct snd_soc_component *comp = dai->component; 208c2ecf20Sopenharmony_ci struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp); 218c2ecf20Sopenharmony_ci unsigned int reg; 228c2ecf20Sopenharmony_ci unsigned int val; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci if (dir != SND_SOC_CLOCK_IN) { 258c2ecf20Sopenharmony_ci dev_err(comp->dev, "unsupported sysclock dir: %d\n", dir); 268c2ecf20Sopenharmony_ci return -EINVAL; 278c2ecf20Sopenharmony_ci } 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci switch (clk_id) { 308c2ecf20Sopenharmony_ci case PCM3060_CLK_DEF: 318c2ecf20Sopenharmony_ci val = 0; 328c2ecf20Sopenharmony_ci break; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci case PCM3060_CLK1: 358c2ecf20Sopenharmony_ci val = (dai->id == PCM3060_DAI_ID_DAC ? PCM3060_REG_CSEL : 0); 368c2ecf20Sopenharmony_ci break; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci case PCM3060_CLK2: 398c2ecf20Sopenharmony_ci val = (dai->id == PCM3060_DAI_ID_DAC ? 0 : PCM3060_REG_CSEL); 408c2ecf20Sopenharmony_ci break; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci default: 438c2ecf20Sopenharmony_ci dev_err(comp->dev, "unsupported sysclock id: %d\n", clk_id); 448c2ecf20Sopenharmony_ci return -EINVAL; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (dai->id == PCM3060_DAI_ID_DAC) 488c2ecf20Sopenharmony_ci reg = PCM3060_REG67; 498c2ecf20Sopenharmony_ci else 508c2ecf20Sopenharmony_ci reg = PCM3060_REG72; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci regmap_update_bits(priv->regmap, reg, PCM3060_REG_CSEL, val); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci priv->dai[dai->id].sclk_freq = freq; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int pcm3060_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci struct snd_soc_component *comp = dai->component; 628c2ecf20Sopenharmony_ci struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp); 638c2ecf20Sopenharmony_ci unsigned int reg; 648c2ecf20Sopenharmony_ci unsigned int val; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) { 678c2ecf20Sopenharmony_ci dev_err(comp->dev, "unsupported DAI polarity: 0x%x\n", fmt); 688c2ecf20Sopenharmony_ci return -EINVAL; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 728c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 738c2ecf20Sopenharmony_ci priv->dai[dai->id].is_master = true; 748c2ecf20Sopenharmony_ci break; 758c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 768c2ecf20Sopenharmony_ci priv->dai[dai->id].is_master = false; 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci default: 798c2ecf20Sopenharmony_ci dev_err(comp->dev, "unsupported DAI master mode: 0x%x\n", fmt); 808c2ecf20Sopenharmony_ci return -EINVAL; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 848c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 858c2ecf20Sopenharmony_ci val = PCM3060_REG_FMT_I2S; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 888c2ecf20Sopenharmony_ci val = PCM3060_REG_FMT_RJ; 898c2ecf20Sopenharmony_ci break; 908c2ecf20Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 918c2ecf20Sopenharmony_ci val = PCM3060_REG_FMT_LJ; 928c2ecf20Sopenharmony_ci break; 938c2ecf20Sopenharmony_ci default: 948c2ecf20Sopenharmony_ci dev_err(comp->dev, "unsupported DAI format: 0x%x\n", fmt); 958c2ecf20Sopenharmony_ci return -EINVAL; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (dai->id == PCM3060_DAI_ID_DAC) 998c2ecf20Sopenharmony_ci reg = PCM3060_REG67; 1008c2ecf20Sopenharmony_ci else 1018c2ecf20Sopenharmony_ci reg = PCM3060_REG72; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci regmap_update_bits(priv->regmap, reg, PCM3060_REG_MASK_FMT, val); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic int pcm3060_hw_params(struct snd_pcm_substream *substream, 1098c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params, 1108c2ecf20Sopenharmony_ci struct snd_soc_dai *dai) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct snd_soc_component *comp = dai->component; 1138c2ecf20Sopenharmony_ci struct pcm3060_priv *priv = snd_soc_component_get_drvdata(comp); 1148c2ecf20Sopenharmony_ci unsigned int rate; 1158c2ecf20Sopenharmony_ci unsigned int ratio; 1168c2ecf20Sopenharmony_ci unsigned int reg; 1178c2ecf20Sopenharmony_ci unsigned int val; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (!priv->dai[dai->id].is_master) { 1208c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_S; 1218c2ecf20Sopenharmony_ci goto val_ready; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci rate = params_rate(params); 1258c2ecf20Sopenharmony_ci if (!rate) { 1268c2ecf20Sopenharmony_ci dev_err(comp->dev, "rate is not configured\n"); 1278c2ecf20Sopenharmony_ci return -EINVAL; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci ratio = priv->dai[dai->id].sclk_freq / rate; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci switch (ratio) { 1338c2ecf20Sopenharmony_ci case 768: 1348c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_M768; 1358c2ecf20Sopenharmony_ci break; 1368c2ecf20Sopenharmony_ci case 512: 1378c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_M512; 1388c2ecf20Sopenharmony_ci break; 1398c2ecf20Sopenharmony_ci case 384: 1408c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_M384; 1418c2ecf20Sopenharmony_ci break; 1428c2ecf20Sopenharmony_ci case 256: 1438c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_M256; 1448c2ecf20Sopenharmony_ci break; 1458c2ecf20Sopenharmony_ci case 192: 1468c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_M192; 1478c2ecf20Sopenharmony_ci break; 1488c2ecf20Sopenharmony_ci case 128: 1498c2ecf20Sopenharmony_ci val = PCM3060_REG_MS_M128; 1508c2ecf20Sopenharmony_ci break; 1518c2ecf20Sopenharmony_ci default: 1528c2ecf20Sopenharmony_ci dev_err(comp->dev, "unsupported ratio: %d\n", ratio); 1538c2ecf20Sopenharmony_ci return -EINVAL; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cival_ready: 1578c2ecf20Sopenharmony_ci if (dai->id == PCM3060_DAI_ID_DAC) 1588c2ecf20Sopenharmony_ci reg = PCM3060_REG67; 1598c2ecf20Sopenharmony_ci else 1608c2ecf20Sopenharmony_ci reg = PCM3060_REG72; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci regmap_update_bits(priv->regmap, reg, PCM3060_REG_MASK_MS, val); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci return 0; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops pcm3060_dai_ops = { 1688c2ecf20Sopenharmony_ci .set_sysclk = pcm3060_set_sysclk, 1698c2ecf20Sopenharmony_ci .set_fmt = pcm3060_set_fmt, 1708c2ecf20Sopenharmony_ci .hw_params = pcm3060_hw_params, 1718c2ecf20Sopenharmony_ci}; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#define PCM3060_DAI_RATES_ADC (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | \ 1748c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ 1758c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci#define PCM3060_DAI_RATES_DAC (PCM3060_DAI_RATES_ADC | \ 1788c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver pcm3060_dai[] = { 1818c2ecf20Sopenharmony_ci { 1828c2ecf20Sopenharmony_ci .name = "pcm3060-dac", 1838c2ecf20Sopenharmony_ci .id = PCM3060_DAI_ID_DAC, 1848c2ecf20Sopenharmony_ci .playback = { 1858c2ecf20Sopenharmony_ci .stream_name = "Playback", 1868c2ecf20Sopenharmony_ci .channels_min = 2, 1878c2ecf20Sopenharmony_ci .channels_max = 2, 1888c2ecf20Sopenharmony_ci .rates = PCM3060_DAI_RATES_DAC, 1898c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S24_LE, 1908c2ecf20Sopenharmony_ci }, 1918c2ecf20Sopenharmony_ci .ops = &pcm3060_dai_ops, 1928c2ecf20Sopenharmony_ci }, 1938c2ecf20Sopenharmony_ci { 1948c2ecf20Sopenharmony_ci .name = "pcm3060-adc", 1958c2ecf20Sopenharmony_ci .id = PCM3060_DAI_ID_ADC, 1968c2ecf20Sopenharmony_ci .capture = { 1978c2ecf20Sopenharmony_ci .stream_name = "Capture", 1988c2ecf20Sopenharmony_ci .channels_min = 2, 1998c2ecf20Sopenharmony_ci .channels_max = 2, 2008c2ecf20Sopenharmony_ci .rates = PCM3060_DAI_RATES_ADC, 2018c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S24_LE, 2028c2ecf20Sopenharmony_ci }, 2038c2ecf20Sopenharmony_ci .ops = &pcm3060_dai_ops, 2048c2ecf20Sopenharmony_ci }, 2058c2ecf20Sopenharmony_ci}; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/* dapm */ 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(pcm3060_dapm_tlv, -10050, 50, 1); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new pcm3060_dapm_controls[] = { 2128c2ecf20Sopenharmony_ci SOC_DOUBLE_R_RANGE_TLV("Master Playback Volume", 2138c2ecf20Sopenharmony_ci PCM3060_REG65, PCM3060_REG66, 0, 2148c2ecf20Sopenharmony_ci PCM3060_REG_AT2_MIN, PCM3060_REG_AT2_MAX, 2158c2ecf20Sopenharmony_ci 0, pcm3060_dapm_tlv), 2168c2ecf20Sopenharmony_ci SOC_DOUBLE("Master Playback Switch", PCM3060_REG68, 2178c2ecf20Sopenharmony_ci PCM3060_REG_SHIFT_MUT21, PCM3060_REG_SHIFT_MUT22, 1, 1), 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci SOC_DOUBLE_R_RANGE_TLV("Master Capture Volume", 2208c2ecf20Sopenharmony_ci PCM3060_REG70, PCM3060_REG71, 0, 2218c2ecf20Sopenharmony_ci PCM3060_REG_AT1_MIN, PCM3060_REG_AT1_MAX, 2228c2ecf20Sopenharmony_ci 0, pcm3060_dapm_tlv), 2238c2ecf20Sopenharmony_ci SOC_DOUBLE("Master Capture Switch", PCM3060_REG73, 2248c2ecf20Sopenharmony_ci PCM3060_REG_SHIFT_MUT11, PCM3060_REG_SHIFT_MUT12, 1, 1), 2258c2ecf20Sopenharmony_ci}; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget pcm3060_dapm_widgets[] = { 2288c2ecf20Sopenharmony_ci SND_SOC_DAPM_DAC("DAC", "Playback", PCM3060_REG64, 2298c2ecf20Sopenharmony_ci PCM3060_REG_SHIFT_DAPSV, 1), 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUTL"), 2328c2ecf20Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUTR"), 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("INL"), 2358c2ecf20Sopenharmony_ci SND_SOC_DAPM_INPUT("INR"), 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci SND_SOC_DAPM_ADC("ADC", "Capture", PCM3060_REG64, 2388c2ecf20Sopenharmony_ci PCM3060_REG_SHIFT_ADPSV, 1), 2398c2ecf20Sopenharmony_ci}; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route pcm3060_dapm_map[] = { 2428c2ecf20Sopenharmony_ci { "OUTL", NULL, "DAC" }, 2438c2ecf20Sopenharmony_ci { "OUTR", NULL, "DAC" }, 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci { "ADC", NULL, "INL" }, 2468c2ecf20Sopenharmony_ci { "ADC", NULL, "INR" }, 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/* soc component */ 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver pcm3060_soc_comp_driver = { 2528c2ecf20Sopenharmony_ci .controls = pcm3060_dapm_controls, 2538c2ecf20Sopenharmony_ci .num_controls = ARRAY_SIZE(pcm3060_dapm_controls), 2548c2ecf20Sopenharmony_ci .dapm_widgets = pcm3060_dapm_widgets, 2558c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(pcm3060_dapm_widgets), 2568c2ecf20Sopenharmony_ci .dapm_routes = pcm3060_dapm_map, 2578c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(pcm3060_dapm_map), 2588c2ecf20Sopenharmony_ci}; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/* regmap */ 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cistatic bool pcm3060_reg_writeable(struct device *dev, unsigned int reg) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci return (reg >= PCM3060_REG64); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic bool pcm3060_reg_readable(struct device *dev, unsigned int reg) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci return (reg >= PCM3060_REG64); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic bool pcm3060_reg_volatile(struct device *dev, unsigned int reg) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci /* PCM3060_REG64 is volatile */ 2758c2ecf20Sopenharmony_ci return (reg == PCM3060_REG64); 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic const struct reg_default pcm3060_reg_defaults[] = { 2798c2ecf20Sopenharmony_ci { PCM3060_REG64, 0xF0 }, 2808c2ecf20Sopenharmony_ci { PCM3060_REG65, 0xFF }, 2818c2ecf20Sopenharmony_ci { PCM3060_REG66, 0xFF }, 2828c2ecf20Sopenharmony_ci { PCM3060_REG67, 0x00 }, 2838c2ecf20Sopenharmony_ci { PCM3060_REG68, 0x00 }, 2848c2ecf20Sopenharmony_ci { PCM3060_REG69, 0x00 }, 2858c2ecf20Sopenharmony_ci { PCM3060_REG70, 0xD7 }, 2868c2ecf20Sopenharmony_ci { PCM3060_REG71, 0xD7 }, 2878c2ecf20Sopenharmony_ci { PCM3060_REG72, 0x00 }, 2888c2ecf20Sopenharmony_ci { PCM3060_REG73, 0x00 }, 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ciconst struct regmap_config pcm3060_regmap = { 2928c2ecf20Sopenharmony_ci .reg_bits = 8, 2938c2ecf20Sopenharmony_ci .val_bits = 8, 2948c2ecf20Sopenharmony_ci .writeable_reg = pcm3060_reg_writeable, 2958c2ecf20Sopenharmony_ci .readable_reg = pcm3060_reg_readable, 2968c2ecf20Sopenharmony_ci .volatile_reg = pcm3060_reg_volatile, 2978c2ecf20Sopenharmony_ci .max_register = PCM3060_REG73, 2988c2ecf20Sopenharmony_ci .reg_defaults = pcm3060_reg_defaults, 2998c2ecf20Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(pcm3060_reg_defaults), 3008c2ecf20Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 3018c2ecf20Sopenharmony_ci}; 3028c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pcm3060_regmap); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci/* device */ 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic void pcm3060_parse_dt(const struct device_node *np, 3078c2ecf20Sopenharmony_ci struct pcm3060_priv *priv) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci priv->out_se = of_property_read_bool(np, "ti,out-single-ended"); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ciint pcm3060_probe(struct device *dev) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci int rc; 3158c2ecf20Sopenharmony_ci struct pcm3060_priv *priv = dev_get_drvdata(dev); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* soft reset */ 3188c2ecf20Sopenharmony_ci rc = regmap_update_bits(priv->regmap, PCM3060_REG64, 3198c2ecf20Sopenharmony_ci PCM3060_REG_MRST, 0); 3208c2ecf20Sopenharmony_ci if (rc) { 3218c2ecf20Sopenharmony_ci dev_err(dev, "failed to reset component, rc=%d\n", rc); 3228c2ecf20Sopenharmony_ci return rc; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (dev->of_node) 3268c2ecf20Sopenharmony_ci pcm3060_parse_dt(dev->of_node, priv); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci if (priv->out_se) 3298c2ecf20Sopenharmony_ci regmap_update_bits(priv->regmap, PCM3060_REG64, 3308c2ecf20Sopenharmony_ci PCM3060_REG_SE, PCM3060_REG_SE); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci rc = devm_snd_soc_register_component(dev, &pcm3060_soc_comp_driver, 3338c2ecf20Sopenharmony_ci pcm3060_dai, 3348c2ecf20Sopenharmony_ci ARRAY_SIZE(pcm3060_dai)); 3358c2ecf20Sopenharmony_ci if (rc) { 3368c2ecf20Sopenharmony_ci dev_err(dev, "failed to register component, rc=%d\n", rc); 3378c2ecf20Sopenharmony_ci return rc; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci return 0; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pcm3060_probe); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCM3060 codec driver"); 3458c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>"); 3468c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 347