2783 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * cs43130.c -- CS43130 ALSA Soc Audio driver4 *5 * Copyright 2017 Cirrus Logic, Inc.6 *7 * Authors: Li Xu <li.xu@cirrus.com>8 */9#include <linux/module.h>10#include <linux/moduleparam.h>11#include <linux/kernel.h>12#include <linux/init.h>13#include <linux/delay.h>14#include <linux/gpio/consumer.h>15#include <linux/platform_device.h>16#include <linux/pm.h>17#include <linux/i2c.h>18#include <linux/property.h>19#include <linux/regmap.h>20#include <linux/slab.h>21#include <sound/core.h>22#include <sound/pcm.h>23#include <sound/pcm_params.h>24#include <sound/soc.h>25#include <sound/soc-dapm.h>26#include <sound/initval.h>27#include <sound/tlv.h>28#include <linux/regulator/consumer.h>29#include <linux/pm_runtime.h>30#include <linux/completion.h>31#include <linux/mutex.h>32#include <linux/workqueue.h>33#include <sound/jack.h>34 35#include "cs43130.h"36#include "cirrus_legacy.h"37 38static const struct reg_default cs43130_reg_defaults[] = {39 {CS43130_SYS_CLK_CTL_1, 0x06},40 {CS43130_SP_SRATE, 0x01},41 {CS43130_SP_BITSIZE, 0x05},42 {CS43130_PAD_INT_CFG, 0x03},43 {CS43130_PWDN_CTL, 0xFE},44 {CS43130_CRYSTAL_SET, 0x04},45 {CS43130_PLL_SET_1, 0x00},46 {CS43130_PLL_SET_2, 0x00},47 {CS43130_PLL_SET_3, 0x00},48 {CS43130_PLL_SET_4, 0x00},49 {CS43130_PLL_SET_5, 0x40},50 {CS43130_PLL_SET_6, 0x10},51 {CS43130_PLL_SET_7, 0x80},52 {CS43130_PLL_SET_8, 0x03},53 {CS43130_PLL_SET_9, 0x02},54 {CS43130_PLL_SET_10, 0x02},55 {CS43130_CLKOUT_CTL, 0x00},56 {CS43130_ASP_NUM_1, 0x01},57 {CS43130_ASP_NUM_2, 0x00},58 {CS43130_ASP_DEN_1, 0x08},59 {CS43130_ASP_DEN_2, 0x00},60 {CS43130_ASP_LRCK_HI_TIME_1, 0x1F},61 {CS43130_ASP_LRCK_HI_TIME_2, 0x00},62 {CS43130_ASP_LRCK_PERIOD_1, 0x3F},63 {CS43130_ASP_LRCK_PERIOD_2, 0x00},64 {CS43130_ASP_CLOCK_CONF, 0x0C},65 {CS43130_ASP_FRAME_CONF, 0x0A},66 {CS43130_XSP_NUM_1, 0x01},67 {CS43130_XSP_NUM_2, 0x00},68 {CS43130_XSP_DEN_1, 0x02},69 {CS43130_XSP_DEN_2, 0x00},70 {CS43130_XSP_LRCK_HI_TIME_1, 0x1F},71 {CS43130_XSP_LRCK_HI_TIME_2, 0x00},72 {CS43130_XSP_LRCK_PERIOD_1, 0x3F},73 {CS43130_XSP_LRCK_PERIOD_2, 0x00},74 {CS43130_XSP_CLOCK_CONF, 0x0C},75 {CS43130_XSP_FRAME_CONF, 0x0A},76 {CS43130_ASP_CH_1_LOC, 0x00},77 {CS43130_ASP_CH_2_LOC, 0x00},78 {CS43130_ASP_CH_1_SZ_EN, 0x06},79 {CS43130_ASP_CH_2_SZ_EN, 0x0E},80 {CS43130_XSP_CH_1_LOC, 0x00},81 {CS43130_XSP_CH_2_LOC, 0x00},82 {CS43130_XSP_CH_1_SZ_EN, 0x06},83 {CS43130_XSP_CH_2_SZ_EN, 0x0E},84 {CS43130_DSD_VOL_B, 0x78},85 {CS43130_DSD_VOL_A, 0x78},86 {CS43130_DSD_PATH_CTL_1, 0xA8},87 {CS43130_DSD_INT_CFG, 0x00},88 {CS43130_DSD_PATH_CTL_2, 0x02},89 {CS43130_DSD_PCM_MIX_CTL, 0x00},90 {CS43130_DSD_PATH_CTL_3, 0x40},91 {CS43130_HP_OUT_CTL_1, 0x30},92 {CS43130_PCM_FILT_OPT, 0x02},93 {CS43130_PCM_VOL_B, 0x78},94 {CS43130_PCM_VOL_A, 0x78},95 {CS43130_PCM_PATH_CTL_1, 0xA8},96 {CS43130_PCM_PATH_CTL_2, 0x00},97 {CS43130_CLASS_H_CTL, 0x1E},98 {CS43130_HP_DETECT, 0x04},99 {CS43130_HP_LOAD_1, 0x00},100 {CS43130_HP_MEAS_LOAD_1, 0x00},101 {CS43130_HP_MEAS_LOAD_2, 0x00},102 {CS43130_INT_MASK_1, 0xFF},103 {CS43130_INT_MASK_2, 0xFF},104 {CS43130_INT_MASK_3, 0xFF},105 {CS43130_INT_MASK_4, 0xFF},106 {CS43130_INT_MASK_5, 0xFF},107};108 109static bool cs43130_volatile_register(struct device *dev, unsigned int reg)110{111 switch (reg) {112 case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:113 case CS43130_HP_DC_STAT_1 ... CS43130_HP_DC_STAT_2:114 case CS43130_HP_AC_STAT_1 ... CS43130_HP_AC_STAT_2:115 return true;116 default:117 return false;118 }119}120 121static bool cs43130_readable_register(struct device *dev, unsigned int reg)122{123 switch (reg) {124 case CS43130_DEVID_AB ... CS43130_SYS_CLK_CTL_1:125 case CS43130_SP_SRATE ... CS43130_PAD_INT_CFG:126 case CS43130_PWDN_CTL:127 case CS43130_CRYSTAL_SET:128 case CS43130_PLL_SET_1 ... CS43130_PLL_SET_5:129 case CS43130_PLL_SET_6:130 case CS43130_PLL_SET_7:131 case CS43130_PLL_SET_8:132 case CS43130_PLL_SET_9:133 case CS43130_PLL_SET_10:134 case CS43130_CLKOUT_CTL:135 case CS43130_ASP_NUM_1 ... CS43130_ASP_FRAME_CONF:136 case CS43130_XSP_NUM_1 ... CS43130_XSP_FRAME_CONF:137 case CS43130_ASP_CH_1_LOC:138 case CS43130_ASP_CH_2_LOC:139 case CS43130_ASP_CH_1_SZ_EN:140 case CS43130_ASP_CH_2_SZ_EN:141 case CS43130_XSP_CH_1_LOC:142 case CS43130_XSP_CH_2_LOC:143 case CS43130_XSP_CH_1_SZ_EN:144 case CS43130_XSP_CH_2_SZ_EN:145 case CS43130_DSD_VOL_B ... CS43130_DSD_PATH_CTL_3:146 case CS43130_HP_OUT_CTL_1:147 case CS43130_PCM_FILT_OPT ... CS43130_PCM_PATH_CTL_2:148 case CS43130_CLASS_H_CTL:149 case CS43130_HP_DETECT:150 case CS43130_HP_STATUS:151 case CS43130_HP_LOAD_1:152 case CS43130_HP_MEAS_LOAD_1:153 case CS43130_HP_MEAS_LOAD_2:154 case CS43130_HP_DC_STAT_1:155 case CS43130_HP_DC_STAT_2:156 case CS43130_HP_AC_STAT_1:157 case CS43130_HP_AC_STAT_2:158 case CS43130_HP_LOAD_STAT:159 case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:160 case CS43130_INT_MASK_1 ... CS43130_INT_MASK_5:161 return true;162 default:163 return false;164 }165}166 167static bool cs43130_precious_register(struct device *dev, unsigned int reg)168{169 switch (reg) {170 case CS43130_INT_STATUS_1 ... CS43130_INT_STATUS_5:171 return true;172 default:173 return false;174 }175}176 177struct cs43130_pll_params {178 unsigned int pll_in;179 u8 sclk_prediv;180 u8 pll_div_int;181 u32 pll_div_frac;182 u8 pll_mode;183 u8 pll_divout;184 unsigned int pll_out;185 u8 pll_cal_ratio;186};187 188static const struct cs43130_pll_params pll_ratio_table[] = {189 {9600000, 0x02, 0x49, 0x800000, 0x00, 0x08, 22579200, 151},190 {9600000, 0x02, 0x50, 0x000000, 0x00, 0x08, 24576000, 164},191 192 {11289600, 0x02, 0X40, 0, 0x01, 0x08, 22579200, 128},193 {11289600, 0x02, 0x44, 0x06F700, 0x0, 0x08, 24576000, 139},194 195 {12000000, 0x02, 0x49, 0x800000, 0x00, 0x0A, 22579200, 120},196 {12000000, 0x02, 0x40, 0x000000, 0x00, 0x08, 24576000, 131},197 198 {12288000, 0x02, 0x49, 0x800000, 0x01, 0x0A, 22579200, 118},199 {12288000, 0x02, 0x40, 0x000000, 0x01, 0x08, 24576000, 128},200 201 {13000000, 0x02, 0x45, 0x797680, 0x01, 0x0A, 22579200, 111},202 {13000000, 0x02, 0x3C, 0x7EA940, 0x01, 0x08, 24576000, 121},203 204 {19200000, 0x03, 0x49, 0x800000, 0x00, 0x08, 22579200, 151},205 {19200000, 0x03, 0x50, 0x000000, 0x00, 0x08, 24576000, 164},206 207 {22579200, 0, 0, 0, 0, 0, 22579200, 0},208 {22579200, 0x03, 0x44, 0x06F700, 0x00, 0x08, 24576000, 139},209 210 {24000000, 0x03, 0x49, 0x800000, 0x00, 0x0A, 22579200, 120},211 {24000000, 0x03, 0x40, 0x000000, 0x00, 0x08, 24576000, 131},212 213 {24576000, 0x03, 0x49, 0x800000, 0x01, 0x0A, 22579200, 118},214 {24576000, 0, 0, 0, 0, 0, 24576000, 0},215 216 {26000000, 0x03, 0x45, 0x797680, 0x01, 0x0A, 22579200, 111},217 {26000000, 0x03, 0x3C, 0x7EA940, 0x01, 0x08, 24576000, 121},218};219 220static const struct cs43130_pll_params *cs43130_get_pll_table(221 unsigned int freq_in, unsigned int freq_out)222{223 int i;224 225 for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {226 if (pll_ratio_table[i].pll_in == freq_in &&227 pll_ratio_table[i].pll_out == freq_out)228 return &pll_ratio_table[i];229 }230 231 return NULL;232}233 234static int cs43130_pll_config(struct snd_soc_component *component)235{236 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);237 const struct cs43130_pll_params *pll_entry;238 239 dev_dbg(cs43130->dev, "cs43130->mclk = %u, cs43130->mclk_int = %u\n",240 cs43130->mclk, cs43130->mclk_int);241 242 pll_entry = cs43130_get_pll_table(cs43130->mclk, cs43130->mclk_int);243 if (!pll_entry)244 return -EINVAL;245 246 if (pll_entry->pll_cal_ratio == 0) {247 regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_1,248 CS43130_PLL_START_MASK, 0);249 250 cs43130->pll_bypass = true;251 return 0;252 }253 254 cs43130->pll_bypass = false;255 256 regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_2,257 CS43130_PLL_DIV_DATA_MASK,258 pll_entry->pll_div_frac >>259 CS43130_PLL_DIV_FRAC_0_DATA_SHIFT);260 regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_3,261 CS43130_PLL_DIV_DATA_MASK,262 pll_entry->pll_div_frac >>263 CS43130_PLL_DIV_FRAC_1_DATA_SHIFT);264 regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_4,265 CS43130_PLL_DIV_DATA_MASK,266 pll_entry->pll_div_frac >>267 CS43130_PLL_DIV_FRAC_2_DATA_SHIFT);268 regmap_write(cs43130->regmap, CS43130_PLL_SET_5,269 pll_entry->pll_div_int);270 regmap_write(cs43130->regmap, CS43130_PLL_SET_6, pll_entry->pll_divout);271 regmap_write(cs43130->regmap, CS43130_PLL_SET_7,272 pll_entry->pll_cal_ratio);273 regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_8,274 CS43130_PLL_MODE_MASK,275 pll_entry->pll_mode << CS43130_PLL_MODE_SHIFT);276 regmap_write(cs43130->regmap, CS43130_PLL_SET_9,277 pll_entry->sclk_prediv);278 regmap_update_bits(cs43130->regmap, CS43130_PLL_SET_1,279 CS43130_PLL_START_MASK, 1);280 281 return 0;282}283 284static int cs43130_set_pll(struct snd_soc_component *component, int pll_id, int source,285 unsigned int freq_in, unsigned int freq_out)286{287 int ret = 0;288 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);289 290 switch (freq_in) {291 case 9600000:292 case 11289600:293 case 12000000:294 case 12288000:295 case 13000000:296 case 19200000:297 case 22579200:298 case 24000000:299 case 24576000:300 case 26000000:301 cs43130->mclk = freq_in;302 break;303 default:304 dev_err(cs43130->dev,305 "unsupported pll input reference clock:%d\n", freq_in);306 return -EINVAL;307 }308 309 switch (freq_out) {310 case 22579200:311 cs43130->mclk_int = freq_out;312 break;313 case 24576000:314 cs43130->mclk_int = freq_out;315 break;316 default:317 dev_err(cs43130->dev,318 "unsupported pll output ref clock: %u\n", freq_out);319 return -EINVAL;320 }321 322 ret = cs43130_pll_config(component);323 dev_dbg(cs43130->dev, "cs43130->pll_bypass = %d", cs43130->pll_bypass);324 return ret;325}326 327static int cs43130_wait_for_completion(struct cs43130_private *cs43130, struct completion *to_poll,328 int time)329{330 int stickies, offset, flag, ret;331 332 if (cs43130->has_irq_line) {333 ret = wait_for_completion_timeout(to_poll, msecs_to_jiffies(time));334 if (ret == 0)335 return -ETIMEDOUT;336 else337 return 0; // Discard number of jiffies left till timeout and return success338 }339 340 if (to_poll == &cs43130->xtal_rdy) {341 offset = 0;342 flag = CS43130_XTAL_RDY_INT;343 } else if (to_poll == &cs43130->pll_rdy) {344 offset = 0;345 flag = CS43130_PLL_RDY_INT;346 } else {347 return -EINVAL;348 }349 350 return regmap_read_poll_timeout(cs43130->regmap, CS43130_INT_STATUS_1 + offset,351 stickies, (stickies & flag),352 1000, time * 1000);353}354 355static int cs43130_change_clksrc(struct snd_soc_component *component,356 enum cs43130_mclk_src_sel src)357{358 int ret;359 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);360 int mclk_int_decoded;361 362 if (src == cs43130->mclk_int_src) {363 /* clk source has not changed */364 return 0;365 }366 367 switch (cs43130->mclk_int) {368 case CS43130_MCLK_22M:369 mclk_int_decoded = CS43130_MCLK_22P5;370 break;371 case CS43130_MCLK_24M:372 mclk_int_decoded = CS43130_MCLK_24P5;373 break;374 default:375 dev_err(cs43130->dev, "Invalid MCLK INT freq: %u\n", cs43130->mclk_int);376 return -EINVAL;377 }378 379 switch (src) {380 case CS43130_MCLK_SRC_EXT:381 cs43130->pll_bypass = true;382 cs43130->mclk_int_src = CS43130_MCLK_SRC_EXT;383 if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {384 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,385 CS43130_PDN_XTAL_MASK,386 1 << CS43130_PDN_XTAL_SHIFT);387 } else {388 reinit_completion(&cs43130->xtal_rdy);389 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,390 CS43130_XTAL_RDY_INT_MASK, 0);391 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,392 CS43130_PDN_XTAL_MASK, 0);393 ret = cs43130_wait_for_completion(cs43130, &cs43130->xtal_rdy, 100);394 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,395 CS43130_XTAL_RDY_INT_MASK,396 1 << CS43130_XTAL_RDY_INT_SHIFT);397 if (ret) {398 dev_err(cs43130->dev, "Error waiting for XTAL_READY interrupt: %d\n", ret);399 return ret;400 }401 }402 403 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,404 CS43130_MCLK_SRC_SEL_MASK,405 src << CS43130_MCLK_SRC_SEL_SHIFT);406 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,407 CS43130_MCLK_INT_MASK,408 mclk_int_decoded << CS43130_MCLK_INT_SHIFT);409 usleep_range(150, 200);410 411 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,412 CS43130_PDN_PLL_MASK,413 1 << CS43130_PDN_PLL_SHIFT);414 break;415 case CS43130_MCLK_SRC_PLL:416 cs43130->pll_bypass = false;417 cs43130->mclk_int_src = CS43130_MCLK_SRC_PLL;418 if (cs43130->xtal_ibias == CS43130_XTAL_UNUSED) {419 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,420 CS43130_PDN_XTAL_MASK,421 1 << CS43130_PDN_XTAL_SHIFT);422 } else {423 reinit_completion(&cs43130->xtal_rdy);424 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,425 CS43130_XTAL_RDY_INT_MASK, 0);426 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,427 CS43130_PDN_XTAL_MASK, 0);428 ret = cs43130_wait_for_completion(cs43130, &cs43130->xtal_rdy, 100);429 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,430 CS43130_XTAL_RDY_INT_MASK,431 1 << CS43130_XTAL_RDY_INT_SHIFT);432 if (ret) {433 dev_err(cs43130->dev, "Error waiting for XTAL_READY interrupt: %d\n", ret);434 return ret;435 }436 }437 438 reinit_completion(&cs43130->pll_rdy);439 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,440 CS43130_PLL_RDY_INT_MASK, 0);441 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,442 CS43130_PDN_PLL_MASK, 0);443 ret = cs43130_wait_for_completion(cs43130, &cs43130->pll_rdy, 100);444 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,445 CS43130_PLL_RDY_INT_MASK,446 1 << CS43130_PLL_RDY_INT_SHIFT);447 if (ret) {448 dev_err(cs43130->dev, "Error waiting for PLL_READY interrupt: %d\n", ret);449 return ret;450 }451 452 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,453 CS43130_MCLK_SRC_SEL_MASK,454 src << CS43130_MCLK_SRC_SEL_SHIFT);455 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,456 CS43130_MCLK_INT_MASK,457 mclk_int_decoded << CS43130_MCLK_INT_SHIFT);458 usleep_range(150, 200);459 break;460 case CS43130_MCLK_SRC_RCO:461 cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;462 463 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,464 CS43130_MCLK_SRC_SEL_MASK,465 src << CS43130_MCLK_SRC_SEL_SHIFT);466 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1,467 CS43130_MCLK_INT_MASK,468 CS43130_MCLK_22P5 << CS43130_MCLK_INT_SHIFT);469 usleep_range(150, 200);470 471 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,472 CS43130_PDN_XTAL_MASK,473 1 << CS43130_PDN_XTAL_SHIFT);474 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL,475 CS43130_PDN_PLL_MASK,476 1 << CS43130_PDN_PLL_SHIFT);477 break;478 default:479 dev_err(cs43130->dev, "Invalid MCLK source value\n");480 return -EINVAL;481 }482 483 return 0;484}485 486static const struct cs43130_bitwidth_map cs43130_bitwidth_table[] = {487 {8, CS43130_SP_BIT_SIZE_8, CS43130_CH_BIT_SIZE_8},488 {16, CS43130_SP_BIT_SIZE_16, CS43130_CH_BIT_SIZE_16},489 {24, CS43130_SP_BIT_SIZE_24, CS43130_CH_BIT_SIZE_24},490 {32, CS43130_SP_BIT_SIZE_32, CS43130_CH_BIT_SIZE_32},491};492 493static const struct cs43130_bitwidth_map *cs43130_get_bitwidth_table(494 unsigned int bitwidth)495{496 int i;497 498 for (i = 0; i < ARRAY_SIZE(cs43130_bitwidth_table); i++) {499 if (cs43130_bitwidth_table[i].bitwidth == bitwidth)500 return &cs43130_bitwidth_table[i];501 }502 503 return NULL;504}505 506static int cs43130_set_bitwidth(int dai_id, unsigned int bitwidth_dai,507 struct regmap *regmap)508{509 const struct cs43130_bitwidth_map *bw_map;510 511 bw_map = cs43130_get_bitwidth_table(bitwidth_dai);512 if (!bw_map)513 return -EINVAL;514 515 switch (dai_id) {516 case CS43130_ASP_PCM_DAI:517 case CS43130_ASP_DOP_DAI:518 regmap_update_bits(regmap, CS43130_ASP_CH_1_SZ_EN,519 CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);520 regmap_update_bits(regmap, CS43130_ASP_CH_2_SZ_EN,521 CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);522 regmap_update_bits(regmap, CS43130_SP_BITSIZE,523 CS43130_ASP_BITSIZE_MASK, bw_map->sp_bit);524 break;525 case CS43130_XSP_DOP_DAI:526 regmap_update_bits(regmap, CS43130_XSP_CH_1_SZ_EN,527 CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);528 regmap_update_bits(regmap, CS43130_XSP_CH_2_SZ_EN,529 CS43130_CH_BITSIZE_MASK, bw_map->ch_bit);530 regmap_update_bits(regmap, CS43130_SP_BITSIZE,531 CS43130_XSP_BITSIZE_MASK, bw_map->sp_bit <<532 CS43130_XSP_BITSIZE_SHIFT);533 break;534 default:535 return -EINVAL;536 }537 538 return 0;539}540 541static const struct cs43130_rate_map cs43130_rate_table[] = {542 {32000, CS43130_ASP_SPRATE_32K},543 {44100, CS43130_ASP_SPRATE_44_1K},544 {48000, CS43130_ASP_SPRATE_48K},545 {88200, CS43130_ASP_SPRATE_88_2K},546 {96000, CS43130_ASP_SPRATE_96K},547 {176400, CS43130_ASP_SPRATE_176_4K},548 {192000, CS43130_ASP_SPRATE_192K},549 {352800, CS43130_ASP_SPRATE_352_8K},550 {384000, CS43130_ASP_SPRATE_384K},551};552 553static const struct cs43130_rate_map *cs43130_get_rate_table(int fs)554{555 int i;556 557 for (i = 0; i < ARRAY_SIZE(cs43130_rate_table); i++) {558 if (cs43130_rate_table[i].fs == fs)559 return &cs43130_rate_table[i];560 }561 562 return NULL;563}564 565static const struct cs43130_clk_gen *cs43130_get_clk_gen(int mclk_int, int fs,566 const struct cs43130_clk_gen *clk_gen_table, int len_clk_gen_table)567{568 int i;569 570 for (i = 0; i < len_clk_gen_table; i++) {571 if (clk_gen_table[i].mclk_int == mclk_int &&572 clk_gen_table[i].fs == fs)573 return &clk_gen_table[i];574 }575 576 return NULL;577}578 579static int cs43130_set_sp_fmt(int dai_id, unsigned int bitwidth_sclk,580 struct snd_pcm_hw_params *params,581 struct cs43130_private *cs43130)582{583 u16 frm_size;584 u16 hi_size;585 u8 frm_delay;586 u8 frm_phase;587 u8 frm_data;588 u8 sclk_edge;589 u8 lrck_edge;590 u8 clk_data;591 u8 loc_ch1;592 u8 loc_ch2;593 u8 dai_mode_val;594 const struct cs43130_clk_gen *clk_gen;595 596 switch (cs43130->dais[dai_id].dai_format) {597 case SND_SOC_DAIFMT_I2S:598 hi_size = bitwidth_sclk;599 frm_delay = 2;600 frm_phase = 0;601 break;602 case SND_SOC_DAIFMT_LEFT_J:603 hi_size = bitwidth_sclk;604 frm_delay = 0;605 frm_phase = 1;606 break;607 case SND_SOC_DAIFMT_DSP_A:608 hi_size = 1;609 frm_delay = 2;610 frm_phase = 1;611 break;612 case SND_SOC_DAIFMT_DSP_B:613 hi_size = 1;614 frm_delay = 0;615 frm_phase = 1;616 break;617 default:618 return -EINVAL;619 }620 621 switch (cs43130->dais[dai_id].dai_invert) {622 case SND_SOC_DAIFMT_NB_NF:623 sclk_edge = 1;624 lrck_edge = 0;625 break;626 case SND_SOC_DAIFMT_IB_NF:627 sclk_edge = 0;628 lrck_edge = 0;629 break;630 case SND_SOC_DAIFMT_NB_IF:631 sclk_edge = 1;632 lrck_edge = 1;633 break;634 case SND_SOC_DAIFMT_IB_IF:635 sclk_edge = 0;636 lrck_edge = 1;637 break;638 default:639 return -EINVAL;640 }641 642 switch (cs43130->dais[dai_id].dai_mode) {643 case SND_SOC_DAIFMT_CBS_CFS:644 dai_mode_val = 0;645 break;646 case SND_SOC_DAIFMT_CBM_CFM:647 dai_mode_val = 1;648 break;649 default:650 return -EINVAL;651 }652 653 frm_size = bitwidth_sclk * params_channels(params);654 loc_ch1 = 0;655 loc_ch2 = bitwidth_sclk * (params_channels(params) - 1);656 657 frm_data = frm_delay & CS43130_SP_FSD_MASK;658 frm_data |= (frm_phase << CS43130_SP_STP_SHIFT) & CS43130_SP_STP_MASK;659 660 clk_data = lrck_edge & CS43130_SP_LCPOL_IN_MASK;661 clk_data |= (lrck_edge << CS43130_SP_LCPOL_OUT_SHIFT) &662 CS43130_SP_LCPOL_OUT_MASK;663 clk_data |= (sclk_edge << CS43130_SP_SCPOL_IN_SHIFT) &664 CS43130_SP_SCPOL_IN_MASK;665 clk_data |= (sclk_edge << CS43130_SP_SCPOL_OUT_SHIFT) &666 CS43130_SP_SCPOL_OUT_MASK;667 clk_data |= (dai_mode_val << CS43130_SP_MODE_SHIFT) &668 CS43130_SP_MODE_MASK;669 670 switch (dai_id) {671 case CS43130_ASP_PCM_DAI:672 case CS43130_ASP_DOP_DAI:673 regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_1,674 CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>675 CS43130_SP_LCPR_LSB_DATA_SHIFT);676 regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_PERIOD_2,677 CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>678 CS43130_SP_LCPR_MSB_DATA_SHIFT);679 regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_1,680 CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>681 CS43130_SP_LCHI_LSB_DATA_SHIFT);682 regmap_update_bits(cs43130->regmap, CS43130_ASP_LRCK_HI_TIME_2,683 CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>684 CS43130_SP_LCHI_MSB_DATA_SHIFT);685 regmap_write(cs43130->regmap, CS43130_ASP_FRAME_CONF, frm_data);686 regmap_write(cs43130->regmap, CS43130_ASP_CH_1_LOC, loc_ch1);687 regmap_write(cs43130->regmap, CS43130_ASP_CH_2_LOC, loc_ch2);688 regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_1_SZ_EN,689 CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);690 regmap_update_bits(cs43130->regmap, CS43130_ASP_CH_2_SZ_EN,691 CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);692 regmap_write(cs43130->regmap, CS43130_ASP_CLOCK_CONF, clk_data);693 break;694 case CS43130_XSP_DOP_DAI:695 regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_1,696 CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>697 CS43130_SP_LCPR_LSB_DATA_SHIFT);698 regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_PERIOD_2,699 CS43130_SP_LCPR_DATA_MASK, (frm_size - 1) >>700 CS43130_SP_LCPR_MSB_DATA_SHIFT);701 regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_1,702 CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>703 CS43130_SP_LCHI_LSB_DATA_SHIFT);704 regmap_update_bits(cs43130->regmap, CS43130_XSP_LRCK_HI_TIME_2,705 CS43130_SP_LCHI_DATA_MASK, (hi_size - 1) >>706 CS43130_SP_LCHI_MSB_DATA_SHIFT);707 regmap_write(cs43130->regmap, CS43130_XSP_FRAME_CONF, frm_data);708 regmap_write(cs43130->regmap, CS43130_XSP_CH_1_LOC, loc_ch1);709 regmap_write(cs43130->regmap, CS43130_XSP_CH_2_LOC, loc_ch2);710 regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_1_SZ_EN,711 CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);712 regmap_update_bits(cs43130->regmap, CS43130_XSP_CH_2_SZ_EN,713 CS43130_CH_EN_MASK, 1 << CS43130_CH_EN_SHIFT);714 regmap_write(cs43130->regmap, CS43130_XSP_CLOCK_CONF, clk_data);715 break;716 default:717 return -EINVAL;718 }719 720 switch (frm_size) {721 case 16:722 clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,723 params_rate(params),724 cs43130_16_clk_gen,725 ARRAY_SIZE(cs43130_16_clk_gen));726 break;727 case 32:728 clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,729 params_rate(params),730 cs43130_32_clk_gen,731 ARRAY_SIZE(cs43130_32_clk_gen));732 break;733 case 48:734 clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,735 params_rate(params),736 cs43130_48_clk_gen,737 ARRAY_SIZE(cs43130_48_clk_gen));738 break;739 case 64:740 clk_gen = cs43130_get_clk_gen(cs43130->mclk_int,741 params_rate(params),742 cs43130_64_clk_gen,743 ARRAY_SIZE(cs43130_64_clk_gen));744 break;745 default:746 return -EINVAL;747 }748 749 if (!clk_gen)750 return -EINVAL;751 752 switch (dai_id) {753 case CS43130_ASP_PCM_DAI:754 case CS43130_ASP_DOP_DAI:755 regmap_write(cs43130->regmap, CS43130_ASP_DEN_1,756 (clk_gen->v.denominator & CS43130_SP_M_LSB_DATA_MASK) >>757 CS43130_SP_M_LSB_DATA_SHIFT);758 regmap_write(cs43130->regmap, CS43130_ASP_DEN_2,759 (clk_gen->v.denominator & CS43130_SP_M_MSB_DATA_MASK) >>760 CS43130_SP_M_MSB_DATA_SHIFT);761 regmap_write(cs43130->regmap, CS43130_ASP_NUM_1,762 (clk_gen->v.numerator & CS43130_SP_N_LSB_DATA_MASK) >>763 CS43130_SP_N_LSB_DATA_SHIFT);764 regmap_write(cs43130->regmap, CS43130_ASP_NUM_2,765 (clk_gen->v.numerator & CS43130_SP_N_MSB_DATA_MASK) >>766 CS43130_SP_N_MSB_DATA_SHIFT);767 break;768 case CS43130_XSP_DOP_DAI:769 regmap_write(cs43130->regmap, CS43130_XSP_DEN_1,770 (clk_gen->v.denominator & CS43130_SP_M_LSB_DATA_MASK) >>771 CS43130_SP_M_LSB_DATA_SHIFT);772 regmap_write(cs43130->regmap, CS43130_XSP_DEN_2,773 (clk_gen->v.denominator & CS43130_SP_M_MSB_DATA_MASK) >>774 CS43130_SP_M_MSB_DATA_SHIFT);775 regmap_write(cs43130->regmap, CS43130_XSP_NUM_1,776 (clk_gen->v.numerator & CS43130_SP_N_LSB_DATA_MASK) >>777 CS43130_SP_N_LSB_DATA_SHIFT);778 regmap_write(cs43130->regmap, CS43130_XSP_NUM_2,779 (clk_gen->v.numerator & CS43130_SP_N_MSB_DATA_MASK) >>780 CS43130_SP_N_MSB_DATA_SHIFT);781 break;782 default:783 return -EINVAL;784 }785 786 return 0;787}788 789static int cs43130_pcm_dsd_mix(bool en, struct regmap *regmap)790{791 if (en) {792 regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,793 CS43130_MIX_PCM_PREP_MASK,794 1 << CS43130_MIX_PCM_PREP_SHIFT);795 usleep_range(6000, 6050);796 regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,797 CS43130_MIX_PCM_DSD_MASK,798 1 << CS43130_MIX_PCM_DSD_SHIFT);799 } else {800 regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,801 CS43130_MIX_PCM_DSD_MASK,802 0 << CS43130_MIX_PCM_DSD_SHIFT);803 usleep_range(1600, 1650);804 regmap_update_bits(regmap, CS43130_DSD_PCM_MIX_CTL,805 CS43130_MIX_PCM_PREP_MASK,806 0 << CS43130_MIX_PCM_PREP_SHIFT);807 }808 809 return 0;810}811 812static int cs43130_dsd_hw_params(struct snd_pcm_substream *substream,813 struct snd_pcm_hw_params *params,814 struct snd_soc_dai *dai)815{816 struct snd_soc_component *component = dai->component;817 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);818 unsigned int required_clk;819 u8 dsd_speed;820 821 mutex_lock(&cs43130->clk_mutex);822 if (!cs43130->clk_req) {823 /* no DAI is currently using clk */824 if (!(CS43130_MCLK_22M % params_rate(params)))825 required_clk = CS43130_MCLK_22M;826 else827 required_clk = CS43130_MCLK_24M;828 829 cs43130_set_pll(component, 0, 0, cs43130->mclk, required_clk);830 if (cs43130->pll_bypass)831 cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);832 else833 cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);834 }835 836 cs43130->clk_req++;837 if (cs43130->clk_req == 2)838 cs43130_pcm_dsd_mix(true, cs43130->regmap);839 mutex_unlock(&cs43130->clk_mutex);840 841 switch (params_rate(params)) {842 case 176400:843 dsd_speed = 0;844 break;845 case 352800:846 dsd_speed = 1;847 break;848 default:849 dev_err(cs43130->dev, "Rate(%u) not supported\n",850 params_rate(params));851 return -EINVAL;852 }853 854 if (cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBM_CFM)855 regmap_update_bits(cs43130->regmap, CS43130_DSD_INT_CFG,856 CS43130_DSD_MASTER, CS43130_DSD_MASTER);857 else858 regmap_update_bits(cs43130->regmap, CS43130_DSD_INT_CFG,859 CS43130_DSD_MASTER, 0);860 861 regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,862 CS43130_DSD_SPEED_MASK,863 dsd_speed << CS43130_DSD_SPEED_SHIFT);864 regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,865 CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_DSD <<866 CS43130_DSD_SRC_SHIFT);867 868 return 0;869}870 871static int cs43130_hw_params(struct snd_pcm_substream *substream,872 struct snd_pcm_hw_params *params,873 struct snd_soc_dai *dai)874{875 struct snd_soc_component *component = dai->component;876 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);877 const struct cs43130_rate_map *rate_map;878 unsigned int sclk = cs43130->dais[dai->id].sclk;879 unsigned int bitwidth_sclk;880 unsigned int bitwidth_dai = (unsigned int)(params_width(params));881 unsigned int required_clk;882 u8 dsd_speed;883 884 mutex_lock(&cs43130->clk_mutex);885 if (!cs43130->clk_req) {886 /* no DAI is currently using clk */887 if (!(CS43130_MCLK_22M % params_rate(params)))888 required_clk = CS43130_MCLK_22M;889 else890 required_clk = CS43130_MCLK_24M;891 892 cs43130_set_pll(component, 0, 0, cs43130->mclk, required_clk);893 if (cs43130->pll_bypass)894 cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);895 else896 cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);897 }898 899 cs43130->clk_req++;900 if (cs43130->clk_req == 2)901 cs43130_pcm_dsd_mix(true, cs43130->regmap);902 mutex_unlock(&cs43130->clk_mutex);903 904 switch (dai->id) {905 case CS43130_ASP_DOP_DAI:906 case CS43130_XSP_DOP_DAI:907 /* DoP bitwidth is always 24-bit */908 bitwidth_dai = 24;909 sclk = params_rate(params) * bitwidth_dai *910 params_channels(params);911 912 switch (params_rate(params)) {913 case 176400:914 dsd_speed = 0;915 break;916 case 352800:917 dsd_speed = 1;918 break;919 default:920 dev_err(cs43130->dev, "Rate(%u) not supported\n",921 params_rate(params));922 return -EINVAL;923 }924 925 regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,926 CS43130_DSD_SPEED_MASK,927 dsd_speed << CS43130_DSD_SPEED_SHIFT);928 break;929 case CS43130_ASP_PCM_DAI:930 rate_map = cs43130_get_rate_table(params_rate(params));931 if (!rate_map)932 return -EINVAL;933 934 regmap_write(cs43130->regmap, CS43130_SP_SRATE, rate_map->val);935 break;936 default:937 dev_err(cs43130->dev, "Invalid DAI (%d)\n", dai->id);938 return -EINVAL;939 }940 941 switch (dai->id) {942 case CS43130_ASP_DOP_DAI:943 regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,944 CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_ASP <<945 CS43130_DSD_SRC_SHIFT);946 break;947 case CS43130_XSP_DOP_DAI:948 regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_2,949 CS43130_DSD_SRC_MASK, CS43130_DSD_SRC_XSP <<950 CS43130_DSD_SRC_SHIFT);951 break;952 }953 954 if (!sclk && cs43130->dais[dai->id].dai_mode == SND_SOC_DAIFMT_CBM_CFM)955 /* Calculate SCLK in master mode if unassigned */956 sclk = params_rate(params) * bitwidth_dai *957 params_channels(params);958 959 if (!sclk) {960 /* at this point, SCLK must be set */961 dev_err(cs43130->dev, "SCLK freq is not set\n");962 return -EINVAL;963 }964 965 bitwidth_sclk = (sclk / params_rate(params)) / params_channels(params);966 if (bitwidth_sclk < bitwidth_dai) {967 dev_err(cs43130->dev, "Format not supported: SCLK freq is too low\n");968 return -EINVAL;969 }970 971 dev_dbg(cs43130->dev,972 "sclk = %u, fs = %d, bitwidth_dai = %u\n",973 sclk, params_rate(params), bitwidth_dai);974 975 dev_dbg(cs43130->dev,976 "bitwidth_sclk = %u, num_ch = %u\n",977 bitwidth_sclk, params_channels(params));978 979 cs43130_set_bitwidth(dai->id, bitwidth_dai, cs43130->regmap);980 cs43130_set_sp_fmt(dai->id, bitwidth_sclk, params, cs43130);981 982 return 0;983}984 985static int cs43130_hw_free(struct snd_pcm_substream *substream,986 struct snd_soc_dai *dai)987{988 struct snd_soc_component *component = dai->component;989 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);990 991 mutex_lock(&cs43130->clk_mutex);992 cs43130->clk_req--;993 if (!cs43130->clk_req) {994 /* no DAI is currently using clk */995 cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);996 cs43130_pcm_dsd_mix(false, cs43130->regmap);997 }998 mutex_unlock(&cs43130->clk_mutex);999 1000 return 0;1001}1002 1003static const DECLARE_TLV_DB_SCALE(pcm_vol_tlv, -12750, 50, 1);1004 1005static const char * const pcm_ch_text[] = {1006 "Left-Right Ch",1007 "Left-Left Ch",1008 "Right-Left Ch",1009 "Right-Right Ch",1010};1011 1012static const struct reg_sequence pcm_ch_en_seq[] = {1013 {CS43130_DXD1, 0x99},1014 {0x180005, 0x8C},1015 {0x180007, 0xAB},1016 {0x180015, 0x31},1017 {0x180017, 0xB2},1018 {0x180025, 0x30},1019 {0x180027, 0x84},1020 {0x180035, 0x9C},1021 {0x180037, 0xAE},1022 {0x18000D, 0x24},1023 {0x18000F, 0xA3},1024 {0x18001D, 0x05},1025 {0x18001F, 0xD4},1026 {0x18002D, 0x0B},1027 {0x18002F, 0xC7},1028 {0x18003D, 0x71},1029 {0x18003F, 0xE7},1030 {CS43130_DXD1, 0},1031};1032 1033static const struct reg_sequence pcm_ch_dis_seq[] = {1034 {CS43130_DXD1, 0x99},1035 {0x180005, 0x24},1036 {0x180007, 0xA3},1037 {0x180015, 0x05},1038 {0x180017, 0xD4},1039 {0x180025, 0x0B},1040 {0x180027, 0xC7},1041 {0x180035, 0x71},1042 {0x180037, 0xE7},1043 {0x18000D, 0x8C},1044 {0x18000F, 0xAB},1045 {0x18001D, 0x31},1046 {0x18001F, 0xB2},1047 {0x18002D, 0x30},1048 {0x18002F, 0x84},1049 {0x18003D, 0x9C},1050 {0x18003F, 0xAE},1051 {CS43130_DXD1, 0},1052};1053 1054static int cs43130_pcm_ch_get(struct snd_kcontrol *kcontrol,1055 struct snd_ctl_elem_value *ucontrol)1056{1057 return snd_soc_get_enum_double(kcontrol, ucontrol);1058}1059 1060static int cs43130_pcm_ch_put(struct snd_kcontrol *kcontrol,1061 struct snd_ctl_elem_value *ucontrol)1062{1063 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;1064 unsigned int *item = ucontrol->value.enumerated.item;1065 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);1066 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1067 unsigned int val;1068 1069 if (item[0] >= e->items)1070 return -EINVAL;1071 val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;1072 1073 switch (cs43130->dev_id) {1074 case CS43131_CHIP_ID:1075 case CS43198_CHIP_ID:1076 if (val >= 2)1077 regmap_multi_reg_write(cs43130->regmap, pcm_ch_en_seq,1078 ARRAY_SIZE(pcm_ch_en_seq));1079 else1080 regmap_multi_reg_write(cs43130->regmap, pcm_ch_dis_seq,1081 ARRAY_SIZE(pcm_ch_dis_seq));1082 break;1083 }1084 1085 return snd_soc_put_enum_double(kcontrol, ucontrol);1086}1087 1088static SOC_ENUM_SINGLE_DECL(pcm_ch_enum, CS43130_PCM_PATH_CTL_2, 0,1089 pcm_ch_text);1090 1091static const char * const pcm_spd_texts[] = {1092 "Fast",1093 "Slow",1094};1095 1096static SOC_ENUM_SINGLE_DECL(pcm_spd_enum, CS43130_PCM_FILT_OPT, 7,1097 pcm_spd_texts);1098 1099static const char * const dsd_texts[] = {1100 "Off",1101 "BCKA Mode",1102 "BCKD Mode",1103};1104 1105static const unsigned int dsd_values[] = {1106 CS43130_DSD_SRC_DSD,1107 CS43130_DSD_SRC_ASP,1108 CS43130_DSD_SRC_XSP,1109};1110 1111static SOC_VALUE_ENUM_SINGLE_DECL(dsd_enum, CS43130_DSD_INT_CFG, 0, 0x03,1112 dsd_texts, dsd_values);1113 1114static const struct snd_kcontrol_new cs43130_snd_controls[] = {1115 SOC_DOUBLE_R_TLV("Master Playback Volume",1116 CS43130_PCM_VOL_A, CS43130_PCM_VOL_B, 0, 0xFF, 1,1117 pcm_vol_tlv),1118 SOC_DOUBLE_R_TLV("Master DSD Playback Volume",1119 CS43130_DSD_VOL_A, CS43130_DSD_VOL_B, 0, 0xFF, 1,1120 pcm_vol_tlv),1121 SOC_ENUM_EXT("PCM Ch Select", pcm_ch_enum, cs43130_pcm_ch_get,1122 cs43130_pcm_ch_put),1123 SOC_ENUM("PCM Filter Speed", pcm_spd_enum),1124 SOC_SINGLE("PCM Phase Compensation", CS43130_PCM_FILT_OPT, 6, 1, 0),1125 SOC_SINGLE("PCM Nonoversample Emulate", CS43130_PCM_FILT_OPT, 5, 1, 0),1126 SOC_SINGLE("PCM High-pass Filter", CS43130_PCM_FILT_OPT, 1, 1, 0),1127 SOC_SINGLE("PCM De-emphasis Filter", CS43130_PCM_FILT_OPT, 0, 1, 0),1128 SOC_ENUM("DSD Phase Modulation", dsd_enum),1129};1130 1131static const struct reg_sequence pcm_seq[] = {1132 {CS43130_DXD1, 0x99},1133 {CS43130_DXD7, 0x01},1134 {CS43130_DXD8, 0},1135 {CS43130_DXD9, 0x01},1136 {CS43130_DXD3, 0x12},1137 {CS43130_DXD4, 0},1138 {CS43130_DXD10, 0x28},1139 {CS43130_DXD11, 0x28},1140 {CS43130_DXD1, 0},1141};1142 1143static const struct reg_sequence dsd_seq[] = {1144 {CS43130_DXD1, 0x99},1145 {CS43130_DXD7, 0x01},1146 {CS43130_DXD8, 0},1147 {CS43130_DXD9, 0x01},1148 {CS43130_DXD3, 0x12},1149 {CS43130_DXD4, 0},1150 {CS43130_DXD10, 0x1E},1151 {CS43130_DXD11, 0x20},1152 {CS43130_DXD1, 0},1153};1154 1155static const struct reg_sequence pop_free_seq[] = {1156 {CS43130_DXD1, 0x99},1157 {CS43130_DXD12, 0x0A},1158 {CS43130_DXD1, 0},1159};1160 1161static const struct reg_sequence pop_free_seq2[] = {1162 {CS43130_DXD1, 0x99},1163 {CS43130_DXD13, 0x20},1164 {CS43130_DXD1, 0},1165};1166 1167static const struct reg_sequence mute_seq[] = {1168 {CS43130_DXD1, 0x99},1169 {CS43130_DXD3, 0x12},1170 {CS43130_DXD5, 0x02},1171 {CS43130_DXD4, 0x12},1172 {CS43130_DXD1, 0},1173};1174 1175static const struct reg_sequence unmute_seq[] = {1176 {CS43130_DXD1, 0x99},1177 {CS43130_DXD3, 0x10},1178 {CS43130_DXD5, 0},1179 {CS43130_DXD4, 0x16},1180 {CS43130_DXD1, 0},1181};1182 1183static int cs43130_dsd_event(struct snd_soc_dapm_widget *w,1184 struct snd_kcontrol *kcontrol, int event)1185{1186 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1187 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1188 1189 switch (event) {1190 case SND_SOC_DAPM_PRE_PMU:1191 switch (cs43130->dev_id) {1192 case CS43130_CHIP_ID:1193 case CS4399_CHIP_ID:1194 regmap_multi_reg_write(cs43130->regmap, dsd_seq,1195 ARRAY_SIZE(dsd_seq));1196 break;1197 }1198 break;1199 case SND_SOC_DAPM_POST_PMU:1200 regmap_update_bits(cs43130->regmap, CS43130_DSD_PATH_CTL_1,1201 CS43130_MUTE_MASK, 0);1202 switch (cs43130->dev_id) {1203 case CS43130_CHIP_ID:1204 case CS4399_CHIP_ID:1205 regmap_multi_reg_write(cs43130->regmap, unmute_seq,1206 ARRAY_SIZE(unmute_seq));1207 break;1208 }1209 break;1210 case SND_SOC_DAPM_PRE_PMD:1211 switch (cs43130->dev_id) {1212 case CS43130_CHIP_ID:1213 case CS4399_CHIP_ID:1214 regmap_multi_reg_write(cs43130->regmap, mute_seq,1215 ARRAY_SIZE(mute_seq));1216 regmap_update_bits(cs43130->regmap,1217 CS43130_DSD_PATH_CTL_1,1218 CS43130_MUTE_MASK, CS43130_MUTE_EN);1219 /*1220 * DSD Power Down Sequence1221 * According to Design, 130ms is preferred.1222 */1223 msleep(130);1224 break;1225 case CS43131_CHIP_ID:1226 case CS43198_CHIP_ID:1227 regmap_update_bits(cs43130->regmap,1228 CS43130_DSD_PATH_CTL_1,1229 CS43130_MUTE_MASK, CS43130_MUTE_EN);1230 break;1231 }1232 break;1233 default:1234 dev_err(cs43130->dev, "Invalid event = 0x%x\n", event);1235 return -EINVAL;1236 }1237 return 0;1238}1239 1240static int cs43130_pcm_event(struct snd_soc_dapm_widget *w,1241 struct snd_kcontrol *kcontrol, int event)1242{1243 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1244 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1245 1246 switch (event) {1247 case SND_SOC_DAPM_PRE_PMU:1248 switch (cs43130->dev_id) {1249 case CS43130_CHIP_ID:1250 case CS4399_CHIP_ID:1251 regmap_multi_reg_write(cs43130->regmap, pcm_seq,1252 ARRAY_SIZE(pcm_seq));1253 break;1254 }1255 break;1256 case SND_SOC_DAPM_POST_PMU:1257 regmap_update_bits(cs43130->regmap, CS43130_PCM_PATH_CTL_1,1258 CS43130_MUTE_MASK, 0);1259 switch (cs43130->dev_id) {1260 case CS43130_CHIP_ID:1261 case CS4399_CHIP_ID:1262 regmap_multi_reg_write(cs43130->regmap, unmute_seq,1263 ARRAY_SIZE(unmute_seq));1264 break;1265 }1266 break;1267 case SND_SOC_DAPM_PRE_PMD:1268 switch (cs43130->dev_id) {1269 case CS43130_CHIP_ID:1270 case CS4399_CHIP_ID:1271 regmap_multi_reg_write(cs43130->regmap, mute_seq,1272 ARRAY_SIZE(mute_seq));1273 regmap_update_bits(cs43130->regmap,1274 CS43130_PCM_PATH_CTL_1,1275 CS43130_MUTE_MASK, CS43130_MUTE_EN);1276 /*1277 * PCM Power Down Sequence1278 * According to Design, 130ms is preferred.1279 */1280 msleep(130);1281 break;1282 case CS43131_CHIP_ID:1283 case CS43198_CHIP_ID:1284 regmap_update_bits(cs43130->regmap,1285 CS43130_PCM_PATH_CTL_1,1286 CS43130_MUTE_MASK, CS43130_MUTE_EN);1287 break;1288 }1289 break;1290 default:1291 dev_err(cs43130->dev, "Invalid event = 0x%x\n", event);1292 return -EINVAL;1293 }1294 return 0;1295}1296 1297static const struct reg_sequence dac_postpmu_seq[] = {1298 {CS43130_DXD9, 0x0C},1299 {CS43130_DXD3, 0x10},1300 {CS43130_DXD4, 0x20},1301};1302 1303static const struct reg_sequence dac_postpmd_seq[] = {1304 {CS43130_DXD1, 0x99},1305 {CS43130_DXD6, 0x01},1306 {CS43130_DXD1, 0},1307};1308 1309static int cs43130_dac_event(struct snd_soc_dapm_widget *w,1310 struct snd_kcontrol *kcontrol, int event)1311{1312 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1313 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1314 1315 switch (event) {1316 case SND_SOC_DAPM_PRE_PMU:1317 switch (cs43130->dev_id) {1318 case CS43130_CHIP_ID:1319 case CS4399_CHIP_ID:1320 regmap_multi_reg_write(cs43130->regmap, pop_free_seq,1321 ARRAY_SIZE(pop_free_seq));1322 break;1323 case CS43131_CHIP_ID:1324 case CS43198_CHIP_ID:1325 regmap_multi_reg_write(cs43130->regmap, pop_free_seq2,1326 ARRAY_SIZE(pop_free_seq2));1327 break;1328 }1329 break;1330 case SND_SOC_DAPM_POST_PMU:1331 usleep_range(10000, 10050);1332 1333 regmap_write(cs43130->regmap, CS43130_DXD1, 0x99);1334 1335 switch (cs43130->dev_id) {1336 case CS43130_CHIP_ID:1337 case CS4399_CHIP_ID:1338 regmap_multi_reg_write(cs43130->regmap, dac_postpmu_seq,1339 ARRAY_SIZE(dac_postpmu_seq));1340 /*1341 * Per datasheet, Sec. PCM Power-Up Sequence.1342 * According to Design, CS43130_DXD12 must be 0 to meet1343 * THDN and Dynamic Range spec.1344 */1345 msleep(1000);1346 regmap_write(cs43130->regmap, CS43130_DXD12, 0);1347 break;1348 case CS43131_CHIP_ID:1349 case CS43198_CHIP_ID:1350 usleep_range(12000, 12010);1351 regmap_write(cs43130->regmap, CS43130_DXD13, 0);1352 break;1353 }1354 1355 regmap_write(cs43130->regmap, CS43130_DXD1, 0);1356 break;1357 case SND_SOC_DAPM_POST_PMD:1358 switch (cs43130->dev_id) {1359 case CS43130_CHIP_ID:1360 case CS4399_CHIP_ID:1361 regmap_multi_reg_write(cs43130->regmap, dac_postpmd_seq,1362 ARRAY_SIZE(dac_postpmd_seq));1363 break;1364 }1365 break;1366 default:1367 dev_err(cs43130->dev, "Invalid DAC event = 0x%x\n", event);1368 return -EINVAL;1369 }1370 return 0;1371}1372 1373static const struct reg_sequence hpin_prepmd_seq[] = {1374 {CS43130_DXD1, 0x99},1375 {CS43130_DXD15, 0x64},1376 {CS43130_DXD14, 0},1377 {CS43130_DXD2, 0},1378 {CS43130_DXD1, 0},1379};1380 1381static const struct reg_sequence hpin_postpmu_seq[] = {1382 {CS43130_DXD1, 0x99},1383 {CS43130_DXD2, 1},1384 {CS43130_DXD14, 0xDC},1385 {CS43130_DXD15, 0xE4},1386 {CS43130_DXD1, 0},1387};1388 1389static int cs43130_hpin_event(struct snd_soc_dapm_widget *w,1390 struct snd_kcontrol *kcontrol, int event)1391{1392 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);1393 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1394 1395 switch (event) {1396 case SND_SOC_DAPM_POST_PMD:1397 regmap_multi_reg_write(cs43130->regmap, hpin_prepmd_seq,1398 ARRAY_SIZE(hpin_prepmd_seq));1399 break;1400 case SND_SOC_DAPM_PRE_PMU:1401 regmap_multi_reg_write(cs43130->regmap, hpin_postpmu_seq,1402 ARRAY_SIZE(hpin_postpmu_seq));1403 break;1404 default:1405 dev_err(cs43130->dev, "Invalid HPIN event = 0x%x\n", event);1406 return -EINVAL;1407 }1408 return 0;1409}1410 1411static const char * const bypass_mux_text[] = {1412 "Internal",1413 "Alternative",1414};1415static SOC_ENUM_SINGLE_DECL(bypass_enum, SND_SOC_NOPM, 0, bypass_mux_text);1416static const struct snd_kcontrol_new bypass_ctrl = SOC_DAPM_ENUM("Switch", bypass_enum);1417 1418static const struct snd_soc_dapm_widget hp_widgets[] = {1419 SND_SOC_DAPM_MUX("Bypass Switch", SND_SOC_NOPM, 0, 0, &bypass_ctrl),1420 SND_SOC_DAPM_OUTPUT("HPOUTA"),1421 SND_SOC_DAPM_OUTPUT("HPOUTB"),1422 1423 SND_SOC_DAPM_AIF_IN_E("ASPIN PCM", NULL, 0, CS43130_PWDN_CTL,1424 CS43130_PDN_ASP_SHIFT, 1, cs43130_pcm_event,1425 (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |1426 SND_SOC_DAPM_PRE_PMD)),1427 1428 SND_SOC_DAPM_AIF_IN_E("ASPIN DoP", NULL, 0, CS43130_PWDN_CTL,1429 CS43130_PDN_ASP_SHIFT, 1, cs43130_dsd_event,1430 (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |1431 SND_SOC_DAPM_PRE_PMD)),1432 1433 SND_SOC_DAPM_AIF_IN_E("XSPIN DoP", NULL, 0, CS43130_PWDN_CTL,1434 CS43130_PDN_XSP_SHIFT, 1, cs43130_dsd_event,1435 (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |1436 SND_SOC_DAPM_PRE_PMD)),1437 1438 SND_SOC_DAPM_AIF_IN_E("XSPIN DSD", NULL, 0, CS43130_PWDN_CTL,1439 CS43130_PDN_DSDIF_SHIFT, 1, cs43130_dsd_event,1440 (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |1441 SND_SOC_DAPM_PRE_PMD)),1442 1443 SND_SOC_DAPM_DAC("DSD", NULL, CS43130_DSD_PATH_CTL_2,1444 CS43130_DSD_EN_SHIFT, 0),1445 1446 SND_SOC_DAPM_DAC_E("HiFi DAC", NULL, CS43130_PWDN_CTL,1447 CS43130_PDN_HP_SHIFT, 1, cs43130_dac_event,1448 (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |1449 SND_SOC_DAPM_POST_PMD)),1450 1451/* Some devices have some extra analog widgets */1452#define NUM_ANALOG_WIDGETS 11453 1454 SND_SOC_DAPM_DAC_E("Analog Playback", NULL, CS43130_HP_OUT_CTL_1,1455 CS43130_HP_IN_EN_SHIFT, 0, cs43130_hpin_event,1456 (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)),1457};1458 1459static const struct snd_soc_dapm_route hp_routes[] = {1460 {"ASPIN PCM", NULL, "ASP PCM Playback"},1461 {"ASPIN DoP", NULL, "ASP DoP Playback"},1462 {"XSPIN DoP", NULL, "XSP DoP Playback"},1463 {"XSPIN DSD", NULL, "XSP DSD Playback"},1464 {"DSD", NULL, "ASPIN DoP"},1465 {"DSD", NULL, "XSPIN DoP"},1466 {"DSD", NULL, "XSPIN DSD"},1467 {"HiFi DAC", NULL, "ASPIN PCM"},1468 {"HiFi DAC", NULL, "DSD"},1469 {"Bypass Switch", "Internal", "HiFi DAC"},1470 {"HPOUTA", NULL, "Bypass Switch"},1471 {"HPOUTB", NULL, "Bypass Switch"},1472 1473/* Some devices have some extra analog routes */1474#define NUM_ANALOG_ROUTES 11475 {"Bypass Switch", "Alternative", "Analog Playback"},1476};1477 1478 1479static const unsigned int cs43130_asp_src_rates[] = {1480 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 3840001481};1482 1483static const struct snd_pcm_hw_constraint_list cs43130_asp_constraints = {1484 .count = ARRAY_SIZE(cs43130_asp_src_rates),1485 .list = cs43130_asp_src_rates,1486};1487 1488static int cs43130_pcm_startup(struct snd_pcm_substream *substream,1489 struct snd_soc_dai *dai)1490{1491 return snd_pcm_hw_constraint_list(substream->runtime, 0,1492 SNDRV_PCM_HW_PARAM_RATE,1493 &cs43130_asp_constraints);1494}1495 1496static const unsigned int cs43130_dop_src_rates[] = {1497 176400, 352800,1498};1499 1500static const struct snd_pcm_hw_constraint_list cs43130_dop_constraints = {1501 .count = ARRAY_SIZE(cs43130_dop_src_rates),1502 .list = cs43130_dop_src_rates,1503};1504 1505static int cs43130_dop_startup(struct snd_pcm_substream *substream,1506 struct snd_soc_dai *dai)1507{1508 return snd_pcm_hw_constraint_list(substream->runtime, 0,1509 SNDRV_PCM_HW_PARAM_RATE,1510 &cs43130_dop_constraints);1511}1512 1513static int cs43130_pcm_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)1514{1515 struct snd_soc_component *component = codec_dai->component;1516 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1517 1518 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {1519 case SND_SOC_DAIFMT_CBS_CFS:1520 cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;1521 break;1522 case SND_SOC_DAIFMT_CBM_CFM:1523 cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;1524 break;1525 default:1526 dev_err(cs43130->dev, "unsupported mode\n");1527 return -EINVAL;1528 }1529 1530 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {1531 case SND_SOC_DAIFMT_NB_NF:1532 cs43130->dais[codec_dai->id].dai_invert = SND_SOC_DAIFMT_NB_NF;1533 break;1534 case SND_SOC_DAIFMT_IB_NF:1535 cs43130->dais[codec_dai->id].dai_invert = SND_SOC_DAIFMT_IB_NF;1536 break;1537 case SND_SOC_DAIFMT_NB_IF:1538 cs43130->dais[codec_dai->id].dai_invert = SND_SOC_DAIFMT_NB_IF;1539 break;1540 case SND_SOC_DAIFMT_IB_IF:1541 cs43130->dais[codec_dai->id].dai_invert = SND_SOC_DAIFMT_IB_IF;1542 break;1543 default:1544 dev_err(cs43130->dev, "Unsupported invert mode 0x%x\n",1545 fmt & SND_SOC_DAIFMT_INV_MASK);1546 return -EINVAL;1547 }1548 1549 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {1550 case SND_SOC_DAIFMT_I2S:1551 cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_I2S;1552 break;1553 case SND_SOC_DAIFMT_LEFT_J:1554 cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_LEFT_J;1555 break;1556 case SND_SOC_DAIFMT_DSP_A:1557 cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_DSP_A;1558 break;1559 case SND_SOC_DAIFMT_DSP_B:1560 cs43130->dais[codec_dai->id].dai_format = SND_SOC_DAIFMT_DSP_B;1561 break;1562 default:1563 dev_err(cs43130->dev,1564 "unsupported audio format\n");1565 return -EINVAL;1566 }1567 1568 dev_dbg(cs43130->dev, "dai_id = %d, dai_mode = %u, dai_format = %u\n",1569 codec_dai->id,1570 cs43130->dais[codec_dai->id].dai_mode,1571 cs43130->dais[codec_dai->id].dai_format);1572 1573 return 0;1574}1575 1576static int cs43130_dsd_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)1577{1578 struct snd_soc_component *component = codec_dai->component;1579 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1580 1581 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {1582 case SND_SOC_DAIFMT_CBS_CFS:1583 cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBS_CFS;1584 break;1585 case SND_SOC_DAIFMT_CBM_CFM:1586 cs43130->dais[codec_dai->id].dai_mode = SND_SOC_DAIFMT_CBM_CFM;1587 break;1588 default:1589 dev_err(cs43130->dev, "Unsupported DAI format.\n");1590 return -EINVAL;1591 }1592 1593 dev_dbg(cs43130->dev, "dai_mode = 0x%x\n",1594 cs43130->dais[codec_dai->id].dai_mode);1595 1596 return 0;1597}1598 1599static int cs43130_set_sysclk(struct snd_soc_dai *codec_dai,1600 int clk_id, unsigned int freq, int dir)1601{1602 struct snd_soc_component *component = codec_dai->component;1603 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1604 1605 cs43130->dais[codec_dai->id].sclk = freq;1606 dev_dbg(cs43130->dev, "dai_id = %d, sclk = %u\n", codec_dai->id,1607 cs43130->dais[codec_dai->id].sclk);1608 1609 return 0;1610}1611 1612static const struct snd_soc_dai_ops cs43130_pcm_ops = {1613 .startup = cs43130_pcm_startup,1614 .hw_params = cs43130_hw_params,1615 .hw_free = cs43130_hw_free,1616 .set_sysclk = cs43130_set_sysclk,1617 .set_fmt = cs43130_pcm_set_fmt,1618};1619 1620static const struct snd_soc_dai_ops cs43130_dop_ops = {1621 .startup = cs43130_dop_startup,1622 .hw_params = cs43130_hw_params,1623 .hw_free = cs43130_hw_free,1624 .set_sysclk = cs43130_set_sysclk,1625 .set_fmt = cs43130_pcm_set_fmt,1626};1627 1628static const struct snd_soc_dai_ops cs43130_dsd_ops = {1629 .startup = cs43130_dop_startup,1630 .hw_params = cs43130_dsd_hw_params,1631 .hw_free = cs43130_hw_free,1632 .set_fmt = cs43130_dsd_set_fmt,1633};1634 1635static struct snd_soc_dai_driver cs43130_dai[] = {1636 {1637 .name = "cs43130-asp-pcm",1638 .id = CS43130_ASP_PCM_DAI,1639 .playback = {1640 .stream_name = "ASP PCM Playback",1641 .channels_min = 1,1642 .channels_max = 2,1643 .rates = SNDRV_PCM_RATE_KNOT,1644 .formats = CS43130_PCM_FORMATS,1645 },1646 .ops = &cs43130_pcm_ops,1647 .symmetric_rate = 1,1648 },1649 {1650 .name = "cs43130-asp-dop",1651 .id = CS43130_ASP_DOP_DAI,1652 .playback = {1653 .stream_name = "ASP DoP Playback",1654 .channels_min = 1,1655 .channels_max = 2,1656 .rates = SNDRV_PCM_RATE_KNOT,1657 .formats = CS43130_DOP_FORMATS,1658 },1659 .ops = &cs43130_dop_ops,1660 .symmetric_rate = 1,1661 },1662 {1663 .name = "cs43130-xsp-dop",1664 .id = CS43130_XSP_DOP_DAI,1665 .playback = {1666 .stream_name = "XSP DoP Playback",1667 .channels_min = 1,1668 .channels_max = 2,1669 .rates = SNDRV_PCM_RATE_KNOT,1670 .formats = CS43130_DOP_FORMATS,1671 },1672 .ops = &cs43130_dop_ops,1673 .symmetric_rate = 1,1674 },1675 {1676 .name = "cs43130-xsp-dsd",1677 .id = CS43130_XSP_DSD_DAI,1678 .playback = {1679 .stream_name = "XSP DSD Playback",1680 .channels_min = 1,1681 .channels_max = 2,1682 .rates = SNDRV_PCM_RATE_KNOT,1683 .formats = CS43130_DOP_FORMATS,1684 },1685 .ops = &cs43130_dsd_ops,1686 },1687 1688};1689 1690static int cs43130_component_set_sysclk(struct snd_soc_component *component,1691 int clk_id, int source, unsigned int freq,1692 int dir)1693{1694 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);1695 1696 dev_dbg(cs43130->dev, "clk_id = %d, source = %d, freq = %d, dir = %d\n",1697 clk_id, source, freq, dir);1698 1699 switch (freq) {1700 case CS43130_MCLK_22M:1701 case CS43130_MCLK_24M:1702 cs43130->mclk = freq;1703 break;1704 default:1705 dev_err(cs43130->dev, "Invalid MCLK INT freq: %u\n", freq);1706 return -EINVAL;1707 }1708 1709 if (source == CS43130_MCLK_SRC_EXT) {1710 cs43130->pll_bypass = true;1711 } else {1712 dev_err(cs43130->dev, "Invalid MCLK source\n");1713 return -EINVAL;1714 }1715 1716 return 0;1717}1718 1719static inline u16 cs43130_get_ac_reg_val(u16 ac_freq)1720{1721 /* AC freq is counted in 5.94Hz step. */1722 return ac_freq / 6;1723}1724 1725static int cs43130_show_dc(struct device *dev, char *buf, u8 ch)1726{1727 struct i2c_client *client = to_i2c_client(dev);1728 struct cs43130_private *cs43130 = i2c_get_clientdata(client);1729 1730 if (!cs43130->hpload_done)1731 return sysfs_emit(buf, "NO_HPLOAD\n");1732 else1733 return sysfs_emit(buf, "%u\n", cs43130->hpload_dc[ch]);1734}1735 1736static ssize_t hpload_dc_l_show(struct device *dev,1737 struct device_attribute *attr, char *buf)1738{1739 return cs43130_show_dc(dev, buf, HP_LEFT);1740}1741 1742static ssize_t hpload_dc_r_show(struct device *dev,1743 struct device_attribute *attr, char *buf)1744{1745 return cs43130_show_dc(dev, buf, HP_RIGHT);1746}1747 1748static const u16 cs43130_ac_freq[CS43130_AC_FREQ] = {1749 24,1750 43,1751 93,1752 200,1753 431,1754 928,1755 2000,1756 4309,1757 9283,1758 20000,1759};1760 1761static int cs43130_show_ac(struct device *dev, char *buf, u8 ch)1762{1763 int i, j = 0, tmp;1764 struct i2c_client *client = to_i2c_client(dev);1765 struct cs43130_private *cs43130 = i2c_get_clientdata(client);1766 1767 if (cs43130->hpload_done && cs43130->ac_meas) {1768 for (i = 0; i < ARRAY_SIZE(cs43130_ac_freq); i++) {1769 tmp = sysfs_emit_at(buf, j, "%u\n",1770 cs43130->hpload_ac[i][ch]);1771 if (!tmp)1772 break;1773 1774 j += tmp;1775 }1776 1777 return j;1778 } else {1779 return sysfs_emit(buf, "NO_HPLOAD\n");1780 }1781}1782 1783static ssize_t hpload_ac_l_show(struct device *dev,1784 struct device_attribute *attr, char *buf)1785{1786 return cs43130_show_ac(dev, buf, HP_LEFT);1787}1788 1789static ssize_t hpload_ac_r_show(struct device *dev,1790 struct device_attribute *attr, char *buf)1791{1792 return cs43130_show_ac(dev, buf, HP_RIGHT);1793}1794 1795static DEVICE_ATTR_RO(hpload_dc_l);1796static DEVICE_ATTR_RO(hpload_dc_r);1797static DEVICE_ATTR_RO(hpload_ac_l);1798static DEVICE_ATTR_RO(hpload_ac_r);1799 1800static struct attribute *hpload_attrs[] = {1801 &dev_attr_hpload_dc_l.attr,1802 &dev_attr_hpload_dc_r.attr,1803 &dev_attr_hpload_ac_l.attr,1804 &dev_attr_hpload_ac_r.attr,1805};1806ATTRIBUTE_GROUPS(hpload);1807 1808static const struct reg_sequence hp_en_cal_seq[] = {1809 {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},1810 {CS43130_HP_MEAS_LOAD_1, 0},1811 {CS43130_HP_MEAS_LOAD_2, 0},1812 {CS43130_INT_MASK_4, 0},1813 {CS43130_DXD1, 0x99},1814 {CS43130_DXD16, 0xBB},1815 {CS43130_DXD12, 0x01},1816 {CS43130_DXD19, 0xCB},1817 {CS43130_DXD17, 0x95},1818 {CS43130_DXD18, 0x0B},1819 {CS43130_DXD1, 0},1820 {CS43130_HP_LOAD_1, 0x80},1821};1822 1823static const struct reg_sequence hp_en_cal_seq2[] = {1824 {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},1825 {CS43130_HP_MEAS_LOAD_1, 0},1826 {CS43130_HP_MEAS_LOAD_2, 0},1827 {CS43130_INT_MASK_4, 0},1828 {CS43130_HP_LOAD_1, 0x80},1829};1830 1831static const struct reg_sequence hp_dis_cal_seq[] = {1832 {CS43130_HP_LOAD_1, 0x80},1833 {CS43130_DXD1, 0x99},1834 {CS43130_DXD12, 0},1835 {CS43130_DXD1, 0},1836 {CS43130_HP_LOAD_1, 0},1837};1838 1839static const struct reg_sequence hp_dis_cal_seq2[] = {1840 {CS43130_HP_LOAD_1, 0x80},1841 {CS43130_HP_LOAD_1, 0},1842};1843 1844static const struct reg_sequence hp_dc_ch_l_seq[] = {1845 {CS43130_DXD1, 0x99},1846 {CS43130_DXD19, 0x0A},1847 {CS43130_DXD17, 0x93},1848 {CS43130_DXD18, 0x0A},1849 {CS43130_DXD1, 0},1850 {CS43130_HP_LOAD_1, 0x80},1851 {CS43130_HP_LOAD_1, 0x81},1852};1853 1854static const struct reg_sequence hp_dc_ch_l_seq2[] = {1855 {CS43130_HP_LOAD_1, 0x80},1856 {CS43130_HP_LOAD_1, 0x81},1857};1858 1859static const struct reg_sequence hp_dc_ch_r_seq[] = {1860 {CS43130_DXD1, 0x99},1861 {CS43130_DXD19, 0x8A},1862 {CS43130_DXD17, 0x15},1863 {CS43130_DXD18, 0x06},1864 {CS43130_DXD1, 0},1865 {CS43130_HP_LOAD_1, 0x90},1866 {CS43130_HP_LOAD_1, 0x91},1867};1868 1869static const struct reg_sequence hp_dc_ch_r_seq2[] = {1870 {CS43130_HP_LOAD_1, 0x90},1871 {CS43130_HP_LOAD_1, 0x91},1872};1873 1874static const struct reg_sequence hp_ac_ch_l_seq[] = {1875 {CS43130_DXD1, 0x99},1876 {CS43130_DXD19, 0x0A},1877 {CS43130_DXD17, 0x93},1878 {CS43130_DXD18, 0x0A},1879 {CS43130_DXD1, 0},1880 {CS43130_HP_LOAD_1, 0x80},1881 {CS43130_HP_LOAD_1, 0x82},1882};1883 1884static const struct reg_sequence hp_ac_ch_l_seq2[] = {1885 {CS43130_HP_LOAD_1, 0x80},1886 {CS43130_HP_LOAD_1, 0x82},1887};1888 1889static const struct reg_sequence hp_ac_ch_r_seq[] = {1890 {CS43130_DXD1, 0x99},1891 {CS43130_DXD19, 0x8A},1892 {CS43130_DXD17, 0x15},1893 {CS43130_DXD18, 0x06},1894 {CS43130_DXD1, 0},1895 {CS43130_HP_LOAD_1, 0x90},1896 {CS43130_HP_LOAD_1, 0x92},1897};1898 1899static const struct reg_sequence hp_ac_ch_r_seq2[] = {1900 {CS43130_HP_LOAD_1, 0x90},1901 {CS43130_HP_LOAD_1, 0x92},1902};1903 1904static const struct reg_sequence hp_cln_seq[] = {1905 {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},1906 {CS43130_HP_MEAS_LOAD_1, 0},1907 {CS43130_HP_MEAS_LOAD_2, 0},1908};1909 1910struct reg_sequences {1911 const struct reg_sequence *seq;1912 int size;1913 unsigned int msk;1914};1915 1916static const struct reg_sequences hpload_seq1[] = {1917 {1918 .seq = hp_en_cal_seq,1919 .size = ARRAY_SIZE(hp_en_cal_seq),1920 .msk = CS43130_HPLOAD_ON_INT,1921 },1922 {1923 .seq = hp_dc_ch_l_seq,1924 .size = ARRAY_SIZE(hp_dc_ch_l_seq),1925 .msk = CS43130_HPLOAD_DC_INT,1926 },1927 {1928 .seq = hp_ac_ch_l_seq,1929 .size = ARRAY_SIZE(hp_ac_ch_l_seq),1930 .msk = CS43130_HPLOAD_AC_INT,1931 },1932 {1933 .seq = hp_dis_cal_seq,1934 .size = ARRAY_SIZE(hp_dis_cal_seq),1935 .msk = CS43130_HPLOAD_OFF_INT,1936 },1937 {1938 .seq = hp_en_cal_seq,1939 .size = ARRAY_SIZE(hp_en_cal_seq),1940 .msk = CS43130_HPLOAD_ON_INT,1941 },1942 {1943 .seq = hp_dc_ch_r_seq,1944 .size = ARRAY_SIZE(hp_dc_ch_r_seq),1945 .msk = CS43130_HPLOAD_DC_INT,1946 },1947 {1948 .seq = hp_ac_ch_r_seq,1949 .size = ARRAY_SIZE(hp_ac_ch_r_seq),1950 .msk = CS43130_HPLOAD_AC_INT,1951 },1952};1953 1954static const struct reg_sequences hpload_seq2[] = {1955 {1956 .seq = hp_en_cal_seq2,1957 .size = ARRAY_SIZE(hp_en_cal_seq2),1958 .msk = CS43130_HPLOAD_ON_INT,1959 },1960 {1961 .seq = hp_dc_ch_l_seq2,1962 .size = ARRAY_SIZE(hp_dc_ch_l_seq2),1963 .msk = CS43130_HPLOAD_DC_INT,1964 },1965 {1966 .seq = hp_ac_ch_l_seq2,1967 .size = ARRAY_SIZE(hp_ac_ch_l_seq2),1968 .msk = CS43130_HPLOAD_AC_INT,1969 },1970 {1971 .seq = hp_dis_cal_seq2,1972 .size = ARRAY_SIZE(hp_dis_cal_seq2),1973 .msk = CS43130_HPLOAD_OFF_INT,1974 },1975 {1976 .seq = hp_en_cal_seq2,1977 .size = ARRAY_SIZE(hp_en_cal_seq2),1978 .msk = CS43130_HPLOAD_ON_INT,1979 },1980 {1981 .seq = hp_dc_ch_r_seq2,1982 .size = ARRAY_SIZE(hp_dc_ch_r_seq2),1983 .msk = CS43130_HPLOAD_DC_INT,1984 },1985 {1986 .seq = hp_ac_ch_r_seq2,1987 .size = ARRAY_SIZE(hp_ac_ch_r_seq2),1988 .msk = CS43130_HPLOAD_AC_INT,1989 },1990};1991 1992static int cs43130_update_hpload(unsigned int msk, int ac_idx,1993 struct cs43130_private *cs43130)1994{1995 bool left_ch = true;1996 unsigned int reg;1997 u32 addr;1998 u16 impedance;1999 2000 switch (msk) {2001 case CS43130_HPLOAD_DC_INT:2002 case CS43130_HPLOAD_AC_INT:2003 break;2004 default:2005 return 0;2006 }2007 2008 regmap_read(cs43130->regmap, CS43130_HP_LOAD_1, ®);2009 if (reg & CS43130_HPLOAD_CHN_SEL)2010 left_ch = false;2011 2012 if (msk == CS43130_HPLOAD_DC_INT)2013 addr = CS43130_HP_DC_STAT_1;2014 else2015 addr = CS43130_HP_AC_STAT_1;2016 2017 regmap_read(cs43130->regmap, addr, ®);2018 impedance = reg >> 3;2019 regmap_read(cs43130->regmap, addr + 1, ®);2020 impedance |= reg << 5;2021 2022 if (msk == CS43130_HPLOAD_DC_INT) {2023 if (left_ch)2024 cs43130->hpload_dc[HP_LEFT] = impedance;2025 else2026 cs43130->hpload_dc[HP_RIGHT] = impedance;2027 2028 dev_dbg(cs43130->dev, "HP DC impedance (Ch %u): %u\n", !left_ch,2029 impedance);2030 } else {2031 if (left_ch)2032 cs43130->hpload_ac[ac_idx][HP_LEFT] = impedance;2033 else2034 cs43130->hpload_ac[ac_idx][HP_RIGHT] = impedance;2035 2036 dev_dbg(cs43130->dev, "HP AC (%u Hz) impedance (Ch %u): %u\n",2037 cs43130->ac_freq[ac_idx], !left_ch, impedance);2038 }2039 2040 return 0;2041}2042 2043static int cs43130_hpload_proc(struct cs43130_private *cs43130,2044 const struct reg_sequence *seq, int seq_size,2045 unsigned int rslt_msk, int ac_idx)2046{2047 int ret;2048 unsigned int msk;2049 u16 ac_reg_val;2050 2051 reinit_completion(&cs43130->hpload_evt);2052 2053 if (rslt_msk == CS43130_HPLOAD_AC_INT) {2054 ac_reg_val = cs43130_get_ac_reg_val(cs43130->ac_freq[ac_idx]);2055 regmap_update_bits(cs43130->regmap, CS43130_HP_LOAD_1,2056 CS43130_HPLOAD_AC_START, 0);2057 regmap_update_bits(cs43130->regmap, CS43130_HP_MEAS_LOAD_1,2058 CS43130_HP_MEAS_LOAD_MASK,2059 ac_reg_val >> CS43130_HP_MEAS_LOAD_1_SHIFT);2060 regmap_update_bits(cs43130->regmap, CS43130_HP_MEAS_LOAD_2,2061 CS43130_HP_MEAS_LOAD_MASK,2062 ac_reg_val >> CS43130_HP_MEAS_LOAD_2_SHIFT);2063 }2064 2065 regmap_multi_reg_write(cs43130->regmap, seq,2066 seq_size);2067 2068 ret = wait_for_completion_timeout(&cs43130->hpload_evt,2069 msecs_to_jiffies(1000));2070 regmap_read(cs43130->regmap, CS43130_INT_MASK_4, &msk);2071 if (!ret) {2072 dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt\n");2073 return -ETIMEDOUT;2074 }2075 2076 dev_dbg(cs43130->dev, "HP load stat: %x, INT_MASK_4: %x\n",2077 cs43130->hpload_stat, msk);2078 if ((cs43130->hpload_stat & (CS43130_HPLOAD_NO_DC_INT |2079 CS43130_HPLOAD_UNPLUG_INT |2080 CS43130_HPLOAD_OOR_INT)) ||2081 !(cs43130->hpload_stat & rslt_msk)) {2082 dev_dbg(cs43130->dev, "HP load measure failed\n");2083 return -1;2084 }2085 2086 return 0;2087}2088 2089static const struct reg_sequence hv_seq[][2] = {2090 {2091 {CS43130_CLASS_H_CTL, 0x1C},2092 {CS43130_HP_OUT_CTL_1, 0x10},2093 },2094 {2095 {CS43130_CLASS_H_CTL, 0x1E},2096 {CS43130_HP_OUT_CTL_1, 0x20},2097 },2098 {2099 {CS43130_CLASS_H_CTL, 0x1E},2100 {CS43130_HP_OUT_CTL_1, 0x30},2101 },2102};2103 2104static int cs43130_set_hv(struct regmap *regmap, u16 hpload_dc,2105 const u16 *dc_threshold)2106{2107 int i;2108 2109 for (i = 0; i < CS43130_DC_THRESHOLD; i++) {2110 if (hpload_dc <= dc_threshold[i])2111 break;2112 }2113 2114 regmap_multi_reg_write(regmap, hv_seq[i], ARRAY_SIZE(hv_seq[i]));2115 2116 return 0;2117}2118 2119static void cs43130_imp_meas(struct work_struct *wk)2120{2121 unsigned int reg, seq_size;2122 int i, ret, ac_idx;2123 struct cs43130_private *cs43130;2124 struct snd_soc_component *component;2125 const struct reg_sequences *hpload_seq;2126 2127 cs43130 = container_of(wk, struct cs43130_private, work);2128 component = cs43130->component;2129 2130 if (!cs43130->mclk)2131 return;2132 2133 cs43130->hpload_done = false;2134 2135 mutex_lock(&cs43130->clk_mutex);2136 if (!cs43130->clk_req) {2137 /* clk not in use */2138 cs43130_set_pll(component, 0, 0, cs43130->mclk, CS43130_MCLK_22M);2139 if (cs43130->pll_bypass)2140 cs43130_change_clksrc(component, CS43130_MCLK_SRC_EXT);2141 else2142 cs43130_change_clksrc(component, CS43130_MCLK_SRC_PLL);2143 }2144 2145 cs43130->clk_req++;2146 mutex_unlock(&cs43130->clk_mutex);2147 2148 regmap_read(cs43130->regmap, CS43130_INT_STATUS_4, ®);2149 2150 switch (cs43130->dev_id) {2151 case CS43130_CHIP_ID:2152 hpload_seq = hpload_seq1;2153 seq_size = ARRAY_SIZE(hpload_seq1);2154 break;2155 case CS43131_CHIP_ID:2156 hpload_seq = hpload_seq2;2157 seq_size = ARRAY_SIZE(hpload_seq2);2158 break;2159 default:2160 WARN(1, "Invalid dev_id for meas: %d", cs43130->dev_id);2161 return;2162 }2163 2164 i = 0;2165 ac_idx = 0;2166 while (i < seq_size) {2167 ret = cs43130_hpload_proc(cs43130, hpload_seq[i].seq,2168 hpload_seq[i].size,2169 hpload_seq[i].msk, ac_idx);2170 if (ret < 0)2171 goto exit;2172 2173 cs43130_update_hpload(hpload_seq[i].msk, ac_idx, cs43130);2174 2175 if (cs43130->ac_meas &&2176 hpload_seq[i].msk == CS43130_HPLOAD_AC_INT &&2177 ac_idx < CS43130_AC_FREQ - 1) {2178 ac_idx++;2179 } else {2180 ac_idx = 0;2181 i++;2182 }2183 }2184 cs43130->hpload_done = true;2185 2186 if (cs43130->hpload_dc[HP_LEFT] >= CS43130_LINEOUT_LOAD)2187 snd_soc_jack_report(&cs43130->jack, CS43130_JACK_LINEOUT,2188 CS43130_JACK_MASK);2189 else2190 snd_soc_jack_report(&cs43130->jack, CS43130_JACK_HEADPHONE,2191 CS43130_JACK_MASK);2192 2193 dev_dbg(cs43130->dev, "Set HP output control. DC threshold\n");2194 for (i = 0; i < CS43130_DC_THRESHOLD; i++)2195 dev_dbg(cs43130->dev, "DC threshold[%d]: %u.\n", i,2196 cs43130->dc_threshold[i]);2197 2198 cs43130_set_hv(cs43130->regmap, cs43130->hpload_dc[HP_LEFT],2199 cs43130->dc_threshold);2200 2201exit:2202 switch (cs43130->dev_id) {2203 case CS43130_CHIP_ID:2204 cs43130_hpload_proc(cs43130, hp_dis_cal_seq,2205 ARRAY_SIZE(hp_dis_cal_seq),2206 CS43130_HPLOAD_OFF_INT, ac_idx);2207 break;2208 case CS43131_CHIP_ID:2209 cs43130_hpload_proc(cs43130, hp_dis_cal_seq2,2210 ARRAY_SIZE(hp_dis_cal_seq2),2211 CS43130_HPLOAD_OFF_INT, ac_idx);2212 break;2213 }2214 2215 regmap_multi_reg_write(cs43130->regmap, hp_cln_seq,2216 ARRAY_SIZE(hp_cln_seq));2217 2218 mutex_lock(&cs43130->clk_mutex);2219 cs43130->clk_req--;2220 /* clk not in use */2221 if (!cs43130->clk_req)2222 cs43130_change_clksrc(component, CS43130_MCLK_SRC_RCO);2223 mutex_unlock(&cs43130->clk_mutex);2224}2225 2226static irqreturn_t cs43130_irq_thread(int irq, void *data)2227{2228 struct cs43130_private *cs43130 = (struct cs43130_private *)data;2229 unsigned int stickies[CS43130_NUM_INT];2230 unsigned int irq_occurrence = 0;2231 unsigned int masks[CS43130_NUM_INT];2232 int i, j;2233 2234 for (i = 0; i < ARRAY_SIZE(stickies); i++) {2235 regmap_read(cs43130->regmap, CS43130_INT_STATUS_1 + i,2236 &stickies[i]);2237 regmap_read(cs43130->regmap, CS43130_INT_MASK_1 + i,2238 &masks[i]);2239 }2240 2241 for (i = 0; i < ARRAY_SIZE(stickies); i++) {2242 stickies[i] = stickies[i] & (~masks[i]);2243 for (j = 0; j < 8; j++)2244 irq_occurrence += (stickies[i] >> j) & 1;2245 }2246 2247 if (!irq_occurrence)2248 return IRQ_NONE;2249 2250 if (stickies[0] & CS43130_XTAL_RDY_INT) {2251 complete(&cs43130->xtal_rdy);2252 return IRQ_HANDLED;2253 }2254 2255 if (stickies[0] & CS43130_PLL_RDY_INT) {2256 complete(&cs43130->pll_rdy);2257 return IRQ_HANDLED;2258 }2259 2260 if (stickies[3] & CS43130_HPLOAD_NO_DC_INT) {2261 cs43130->hpload_stat = stickies[3];2262 dev_err(cs43130->dev,2263 "DC load has not completed before AC load (%x)\n",2264 cs43130->hpload_stat);2265 complete(&cs43130->hpload_evt);2266 return IRQ_HANDLED;2267 }2268 2269 if (stickies[3] & CS43130_HPLOAD_UNPLUG_INT) {2270 cs43130->hpload_stat = stickies[3];2271 dev_err(cs43130->dev, "HP unplugged during measurement (%x)\n",2272 cs43130->hpload_stat);2273 complete(&cs43130->hpload_evt);2274 return IRQ_HANDLED;2275 }2276 2277 if (stickies[3] & CS43130_HPLOAD_OOR_INT) {2278 cs43130->hpload_stat = stickies[3];2279 dev_err(cs43130->dev, "HP load out of range (%x)\n",2280 cs43130->hpload_stat);2281 complete(&cs43130->hpload_evt);2282 return IRQ_HANDLED;2283 }2284 2285 if (stickies[3] & CS43130_HPLOAD_AC_INT) {2286 cs43130->hpload_stat = stickies[3];2287 dev_dbg(cs43130->dev, "HP AC load measurement done (%x)\n",2288 cs43130->hpload_stat);2289 complete(&cs43130->hpload_evt);2290 return IRQ_HANDLED;2291 }2292 2293 if (stickies[3] & CS43130_HPLOAD_DC_INT) {2294 cs43130->hpload_stat = stickies[3];2295 dev_dbg(cs43130->dev, "HP DC load measurement done (%x)\n",2296 cs43130->hpload_stat);2297 complete(&cs43130->hpload_evt);2298 return IRQ_HANDLED;2299 }2300 2301 if (stickies[3] & CS43130_HPLOAD_ON_INT) {2302 cs43130->hpload_stat = stickies[3];2303 dev_dbg(cs43130->dev, "HP load state machine on done (%x)\n",2304 cs43130->hpload_stat);2305 complete(&cs43130->hpload_evt);2306 return IRQ_HANDLED;2307 }2308 2309 if (stickies[3] & CS43130_HPLOAD_OFF_INT) {2310 cs43130->hpload_stat = stickies[3];2311 dev_dbg(cs43130->dev, "HP load state machine off done (%x)\n",2312 cs43130->hpload_stat);2313 complete(&cs43130->hpload_evt);2314 return IRQ_HANDLED;2315 }2316 2317 if (stickies[0] & CS43130_XTAL_ERR_INT) {2318 dev_err(cs43130->dev, "Crystal err: clock is not running\n");2319 return IRQ_HANDLED;2320 }2321 2322 if (stickies[0] & CS43130_HP_UNPLUG_INT) {2323 dev_dbg(cs43130->dev, "HP unplugged\n");2324 cs43130->hpload_done = false;2325 snd_soc_jack_report(&cs43130->jack, 0, CS43130_JACK_MASK);2326 return IRQ_HANDLED;2327 }2328 2329 if (stickies[0] & CS43130_HP_PLUG_INT) {2330 if (cs43130->dc_meas && !cs43130->hpload_done &&2331 !work_busy(&cs43130->work)) {2332 dev_dbg(cs43130->dev, "HP load queue work\n");2333 queue_work(cs43130->wq, &cs43130->work);2334 }2335 2336 snd_soc_jack_report(&cs43130->jack, SND_JACK_MECHANICAL,2337 CS43130_JACK_MASK);2338 return IRQ_HANDLED;2339 }2340 2341 return IRQ_NONE;2342}2343 2344static int cs43130_probe(struct snd_soc_component *component)2345{2346 int ret;2347 struct cs43130_private *cs43130 = snd_soc_component_get_drvdata(component);2348 struct snd_soc_card *card = component->card;2349 unsigned int reg;2350 2351 cs43130->component = component;2352 2353 if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED) {2354 regmap_update_bits(cs43130->regmap, CS43130_CRYSTAL_SET,2355 CS43130_XTAL_IBIAS_MASK,2356 cs43130->xtal_ibias);2357 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,2358 CS43130_XTAL_ERR_INT, 0);2359 }2360 2361 ret = snd_soc_card_jack_new(card, "Headphone", CS43130_JACK_MASK,2362 &cs43130->jack);2363 if (ret < 0) {2364 dev_err(cs43130->dev, "Cannot create jack\n");2365 return ret;2366 }2367 2368 cs43130->hpload_done = false;2369 if (cs43130->dc_meas) {2370 ret = sysfs_create_groups(&cs43130->dev->kobj, hpload_groups);2371 if (ret)2372 return ret;2373 2374 cs43130->wq = create_singlethread_workqueue("cs43130_hp");2375 if (!cs43130->wq) {2376 sysfs_remove_groups(&cs43130->dev->kobj, hpload_groups);2377 return -ENOMEM;2378 }2379 INIT_WORK(&cs43130->work, cs43130_imp_meas);2380 }2381 2382 regmap_read(cs43130->regmap, CS43130_INT_STATUS_1, ®);2383 regmap_read(cs43130->regmap, CS43130_HP_STATUS, ®);2384 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,2385 CS43130_HP_PLUG_INT | CS43130_HP_UNPLUG_INT, 0);2386 regmap_update_bits(cs43130->regmap, CS43130_HP_DETECT,2387 CS43130_HP_DETECT_CTRL_MASK, 0);2388 regmap_update_bits(cs43130->regmap, CS43130_HP_DETECT,2389 CS43130_HP_DETECT_CTRL_MASK,2390 CS43130_HP_DETECT_CTRL_MASK);2391 2392 return 0;2393}2394 2395static const struct snd_soc_component_driver soc_component_dev_cs43130_digital = {2396 .probe = cs43130_probe,2397 .controls = cs43130_snd_controls,2398 .num_controls = ARRAY_SIZE(cs43130_snd_controls),2399 .set_sysclk = cs43130_component_set_sysclk,2400 .set_pll = cs43130_set_pll,2401 .idle_bias_on = 1,2402 .use_pmdown_time = 1,2403 .endianness = 1,2404 /* Don't take into account the ending analog widgets and routes */2405 .dapm_widgets = hp_widgets,2406 .num_dapm_widgets = ARRAY_SIZE(hp_widgets) - NUM_ANALOG_WIDGETS,2407 .dapm_routes = hp_routes,2408 .num_dapm_routes = ARRAY_SIZE(hp_routes) - NUM_ANALOG_ROUTES,2409};2410 2411static const struct snd_soc_component_driver soc_component_dev_cs43130_analog = {2412 .probe = cs43130_probe,2413 .controls = cs43130_snd_controls,2414 .num_controls = ARRAY_SIZE(cs43130_snd_controls),2415 .set_sysclk = cs43130_component_set_sysclk,2416 .set_pll = cs43130_set_pll,2417 .idle_bias_on = 1,2418 .use_pmdown_time = 1,2419 .endianness = 1,2420 .dapm_widgets = hp_widgets,2421 .num_dapm_widgets = ARRAY_SIZE(hp_widgets),2422 .dapm_routes = hp_routes,2423 .num_dapm_routes = ARRAY_SIZE(hp_routes),2424};2425 2426static const struct regmap_config cs43130_regmap = {2427 .reg_bits = 24,2428 .pad_bits = 8,2429 .val_bits = 8,2430 2431 .max_register = CS43130_LASTREG,2432 .reg_defaults = cs43130_reg_defaults,2433 .num_reg_defaults = ARRAY_SIZE(cs43130_reg_defaults),2434 .readable_reg = cs43130_readable_register,2435 .precious_reg = cs43130_precious_register,2436 .volatile_reg = cs43130_volatile_register,2437 .cache_type = REGCACHE_MAPLE,2438 /* needed for regcache_sync */2439 .use_single_read = true,2440 .use_single_write = true,2441};2442 2443static const u16 cs43130_dc_threshold[CS43130_DC_THRESHOLD] = {2444 50,2445 120,2446};2447 2448static int cs43130_handle_device_data(struct cs43130_private *cs43130)2449{2450 unsigned int val;2451 int i;2452 2453 if (device_property_read_u32(cs43130->dev, "cirrus,xtal-ibias", &val) < 0) {2454 /* Crystal is unused. System clock is used for external MCLK */2455 cs43130->xtal_ibias = CS43130_XTAL_UNUSED;2456 return 0;2457 }2458 2459 switch (val) {2460 case 1:2461 cs43130->xtal_ibias = CS43130_XTAL_IBIAS_7_5UA;2462 break;2463 case 2:2464 cs43130->xtal_ibias = CS43130_XTAL_IBIAS_12_5UA;2465 break;2466 case 3:2467 cs43130->xtal_ibias = CS43130_XTAL_IBIAS_15UA;2468 break;2469 default:2470 dev_err(cs43130->dev,2471 "Invalid cirrus,xtal-ibias value: %d\n", val);2472 return -EINVAL;2473 }2474 2475 cs43130->dc_meas = device_property_read_bool(cs43130->dev, "cirrus,dc-measure");2476 cs43130->ac_meas = device_property_read_bool(cs43130->dev, "cirrus,ac-measure");2477 2478 if (!device_property_read_u16_array(cs43130->dev, "cirrus,ac-freq", cs43130->ac_freq,2479 CS43130_AC_FREQ)) {2480 for (i = 0; i < CS43130_AC_FREQ; i++)2481 cs43130->ac_freq[i] = cs43130_ac_freq[i];2482 }2483 2484 if (!device_property_read_u16_array(cs43130->dev, "cirrus,dc-threshold",2485 cs43130->dc_threshold,2486 CS43130_DC_THRESHOLD)) {2487 for (i = 0; i < CS43130_DC_THRESHOLD; i++)2488 cs43130->dc_threshold[i] = cs43130_dc_threshold[i];2489 }2490 2491 return 0;2492}2493 2494static int cs43130_i2c_probe(struct i2c_client *client)2495{2496 const struct snd_soc_component_driver *component_driver;2497 struct cs43130_private *cs43130;2498 int ret;2499 unsigned int reg;2500 int i, devid;2501 2502 cs43130 = devm_kzalloc(&client->dev, sizeof(*cs43130), GFP_KERNEL);2503 if (!cs43130)2504 return -ENOMEM;2505 2506 cs43130->dev = &client->dev;2507 2508 i2c_set_clientdata(client, cs43130);2509 2510 cs43130->regmap = devm_regmap_init_i2c(client, &cs43130_regmap);2511 if (IS_ERR(cs43130->regmap)) {2512 ret = PTR_ERR(cs43130->regmap);2513 return ret;2514 }2515 2516 if (dev_fwnode(cs43130->dev)) {2517 ret = cs43130_handle_device_data(cs43130);2518 if (ret != 0)2519 return ret;2520 }2521 2522 for (i = 0; i < ARRAY_SIZE(cs43130->supplies); i++)2523 cs43130->supplies[i].supply = cs43130_supply_names[i];2524 2525 ret = devm_regulator_bulk_get(cs43130->dev,2526 ARRAY_SIZE(cs43130->supplies),2527 cs43130->supplies);2528 if (ret != 0) {2529 dev_err(cs43130->dev, "Failed to request supplies: %d\n", ret);2530 return ret;2531 }2532 ret = regulator_bulk_enable(ARRAY_SIZE(cs43130->supplies),2533 cs43130->supplies);2534 if (ret != 0) {2535 dev_err(cs43130->dev, "Failed to enable supplies: %d\n", ret);2536 return ret;2537 }2538 2539 cs43130->reset_gpio = devm_gpiod_get_optional(cs43130->dev,2540 "reset", GPIOD_OUT_LOW);2541 if (IS_ERR(cs43130->reset_gpio)) {2542 ret = PTR_ERR(cs43130->reset_gpio);2543 goto err_supplies;2544 }2545 2546 gpiod_set_value_cansleep(cs43130->reset_gpio, 1);2547 2548 usleep_range(2000, 2050);2549 2550 devid = cirrus_read_device_id(cs43130->regmap, CS43130_DEVID_AB);2551 if (devid < 0) {2552 ret = devid;2553 dev_err(cs43130->dev, "Failed to read device ID: %d\n", ret);2554 goto err;2555 }2556 2557 switch (devid) {2558 case CS43130_CHIP_ID:2559 case CS4399_CHIP_ID:2560 case CS43131_CHIP_ID:2561 case CS43198_CHIP_ID:2562 break;2563 default:2564 dev_err(cs43130->dev,2565 "CS43130 Device ID %X. Expected ID %X, %X, %X or %X\n",2566 devid, CS43130_CHIP_ID, CS4399_CHIP_ID,2567 CS43131_CHIP_ID, CS43198_CHIP_ID);2568 ret = -ENODEV;2569 goto err;2570 }2571 2572 cs43130->dev_id = devid;2573 ret = regmap_read(cs43130->regmap, CS43130_REV_ID, ®);2574 if (ret < 0) {2575 dev_err(cs43130->dev, "Get Revision ID failed\n");2576 goto err;2577 }2578 2579 dev_info(cs43130->dev,2580 "Cirrus Logic CS43130 (%x), Revision: %02X\n", devid,2581 reg & 0xFF);2582 2583 mutex_init(&cs43130->clk_mutex);2584 2585 init_completion(&cs43130->xtal_rdy);2586 init_completion(&cs43130->pll_rdy);2587 init_completion(&cs43130->hpload_evt);2588 2589 if (!client->irq) {2590 dev_dbg(cs43130->dev, "IRQ not found, will poll instead\n");2591 cs43130->has_irq_line = 0;2592 } else {2593 ret = devm_request_threaded_irq(cs43130->dev, client->irq,2594 NULL, cs43130_irq_thread,2595 IRQF_ONESHOT | IRQF_TRIGGER_LOW,2596 "cs43130", cs43130);2597 if (ret != 0) {2598 dev_err(cs43130->dev, "Failed to request IRQ: %d\n", ret);2599 goto err;2600 }2601 cs43130->has_irq_line = 1;2602 }2603 2604 cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;2605 2606 pm_runtime_set_autosuspend_delay(cs43130->dev, 100);2607 pm_runtime_use_autosuspend(cs43130->dev);2608 pm_runtime_set_active(cs43130->dev);2609 pm_runtime_enable(cs43130->dev);2610 2611 switch (cs43130->dev_id) {2612 case CS43130_CHIP_ID:2613 case CS43131_CHIP_ID:2614 component_driver = &soc_component_dev_cs43130_analog;2615 break;2616 case CS43198_CHIP_ID:2617 case CS4399_CHIP_ID:2618 component_driver = &soc_component_dev_cs43130_digital;2619 break;2620 }2621 2622 ret = devm_snd_soc_register_component(cs43130->dev, component_driver,2623 cs43130_dai, ARRAY_SIZE(cs43130_dai));2624 if (ret < 0) {2625 dev_err(cs43130->dev,2626 "snd_soc_register_component failed with ret = %d\n", ret);2627 goto err;2628 }2629 2630 regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,2631 CS43130_ASP_3ST_MASK, 0);2632 regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,2633 CS43130_XSP_3ST_MASK, 0);2634 2635 return 0;2636 2637err:2638 gpiod_set_value_cansleep(cs43130->reset_gpio, 0);2639err_supplies:2640 regulator_bulk_disable(ARRAY_SIZE(cs43130->supplies),2641 cs43130->supplies);2642 2643 return ret;2644}2645 2646static void cs43130_i2c_remove(struct i2c_client *client)2647{2648 struct cs43130_private *cs43130 = i2c_get_clientdata(client);2649 2650 if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED)2651 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,2652 CS43130_XTAL_ERR_INT,2653 1 << CS43130_XTAL_ERR_INT_SHIFT);2654 2655 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,2656 CS43130_HP_PLUG_INT | CS43130_HP_UNPLUG_INT,2657 CS43130_HP_PLUG_INT | CS43130_HP_UNPLUG_INT);2658 2659 if (cs43130->dc_meas) {2660 cancel_work_sync(&cs43130->work);2661 flush_workqueue(cs43130->wq);2662 2663 device_remove_file(cs43130->dev, &dev_attr_hpload_dc_l);2664 device_remove_file(cs43130->dev, &dev_attr_hpload_dc_r);2665 device_remove_file(cs43130->dev, &dev_attr_hpload_ac_l);2666 device_remove_file(cs43130->dev, &dev_attr_hpload_ac_r);2667 }2668 2669 gpiod_set_value_cansleep(cs43130->reset_gpio, 0);2670 2671 pm_runtime_disable(cs43130->dev);2672 regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies);2673}2674 2675static int __maybe_unused cs43130_runtime_suspend(struct device *dev)2676{2677 struct cs43130_private *cs43130 = dev_get_drvdata(dev);2678 2679 if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED)2680 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,2681 CS43130_XTAL_ERR_INT,2682 1 << CS43130_XTAL_ERR_INT_SHIFT);2683 2684 regcache_cache_only(cs43130->regmap, true);2685 regcache_mark_dirty(cs43130->regmap);2686 2687 gpiod_set_value_cansleep(cs43130->reset_gpio, 0);2688 2689 regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies);2690 2691 return 0;2692}2693 2694static int __maybe_unused cs43130_runtime_resume(struct device *dev)2695{2696 struct cs43130_private *cs43130 = dev_get_drvdata(dev);2697 int ret;2698 2699 ret = regulator_bulk_enable(CS43130_NUM_SUPPLIES, cs43130->supplies);2700 if (ret != 0) {2701 dev_err(dev, "Failed to enable supplies: %d\n", ret);2702 return ret;2703 }2704 2705 regcache_cache_only(cs43130->regmap, false);2706 2707 gpiod_set_value_cansleep(cs43130->reset_gpio, 1);2708 2709 usleep_range(2000, 2050);2710 2711 ret = regcache_sync(cs43130->regmap);2712 if (ret != 0) {2713 dev_err(dev, "Failed to restore register cache\n");2714 goto err;2715 }2716 2717 if (cs43130->xtal_ibias != CS43130_XTAL_UNUSED)2718 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,2719 CS43130_XTAL_ERR_INT, 0);2720 2721 return 0;2722err:2723 regcache_cache_only(cs43130->regmap, true);2724 regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies);2725 2726 return ret;2727}2728 2729static const struct dev_pm_ops cs43130_runtime_pm = {2730 SET_RUNTIME_PM_OPS(cs43130_runtime_suspend, cs43130_runtime_resume,2731 NULL)2732};2733 2734#if IS_ENABLED(CONFIG_OF)2735static const struct of_device_id cs43130_of_match[] = {2736 {.compatible = "cirrus,cs43130",},2737 {.compatible = "cirrus,cs4399",},2738 {.compatible = "cirrus,cs43131",},2739 {.compatible = "cirrus,cs43198",},2740 {},2741};2742 2743MODULE_DEVICE_TABLE(of, cs43130_of_match);2744#endif2745 2746#if IS_ENABLED(CONFIG_ACPI)2747static const struct acpi_device_id cs43130_acpi_match[] = {2748 { "CSC4399", 0 },2749 {}2750};2751 2752MODULE_DEVICE_TABLE(acpi, cs43130_acpi_match);2753#endif2754 2755 2756static const struct i2c_device_id cs43130_i2c_id[] = {2757 {"cs43130"},2758 {"cs4399"},2759 {"cs43131"},2760 {"cs43198"},2761 {}2762};2763 2764MODULE_DEVICE_TABLE(i2c, cs43130_i2c_id);2765 2766static struct i2c_driver cs43130_i2c_driver = {2767 .driver = {2768 .name = "cs43130",2769 .of_match_table = of_match_ptr(cs43130_of_match),2770 .acpi_match_table = ACPI_PTR(cs43130_acpi_match),2771 .pm = &cs43130_runtime_pm,2772 },2773 .id_table = cs43130_i2c_id,2774 .probe = cs43130_i2c_probe,2775 .remove = cs43130_i2c_remove,2776};2777 2778module_i2c_driver(cs43130_i2c_driver);2779 2780MODULE_AUTHOR("Li Xu <li.xu@cirrus.com>");2781MODULE_DESCRIPTION("Cirrus Logic CS43130 ALSA SoC Codec Driver");2782MODULE_LICENSE("GPL");2783