896 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Ingenic JZ4760 CODEC driver4//5// Copyright (C) 2021, Christophe Branchereau <cbranchereau@gmail.com>6// Copyright (C) 2021, Paul Cercueil <paul@crapouillou.net>7 8#include <linux/bitfield.h>9#include <linux/clk.h>10#include <linux/delay.h>11#include <linux/iopoll.h>12#include <linux/module.h>13#include <linux/regmap.h>14#include <linux/time64.h>15 16#include <sound/pcm_params.h>17#include <sound/soc.h>18#include <sound/soc-dai.h>19#include <sound/soc-dapm.h>20#include <sound/tlv.h>21 22#define ICDC_RGADW_OFFSET 0x0023#define ICDC_RGDATA_OFFSET 0x0424 25/* ICDC internal register access control register(RGADW) */26#define ICDC_RGADW_RGWR BIT(16)27#define ICDC_RGADW_RGADDR_MASK GENMASK(14, 8)28#define ICDC_RGADW_RGDIN_MASK GENMASK(7, 0)29 30/* ICDC internal register data output register (RGDATA)*/31#define ICDC_RGDATA_IRQ BIT(8)32#define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, 0)33 34/* Internal register space, accessed through regmap */35enum {36 JZ4760_CODEC_REG_SR,37 JZ4760_CODEC_REG_AICR,38 JZ4760_CODEC_REG_CR1,39 JZ4760_CODEC_REG_CR2,40 JZ4760_CODEC_REG_CR3,41 JZ4760_CODEC_REG_CR4,42 JZ4760_CODEC_REG_CCR1,43 JZ4760_CODEC_REG_CCR2,44 JZ4760_CODEC_REG_PMR1,45 JZ4760_CODEC_REG_PMR2,46 JZ4760_CODEC_REG_ICR,47 JZ4760_CODEC_REG_IFR,48 JZ4760_CODEC_REG_GCR1,49 JZ4760_CODEC_REG_GCR2,50 JZ4760_CODEC_REG_GCR3,51 JZ4760_CODEC_REG_GCR4,52 JZ4760_CODEC_REG_GCR5,53 JZ4760_CODEC_REG_GCR6,54 JZ4760_CODEC_REG_GCR7,55 JZ4760_CODEC_REG_GCR8,56 JZ4760_CODEC_REG_GCR9,57 JZ4760_CODEC_REG_AGC1,58 JZ4760_CODEC_REG_AGC2,59 JZ4760_CODEC_REG_AGC3,60 JZ4760_CODEC_REG_AGC4,61 JZ4760_CODEC_REG_AGC5,62 JZ4760_CODEC_REG_MIX1,63 JZ4760_CODEC_REG_MIX2,64};65 66#define REG_AICR_DAC_ADWL_MASK GENMASK(7, 6)67#define REG_AICR_DAC_SERIAL BIT(3)68#define REG_AICR_DAC_I2S BIT(1)69 70#define REG_AICR_ADC_ADWL_MASK GENMASK(5, 4)71 72#define REG_AICR_ADC_SERIAL BIT(2)73#define REG_AICR_ADC_I2S BIT(0)74 75#define REG_CR1_HP_LOAD BIT(7)76#define REG_CR1_HP_MUTE BIT(5)77#define REG_CR1_LO_MUTE_OFFSET 478#define REG_CR1_BTL_MUTE_OFFSET 379#define REG_CR1_OUTSEL_OFFSET 080#define REG_CR1_OUTSEL_MASK GENMASK(1, REG_CR1_OUTSEL_OFFSET)81 82#define REG_CR2_DAC_MONO BIT(7)83#define REG_CR2_DAC_MUTE BIT(5)84#define REG_CR2_DAC_NOMAD BIT(1)85#define REG_CR2_DAC_RIGHT_ONLY BIT(0)86 87#define REG_CR3_ADC_INSEL_OFFSET 288#define REG_CR3_ADC_INSEL_MASK GENMASK(3, REG_CR3_ADC_INSEL_OFFSET)89#define REG_CR3_MICSTEREO_OFFSET 190#define REG_CR3_MICDIFF_OFFSET 091 92#define REG_CR4_ADC_HPF_OFFSET 793#define REG_CR4_ADC_RIGHT_ONLY BIT(0)94 95#define REG_CCR1_CRYSTAL_MASK GENMASK(3, 0)96 97#define REG_CCR2_DAC_FREQ_MASK GENMASK(7, 4)98#define REG_CCR2_ADC_FREQ_MASK GENMASK(3, 0)99 100#define REG_PMR1_SB BIT(7)101#define REG_PMR1_SB_SLEEP BIT(6)102#define REG_PMR1_SB_AIP_OFFSET 5103#define REG_PMR1_SB_LINE_OFFSET 4104#define REG_PMR1_SB_MIC1_OFFSET 3105#define REG_PMR1_SB_MIC2_OFFSET 2106#define REG_PMR1_SB_BYPASS_OFFSET 1107#define REG_PMR1_SB_MICBIAS_OFFSET 0108 109#define REG_PMR2_SB_ADC_OFFSET 4110#define REG_PMR2_SB_HP_OFFSET 3111#define REG_PMR2_SB_BTL_OFFSET 2112#define REG_PMR2_SB_LOUT_OFFSET 1113#define REG_PMR2_SB_DAC_OFFSET 0114 115#define REG_ICR_INT_FORM_MASK GENMASK(7, 6)116#define REG_ICR_ALL_MASK GENMASK(5, 0)117#define REG_ICR_JACK_MASK BIT(5)118#define REG_ICR_SCMC_MASK BIT(4)119#define REG_ICR_RUP_MASK BIT(3)120#define REG_ICR_RDO_MASK BIT(2)121#define REG_ICR_GUP_MASK BIT(1)122#define REG_ICR_GDO_MASK BIT(0)123 124#define REG_IFR_ALL_MASK GENMASK(5, 0)125#define REG_IFR_JACK BIT(6)126#define REG_IFR_JACK_EVENT BIT(5)127#define REG_IFR_SCMC BIT(4)128#define REG_IFR_RUP BIT(3)129#define REG_IFR_RDO BIT(2)130#define REG_IFR_GUP BIT(1)131#define REG_IFR_GDO BIT(0)132 133#define REG_GCR_GAIN_OFFSET 0134#define REG_GCR_GAIN_MAX 0x1f135 136#define REG_GCR_RL BIT(7)137 138#define REG_GCR_GIM1_MASK GENMASK(5, 3)139#define REG_GCR_GIM2_MASK GENMASK(2, 0)140#define REG_GCR_GIM_GAIN_MAX 7141 142#define REG_AGC1_EN BIT(7)143#define REG_AGC1_TARGET_MASK GENMASK(5, 2)144 145#define REG_AGC2_NG_THR_MASK GENMASK(6, 4)146#define REG_AGC2_HOLD_MASK GENMASK(3, 0)147 148#define REG_AGC3_ATK_MASK GENMASK(7, 4)149#define REG_AGC3_DCY_MASK GENMASK(3, 0)150 151#define REG_AGC4_AGC_MAX_MASK GENMASK(4, 0)152 153#define REG_AGC5_AGC_MIN_MASK GENMASK(4, 0)154 155#define REG_MIX1_MIX_REC_MASK GENMASK(7, 6)156#define REG_MIX1_GIMIX_MASK GENMASK(4, 0)157 158#define REG_MIX2_DAC_MIX_MASK GENMASK(7, 6)159#define REG_MIX2_GOMIX_MASK GENMASK(4, 0)160 161/* codec private data */162struct jz_codec {163 struct device *dev;164 struct regmap *regmap;165 void __iomem *base;166 struct clk *clk;167};168 169static int jz4760_codec_set_bias_level(struct snd_soc_component *codec,170 enum snd_soc_bias_level level)171{172 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);173 struct regmap *regmap = jz_codec->regmap;174 175 switch (level) {176 case SND_SOC_BIAS_PREPARE:177 /* Reset all interrupt flags. */178 regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK);179 180 regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);181 msleep(250);182 regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);183 msleep(400);184 break;185 case SND_SOC_BIAS_STANDBY:186 regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);187 regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);188 break;189 default:190 break;191 }192 193 return 0;194}195 196static int jz4760_codec_startup(struct snd_pcm_substream *substream,197 struct snd_soc_dai *dai)198{199 struct snd_soc_component *codec = dai->component;200 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);201 int ret = 0;202 203 /*204 * SYSCLK output from the codec to the AIC is required to keep the205 * DMA transfer going during playback when all audible outputs have206 * been disabled.207 */208 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)209 ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");210 return ret;211}212 213static void jz4760_codec_shutdown(struct snd_pcm_substream *substream,214 struct snd_soc_dai *dai)215{216 struct snd_soc_component *codec = dai->component;217 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);218 219 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)220 snd_soc_dapm_disable_pin(dapm, "SYSCLK");221}222 223 224static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream,225 int cmd, struct snd_soc_dai *dai)226{227 struct snd_soc_component *codec = dai->component;228 int ret = 0;229 230 switch (cmd) {231 case SNDRV_PCM_TRIGGER_START:232 case SNDRV_PCM_TRIGGER_RESUME:233 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:234 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)235 snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON);236 break;237 case SNDRV_PCM_TRIGGER_STOP:238 case SNDRV_PCM_TRIGGER_SUSPEND:239 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:240 /* do nothing */241 break;242 default:243 ret = -EINVAL;244 }245 246 return ret;247}248 249static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)250{251 struct snd_soc_component *codec = dai->component;252 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);253 unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;254 unsigned int val, reg;255 int change, err;256 257 change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2,258 REG_CR2_DAC_MUTE,259 mute ? REG_CR2_DAC_MUTE : 0);260 if (change == 1) {261 regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val);262 263 if (val & BIT(REG_PMR2_SB_DAC_OFFSET))264 return 1;265 266 err = regmap_read_poll_timeout(jz_codec->regmap,267 JZ4760_CODEC_REG_IFR,268 val, val & gain_bit,269 1000, 1 * USEC_PER_SEC);270 if (err) {271 dev_err(jz_codec->dev,272 "Timeout while setting digital mute: %d", err);273 return err;274 }275 276 /* clear GUP/GDO flag */277 regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit);278 }279 280 regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, ®);281 282 return 0;283}284 285/* unit: 0.01dB */286static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100);287static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);288static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100);289static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);290static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);291 292/* Unconditional controls. */293static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = {294 /* record gain control */295 SOC_DOUBLE_R_TLV("PCM Capture Volume",296 JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8,297 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv),298 299 SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",300 JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3,301 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),302 303 SOC_SINGLE_TLV("Mixer Capture Volume",304 JZ4760_CODEC_REG_MIX1,305 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),306 307 SOC_SINGLE_TLV("Mixer Playback Volume",308 JZ4760_CODEC_REG_MIX2,309 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),310 311 SOC_SINGLE("High-Pass Filter Capture Switch",312 JZ4760_CODEC_REG_CR4,313 REG_CR4_ADC_HPF_OFFSET, 1, 0),314};315 316static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = {317 {318 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,319 .name = "Volume",320 .info = snd_soc_info_volsw,321 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ322 | SNDRV_CTL_ELEM_ACCESS_READWRITE,323 .tlv.p = dac_tlv,324 .get = snd_soc_dapm_get_volsw,325 .put = snd_soc_dapm_put_volsw,326 .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6,327 JZ4760_CODEC_REG_GCR5,328 REG_GCR_GAIN_OFFSET,329 REG_GCR_GAIN_MAX, 1),330 },331};332 333static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = {334 {335 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,336 .name = "Volume",337 .info = snd_soc_info_volsw,338 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ339 | SNDRV_CTL_ELEM_ACCESS_READWRITE,340 .tlv.p = out_tlv,341 .get = snd_soc_dapm_get_volsw,342 .put = snd_soc_dapm_put_volsw,343 .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2,344 JZ4760_CODEC_REG_GCR1,345 REG_GCR_GAIN_OFFSET,346 REG_GCR_GAIN_MAX, 1),347 },348};349 350static int hpout_event(struct snd_soc_dapm_widget *w,351 struct snd_kcontrol *kcontrol, int event)352{353 struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);354 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);355 unsigned int val;356 int err;357 358 switch (event) {359 case SND_SOC_DAPM_PRE_PMU:360 /* unmute HP */361 regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,362 REG_CR1_HP_MUTE);363 break;364 365 case SND_SOC_DAPM_POST_PMU:366 /* wait for ramp-up complete (RUP) */367 err = regmap_read_poll_timeout(jz_codec->regmap,368 JZ4760_CODEC_REG_IFR,369 val, val & REG_IFR_RUP,370 1000, 1 * USEC_PER_SEC);371 if (err) {372 dev_err(jz_codec->dev, "RUP timeout: %d", err);373 return err;374 }375 376 /* clear RUP flag */377 regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,378 REG_IFR_RUP);379 380 break;381 382 case SND_SOC_DAPM_POST_PMD:383 /* mute HP */384 regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,385 REG_CR1_HP_MUTE);386 387 err = regmap_read_poll_timeout(jz_codec->regmap,388 JZ4760_CODEC_REG_IFR,389 val, val & REG_IFR_RDO,390 1000, 1 * USEC_PER_SEC);391 if (err) {392 dev_err(jz_codec->dev, "RDO timeout: %d", err);393 return err;394 }395 396 /* clear RDO flag */397 regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,398 REG_IFR_RDO);399 400 break;401 }402 403 return 0;404}405 406static const char * const jz4760_codec_hp_texts[] = {407 "PCM", "Line In", "Mic 1", "Mic 2"408};409 410static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 };411 412static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum,413 JZ4760_CODEC_REG_CR1,414 REG_CR1_OUTSEL_OFFSET,415 REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET,416 jz4760_codec_hp_texts,417 jz4760_codec_hp_values);418static const struct snd_kcontrol_new jz4760_codec_hp_source =419 SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum);420 421static const char * const jz4760_codec_cap_texts[] = {422 "Line In", "Mic 1", "Mic 2"423};424 425static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 };426 427static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum,428 JZ4760_CODEC_REG_CR3,429 REG_CR3_ADC_INSEL_OFFSET,430 REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET,431 jz4760_codec_cap_texts,432 jz4760_codec_cap_values);433static const struct snd_kcontrol_new jz4760_codec_cap_source =434 SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum);435 436static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = {437 SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3,438 REG_CR3_MICSTEREO_OFFSET, 1, 0),439};440 441static const struct snd_kcontrol_new jz4760_codec_line_out_switch =442 SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,443 REG_CR1_LO_MUTE_OFFSET, 0, 0);444static const struct snd_kcontrol_new jz4760_codec_btl_out_switch =445 SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,446 REG_CR1_BTL_MUTE_OFFSET, 0, 0);447 448static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = {449 SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2,450 REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event,451 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |452 SND_SOC_DAPM_POST_PMD),453 454 SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2,455 REG_PMR2_SB_LOUT_OFFSET, 1,456 &jz4760_codec_line_out_switch),457 458 SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2,459 REG_PMR2_SB_BTL_OFFSET, 1,460 &jz4760_codec_btl_out_switch),461 462 SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1,463 REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0),464 465 SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,466 &jz4760_codec_hp_source),467 468 SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,469 &jz4760_codec_cap_source),470 471 SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1,472 REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0),473 474 SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1,475 REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0),476 477 SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3,478 REG_CR3_MICDIFF_OFFSET, 0, NULL, 0),479 480 SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,481 jz4760_codec_mic_controls,482 ARRAY_SIZE(jz4760_codec_mic_controls)),483 484 SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1,485 REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0),486 487 SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2,488 REG_PMR2_SB_ADC_OFFSET, 1),489 490 SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2,491 REG_PMR2_SB_DAC_OFFSET, 1),492 493 SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,494 jz4760_codec_pcm_playback_controls,495 ARRAY_SIZE(jz4760_codec_pcm_playback_controls)),496 497 SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,498 jz4760_codec_hp_playback_controls,499 ARRAY_SIZE(jz4760_codec_hp_playback_controls)),500 501 SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1,502 REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0),503 504 SND_SOC_DAPM_INPUT("MIC1P"),505 SND_SOC_DAPM_INPUT("MIC1N"),506 SND_SOC_DAPM_INPUT("MIC2P"),507 SND_SOC_DAPM_INPUT("MIC2N"),508 509 SND_SOC_DAPM_INPUT("LLINEIN"),510 SND_SOC_DAPM_INPUT("RLINEIN"),511 512 SND_SOC_DAPM_OUTPUT("LHPOUT"),513 SND_SOC_DAPM_OUTPUT("RHPOUT"),514 515 SND_SOC_DAPM_OUTPUT("LOUT"),516 SND_SOC_DAPM_OUTPUT("ROUT"),517 518 SND_SOC_DAPM_OUTPUT("BTLP"),519 SND_SOC_DAPM_OUTPUT("BTLN"),520 521 SND_SOC_DAPM_OUTPUT("SYSCLK"),522};523 524/* Unconditional routes. */525static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = {526 { "Mic 1", NULL, "MIC1P" },527 { "Mic Diff", NULL, "MIC1N" },528 { "Mic 1", NULL, "Mic Diff" },529 { "Mic 2", NULL, "MIC2P" },530 { "Mic Diff", NULL, "MIC2N" },531 { "Mic 2", NULL, "Mic Diff" },532 533 { "Line In", NULL, "LLINEIN" },534 { "Line In", NULL, "RLINEIN" },535 536 { "Mic", "Stereo Capture Switch", "Mic 1" },537 { "Mic", "Stereo Capture Switch", "Mic 2" },538 { "Headphones Source", "Mic 1", "Mic" },539 { "Headphones Source", "Mic 2", "Mic" },540 { "Capture Source", "Mic 1", "Mic" },541 { "Capture Source", "Mic 2", "Mic" },542 543 { "Capture Source", "Line In", "Line In" },544 { "Capture Source", "Mic 1", "Mic 1" },545 { "Capture Source", "Mic 2", "Mic 2" },546 { "ADC", NULL, "Capture Source" },547 548 { "Line In Bypass", NULL, "Line In" },549 550 { "Headphones Source", "Mic 1", "Mic 1" },551 { "Headphones Source", "Mic 2", "Mic 2" },552 { "Headphones Source", "Line In", "Line In Bypass" },553 { "Headphones Source", "PCM", "Headphones Playback" },554 { "HP Out", NULL, "Headphones Source" },555 556 { "LHPOUT", NULL, "HP Out" },557 { "RHPOUT", NULL, "HP Out" },558 { "Line Out", "Switch", "HP Out" },559 560 { "LOUT", NULL, "Line Out" },561 { "ROUT", NULL, "Line Out" },562 { "BTL Out", "Switch", "Line Out" },563 564 { "BTLP", NULL, "BTL Out"},565 { "BTLN", NULL, "BTL Out"},566 567 { "PCM Playback", "Volume", "DAC" },568 { "Headphones Playback", "Volume", "PCM Playback" },569 570 { "SYSCLK", NULL, "DAC" },571};572 573static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec)574{575 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);576 struct regmap *regmap = jz_codec->regmap;577 578 /* Collect updates for later sending. */579 regcache_cache_only(regmap, true);580 581 /* default Amp output to PCM */582 regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK);583 584 /* Disable stereo mic */585 regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,586 BIT(REG_CR3_MICSTEREO_OFFSET));587 588 /* Set mic 1 as default source for ADC */589 regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,590 REG_CR3_ADC_INSEL_MASK);591 592 /* ADC/DAC: serial + i2s */593 regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR,594 REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S |595 REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);596 597 /* The generated IRQ is a high level */598 regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);599 regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK,600 REG_ICR_JACK_MASK | REG_ICR_RUP_MASK |601 REG_ICR_RDO_MASK | REG_ICR_GUP_MASK |602 REG_ICR_GDO_MASK);603 604 /* 12M oscillator */605 regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK);606 607 /* 0: 16ohm/220uF, 1: 10kohm/1uF */608 regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD);609 610 /* default to NOMAD */611 regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2,612 REG_CR2_DAC_NOMAD);613 614 /* disable automatic gain */615 regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN);616 617 /* Independent L/R DAC gain control */618 regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5,619 REG_GCR_RL);620 621 /* Send collected updates. */622 regcache_cache_only(regmap, false);623 regcache_sync(regmap);624}625 626static int jz4760_codec_codec_probe(struct snd_soc_component *codec)627{628 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);629 630 clk_prepare_enable(jz_codec->clk);631 632 jz4760_codec_codec_init_regs(codec);633 634 return 0;635}636 637static void jz4760_codec_codec_remove(struct snd_soc_component *codec)638{639 struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);640 641 clk_disable_unprepare(jz_codec->clk);642}643 644static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = {645 .probe = jz4760_codec_codec_probe,646 .remove = jz4760_codec_codec_remove,647 .set_bias_level = jz4760_codec_set_bias_level,648 .controls = jz4760_codec_snd_controls,649 .num_controls = ARRAY_SIZE(jz4760_codec_snd_controls),650 .dapm_widgets = jz4760_codec_dapm_widgets,651 .num_dapm_widgets = ARRAY_SIZE(jz4760_codec_dapm_widgets),652 .dapm_routes = jz4760_codec_dapm_routes,653 .num_dapm_routes = ARRAY_SIZE(jz4760_codec_dapm_routes),654 .suspend_bias_off = 1,655 .use_pmdown_time = 1,656};657 658static const unsigned int jz4760_codec_sample_rates[] = {659 96000, 48000, 44100, 32000,660 24000, 22050, 16000, 12000,661 11025, 9600, 8000,662};663 664static int jz4760_codec_hw_params(struct snd_pcm_substream *substream,665 struct snd_pcm_hw_params *params,666 struct snd_soc_dai *dai)667{668 struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);669 unsigned int rate, bit_width;670 671 switch (params_format(params)) {672 case SNDRV_PCM_FORMAT_S16_LE:673 bit_width = 0;674 break;675 case SNDRV_PCM_FORMAT_S18_3LE:676 bit_width = 1;677 break;678 case SNDRV_PCM_FORMAT_S20_3LE:679 bit_width = 2;680 break;681 case SNDRV_PCM_FORMAT_S24_3LE:682 bit_width = 3;683 break;684 default:685 return -EINVAL;686 }687 688 for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) {689 if (jz4760_codec_sample_rates[rate] == params_rate(params))690 break;691 }692 693 if (rate == ARRAY_SIZE(jz4760_codec_sample_rates))694 return -EINVAL;695 696 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {697 regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,698 REG_AICR_DAC_ADWL_MASK,699 FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width));700 regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,701 REG_CCR2_DAC_FREQ_MASK,702 FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate));703 } else {704 regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,705 REG_AICR_ADC_ADWL_MASK,706 FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width));707 regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,708 REG_CCR2_ADC_FREQ_MASK,709 FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate));710 }711 712 return 0;713}714 715static const struct snd_soc_dai_ops jz4760_codec_dai_ops = {716 .startup = jz4760_codec_startup,717 .shutdown = jz4760_codec_shutdown,718 .hw_params = jz4760_codec_hw_params,719 .trigger = jz4760_codec_pcm_trigger,720 .mute_stream = jz4760_codec_mute_stream,721 .no_capture_mute = 1,722};723 724#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \725 SNDRV_PCM_FMTBIT_S18_3LE | \726 SNDRV_PCM_FMTBIT_S20_3LE | \727 SNDRV_PCM_FMTBIT_S24_3LE)728 729static struct snd_soc_dai_driver jz4760_codec_dai = {730 .name = "jz4760-hifi",731 .playback = {732 .stream_name = "Playback",733 .channels_min = 2,734 .channels_max = 2,735 .rates = SNDRV_PCM_RATE_8000_96000,736 .formats = JZ_CODEC_FORMATS,737 },738 .capture = {739 .stream_name = "Capture",740 .channels_min = 2,741 .channels_max = 2,742 .rates = SNDRV_PCM_RATE_8000_96000,743 .formats = JZ_CODEC_FORMATS,744 },745 .ops = &jz4760_codec_dai_ops,746};747 748static bool jz4760_codec_volatile(struct device *dev, unsigned int reg)749{750 return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR;751}752 753static bool jz4760_codec_writeable(struct device *dev, unsigned int reg)754{755 switch (reg) {756 case JZ4760_CODEC_REG_SR:757 return false;758 default:759 return true;760 }761}762 763static int jz4760_codec_io_wait(struct jz_codec *codec)764{765 u32 reg;766 767 return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,768 !(reg & ICDC_RGADW_RGWR),769 1000, 1 * USEC_PER_SEC);770}771 772static int jz4760_codec_reg_read(void *context, unsigned int reg,773 unsigned int *val)774{775 struct jz_codec *codec = context;776 unsigned int i;777 u32 tmp;778 int ret;779 780 ret = jz4760_codec_io_wait(codec);781 if (ret)782 return ret;783 784 tmp = readl(codec->base + ICDC_RGADW_OFFSET);785 tmp &= ~ICDC_RGADW_RGADDR_MASK;786 tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg);787 writel(tmp, codec->base + ICDC_RGADW_OFFSET);788 789 /* wait 6+ cycles */790 for (i = 0; i < 6; i++)791 *val = readl(codec->base + ICDC_RGDATA_OFFSET) &792 ICDC_RGDATA_RGDOUT_MASK;793 794 return 0;795}796 797static int jz4760_codec_reg_write(void *context, unsigned int reg,798 unsigned int val)799{800 struct jz_codec *codec = context;801 int ret;802 803 ret = jz4760_codec_io_wait(codec);804 if (ret)805 return ret;806 807 writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val,808 codec->base + ICDC_RGADW_OFFSET);809 810 ret = jz4760_codec_io_wait(codec);811 if (ret)812 return ret;813 814 return 0;815}816 817static const u8 jz4760_codec_reg_defaults[] = {818 0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00,819 0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06,820 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44,821 0x1F, 0x00, 0x00, 0x00822};823 824static const struct regmap_config jz4760_codec_regmap_config = {825 .reg_bits = 7,826 .val_bits = 8,827 828 .max_register = JZ4760_CODEC_REG_MIX2,829 .volatile_reg = jz4760_codec_volatile,830 .writeable_reg = jz4760_codec_writeable,831 832 .reg_read = jz4760_codec_reg_read,833 .reg_write = jz4760_codec_reg_write,834 835 .reg_defaults_raw = jz4760_codec_reg_defaults,836 .num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults),837 .cache_type = REGCACHE_FLAT,838};839 840static int jz4760_codec_probe(struct platform_device *pdev)841{842 struct device *dev = &pdev->dev;843 struct jz_codec *codec;844 int ret;845 846 codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);847 if (!codec)848 return -ENOMEM;849 850 codec->dev = dev;851 852 codec->base = devm_platform_ioremap_resource(pdev, 0);853 if (IS_ERR(codec->base))854 return PTR_ERR(codec->base);855 856 codec->regmap = devm_regmap_init(dev, NULL, codec,857 &jz4760_codec_regmap_config);858 if (IS_ERR(codec->regmap))859 return PTR_ERR(codec->regmap);860 861 codec->clk = devm_clk_get(dev, "aic");862 if (IS_ERR(codec->clk))863 return PTR_ERR(codec->clk);864 865 platform_set_drvdata(pdev, codec);866 867 ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev,868 &jz4760_codec_dai, 1);869 if (ret) {870 dev_err(dev, "Failed to register codec: %d\n", ret);871 return ret;872 }873 874 return 0;875}876 877static const struct of_device_id jz4760_codec_of_matches[] = {878 { .compatible = "ingenic,jz4760-codec", },879 { /* sentinel */ }880};881MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches);882 883static struct platform_driver jz4760_codec_driver = {884 .probe = jz4760_codec_probe,885 .driver = {886 .name = "jz4760-codec",887 .of_match_table = jz4760_codec_of_matches,888 },889};890module_platform_driver(jz4760_codec_driver);891 892MODULE_DESCRIPTION("JZ4760 SoC internal codec driver");893MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");894MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");895MODULE_LICENSE("GPL v2");896