root/sound/soc/codecs/jz4725b.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. jz4725b_out_stage_enable
  2. jz4725b_codec_set_bias_level
  3. jz4725b_codec_dev_probe
  4. jz4725b_codec_dev_remove
  5. jz4725b_codec_hw_params
  6. jz4725b_codec_volatile
  7. jz4725b_codec_can_access_reg
  8. jz4725b_codec_io_wait
  9. jz4725b_codec_reg_read
  10. jz4725b_codec_reg_write
  11. jz4725b_codec_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // JZ4725B CODEC driver
   4 //
   5 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
   6 
   7 #include <linux/kernel.h>
   8 #include <linux/module.h>
   9 #include <linux/platform_device.h>
  10 #include <linux/slab.h>
  11 #include <linux/io.h>
  12 #include <linux/iopoll.h>
  13 #include <linux/regmap.h>
  14 #include <linux/clk.h>
  15 
  16 #include <linux/delay.h>
  17 
  18 #include <sound/core.h>
  19 #include <sound/pcm.h>
  20 #include <sound/pcm_params.h>
  21 #include <sound/initval.h>
  22 #include <sound/soc.h>
  23 #include <sound/tlv.h>
  24 
  25 #define ICDC_RGADW_OFFSET               0x00
  26 #define ICDC_RGDATA_OFFSET              0x04
  27 
  28 /* ICDC internal register access control register(RGADW) */
  29 #define ICDC_RGADW_RGWR                 BIT(16)
  30 
  31 #define ICDC_RGADW_RGADDR_OFFSET        8
  32 #define ICDC_RGADW_RGADDR_MASK          GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
  33 
  34 #define ICDC_RGADW_RGDIN_OFFSET         0
  35 #define ICDC_RGADW_RGDIN_MASK           GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
  36 
  37 /* ICDC internal register data output register (RGDATA)*/
  38 #define ICDC_RGDATA_IRQ                 BIT(8)
  39 
  40 #define ICDC_RGDATA_RGDOUT_OFFSET       0
  41 #define ICDC_RGDATA_RGDOUT_MASK         GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
  42 
  43 /* JZ internal register space */
  44 enum {
  45         JZ4725B_CODEC_REG_AICR,
  46         JZ4725B_CODEC_REG_CR1,
  47         JZ4725B_CODEC_REG_CR2,
  48         JZ4725B_CODEC_REG_CCR1,
  49         JZ4725B_CODEC_REG_CCR2,
  50         JZ4725B_CODEC_REG_PMR1,
  51         JZ4725B_CODEC_REG_PMR2,
  52         JZ4725B_CODEC_REG_CRR,
  53         JZ4725B_CODEC_REG_ICR,
  54         JZ4725B_CODEC_REG_IFR,
  55         JZ4725B_CODEC_REG_CGR1,
  56         JZ4725B_CODEC_REG_CGR2,
  57         JZ4725B_CODEC_REG_CGR3,
  58         JZ4725B_CODEC_REG_CGR4,
  59         JZ4725B_CODEC_REG_CGR5,
  60         JZ4725B_CODEC_REG_CGR6,
  61         JZ4725B_CODEC_REG_CGR7,
  62         JZ4725B_CODEC_REG_CGR8,
  63         JZ4725B_CODEC_REG_CGR9,
  64         JZ4725B_CODEC_REG_CGR10,
  65         JZ4725B_CODEC_REG_TR1,
  66         JZ4725B_CODEC_REG_TR2,
  67         JZ4725B_CODEC_REG_CR3,
  68         JZ4725B_CODEC_REG_AGC1,
  69         JZ4725B_CODEC_REG_AGC2,
  70         JZ4725B_CODEC_REG_AGC3,
  71         JZ4725B_CODEC_REG_AGC4,
  72         JZ4725B_CODEC_REG_AGC5,
  73 };
  74 
  75 #define REG_AICR_CONFIG1_OFFSET         0
  76 #define REG_AICR_CONFIG1_MASK           (0xf << REG_AICR_CONFIG1_OFFSET)
  77 
  78 #define REG_CR1_SB_MICBIAS_OFFSET       7
  79 #define REG_CR1_MONO_OFFSET             6
  80 #define REG_CR1_DAC_MUTE_OFFSET         5
  81 #define REG_CR1_HP_DIS_OFFSET           4
  82 #define REG_CR1_DACSEL_OFFSET           3
  83 #define REG_CR1_BYPASS_OFFSET           2
  84 
  85 #define REG_CR2_DAC_DEEMP_OFFSET        7
  86 #define REG_CR2_DAC_ADWL_OFFSET         5
  87 #define REG_CR2_DAC_ADWL_MASK           (0x3 << REG_CR2_DAC_ADWL_OFFSET)
  88 #define REG_CR2_ADC_ADWL_OFFSET         3
  89 #define REG_CR2_ADC_ADWL_MASK           (0x3 << REG_CR2_ADC_ADWL_OFFSET)
  90 #define REG_CR2_ADC_HPF_OFFSET          2
  91 
  92 #define REG_CR3_SB_MIC1_OFFSET          7
  93 #define REG_CR3_SB_MIC2_OFFSET          6
  94 #define REG_CR3_SIDETONE1_OFFSET        5
  95 #define REG_CR3_SIDETONE2_OFFSET        4
  96 #define REG_CR3_MICDIFF_OFFSET          3
  97 #define REG_CR3_MICSTEREO_OFFSET        2
  98 #define REG_CR3_INSEL_OFFSET            0
  99 #define REG_CR3_INSEL_MASK              (0x3 << REG_CR3_INSEL_OFFSET)
 100 
 101 #define REG_CCR1_CONFIG4_OFFSET         0
 102 #define REG_CCR1_CONFIG4_MASK           (0xf << REG_CCR1_CONFIG4_OFFSET)
 103 
 104 #define REG_CCR2_DFREQ_OFFSET           4
 105 #define REG_CCR2_DFREQ_MASK             (0xf << REG_CCR2_DFREQ_OFFSET)
 106 #define REG_CCR2_AFREQ_OFFSET           0
 107 #define REG_CCR2_AFREQ_MASK             (0xf << REG_CCR2_AFREQ_OFFSET)
 108 
 109 #define REG_PMR1_SB_DAC_OFFSET          7
 110 #define REG_PMR1_SB_OUT_OFFSET          6
 111 #define REG_PMR1_SB_MIX_OFFSET          5
 112 #define REG_PMR1_SB_ADC_OFFSET          4
 113 #define REG_PMR1_SB_LIN_OFFSET          3
 114 #define REG_PMR1_SB_IND_OFFSET          0
 115 
 116 #define REG_PMR2_LRGI_OFFSET            7
 117 #define REG_PMR2_RLGI_OFFSET            6
 118 #define REG_PMR2_LRGOD_OFFSET           5
 119 #define REG_PMR2_RLGOD_OFFSET           4
 120 #define REG_PMR2_GIM_OFFSET             3
 121 #define REG_PMR2_SB_MC_OFFSET           2
 122 #define REG_PMR2_SB_OFFSET              1
 123 #define REG_PMR2_SB_SLEEP_OFFSET        0
 124 
 125 #define REG_IFR_RAMP_UP_DONE_OFFSET     3
 126 #define REG_IFR_RAMP_DOWN_DONE_OFFSET   2
 127 
 128 #define REG_CGR1_GODL_OFFSET            4
 129 #define REG_CGR1_GODL_MASK              (0xf << REG_CGR1_GODL_OFFSET)
 130 #define REG_CGR1_GODR_OFFSET            0
 131 #define REG_CGR1_GODR_MASK              (0xf << REG_CGR1_GODR_OFFSET)
 132 
 133 #define REG_CGR2_GO1R_OFFSET            0
 134 #define REG_CGR2_GO1R_MASK              (0x1f << REG_CGR2_GO1R_OFFSET)
 135 
 136 #define REG_CGR3_GO1L_OFFSET            0
 137 #define REG_CGR3_GO1L_MASK              (0x1f << REG_CGR3_GO1L_OFFSET)
 138 
 139 struct jz_icdc {
 140         struct regmap *regmap;
 141         void __iomem *base;
 142         struct clk *clk;
 143 };
 144 
 145 static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0);
 146 static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600);
 147 
 148 static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
 149         SOC_DOUBLE_TLV("Master Playback Volume",
 150                        JZ4725B_CODEC_REG_CGR1,
 151                        REG_CGR1_GODL_OFFSET,
 152                        REG_CGR1_GODR_OFFSET,
 153                        0xf, 1, jz4725b_dac_tlv),
 154         SOC_DOUBLE_R_TLV("Master Capture Volume",
 155                          JZ4725B_CODEC_REG_CGR3,
 156                          JZ4725B_CODEC_REG_CGR2,
 157                          REG_CGR2_GO1R_OFFSET,
 158                          0x1f, 1, jz4725b_line_tlv),
 159 
 160         SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
 161                    REG_CR1_DAC_MUTE_OFFSET, 1, 1),
 162 
 163         SOC_SINGLE("Deemphasize Filter Playback Switch",
 164                    JZ4725B_CODEC_REG_CR2,
 165                    REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
 166 
 167         SOC_SINGLE("High-Pass Filter Capture Switch",
 168                    JZ4725B_CODEC_REG_CR2,
 169                    REG_CR2_ADC_HPF_OFFSET, 1, 0),
 170 };
 171 
 172 static const char * const jz4725b_codec_adc_src_texts[] = {
 173         "Mic 1", "Mic 2", "Line In", "Mixer",
 174 };
 175 static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
 176 static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
 177                                   JZ4725B_CODEC_REG_CR3,
 178                                   REG_CR3_INSEL_OFFSET,
 179                                   REG_CR3_INSEL_MASK,
 180                                   jz4725b_codec_adc_src_texts,
 181                                   jz4725b_codec_adc_src_values);
 182 static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
 183                         SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum);
 184 
 185 static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
 186         SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
 187                         REG_CR1_BYPASS_OFFSET, 1, 0),
 188 };
 189 
 190 static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
 191                                     struct snd_kcontrol *kcontrol,
 192                                     int event)
 193 {
 194         struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
 195         struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
 196         struct regmap *map = icdc->regmap;
 197         unsigned int val;
 198 
 199         switch (event) {
 200         case SND_SOC_DAPM_PRE_PMU:
 201                 return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
 202                                           BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 0);
 203         case SND_SOC_DAPM_POST_PMU:
 204                 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
 205                                val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
 206                                100000, 500000);
 207         case SND_SOC_DAPM_PRE_PMD:
 208                 return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
 209                                 BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 0);
 210         case SND_SOC_DAPM_POST_PMD:
 211                 return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
 212                                val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
 213                                100000, 500000);
 214         default:
 215                 return -EINVAL;
 216         }
 217 }
 218 
 219 static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
 220         /* DAC */
 221         SND_SOC_DAPM_DAC("DAC", "Playback",
 222                          JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
 223 
 224         /* ADC */
 225         SND_SOC_DAPM_ADC("ADC", "Capture",
 226                          JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
 227 
 228         SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0,
 229                          &jz4725b_codec_adc_src_ctrl),
 230 
 231         /* Mixer */
 232         SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
 233                            REG_PMR1_SB_MIX_OFFSET, 1,
 234                            jz4725b_codec_mixer_controls,
 235                            ARRAY_SIZE(jz4725b_codec_mixer_controls)),
 236         SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
 237                            REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
 238 
 239         SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0),
 240         SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
 241                            REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
 242 
 243         SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
 244                            REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
 245         SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
 246                            REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
 247 
 248         SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
 249                              REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
 250                              jz4725b_out_stage_enable,
 251                              SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 252                              SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 253         SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
 254                            REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
 255 
 256         SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
 257                             REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
 258 
 259         /* Pins */
 260         SND_SOC_DAPM_INPUT("MIC1P"),
 261         SND_SOC_DAPM_INPUT("MIC1N"),
 262         SND_SOC_DAPM_INPUT("MIC2P"),
 263         SND_SOC_DAPM_INPUT("MIC2N"),
 264 
 265         SND_SOC_DAPM_INPUT("LLINEIN"),
 266         SND_SOC_DAPM_INPUT("RLINEIN"),
 267 
 268         SND_SOC_DAPM_OUTPUT("LHPOUT"),
 269         SND_SOC_DAPM_OUTPUT("RHPOUT"),
 270 };
 271 
 272 static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
 273         {"Mic 1", NULL, "MIC1P"},
 274         {"Mic 1", NULL, "MIC1N"},
 275         {"Mic 2", NULL, "MIC2P"},
 276         {"Mic 2", NULL, "MIC2N"},
 277 
 278         {"Line In", NULL, "LLINEIN"},
 279         {"Line In", NULL, "RLINEIN"},
 280 
 281         {"Mixer", "Line In Bypass", "Line In"},
 282         {"DAC to Mixer", NULL, "DAC"},
 283         {"Mixer", NULL, "DAC to Mixer"},
 284 
 285         {"Mixer to ADC", NULL, "Mixer"},
 286         {"ADC Source", "Mixer", "Mixer to ADC"},
 287         {"ADC Source", "Line In", "Line In"},
 288         {"ADC Source", "Mic 1", "Mic 1"},
 289         {"ADC Source", "Mic 2", "Mic 2"},
 290         {"ADC", NULL, "ADC Source"},
 291 
 292         {"Out Stage", NULL, "Mixer"},
 293         {"HP Out", NULL, "Out Stage"},
 294         {"LHPOUT", NULL, "HP Out"},
 295         {"RHPOUT", NULL, "HP Out"},
 296 };
 297 
 298 static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
 299                                         enum snd_soc_bias_level level)
 300 {
 301         struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
 302         struct regmap *map = icdc->regmap;
 303 
 304         switch (level) {
 305         case SND_SOC_BIAS_ON:
 306                 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
 307                                    BIT(REG_PMR2_SB_SLEEP_OFFSET), 0);
 308                 break;
 309         case SND_SOC_BIAS_PREPARE:
 310                 /* Enable sound hardware */
 311                 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
 312                                    BIT(REG_PMR2_SB_OFFSET), 0);
 313                 msleep(224);
 314                 break;
 315         case SND_SOC_BIAS_STANDBY:
 316                 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
 317                                    BIT(REG_PMR2_SB_SLEEP_OFFSET),
 318                                    BIT(REG_PMR2_SB_SLEEP_OFFSET));
 319                 break;
 320         case SND_SOC_BIAS_OFF:
 321                 regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
 322                                    BIT(REG_PMR2_SB_OFFSET),
 323                                    BIT(REG_PMR2_SB_OFFSET));
 324                 break;
 325         }
 326 
 327         return 0;
 328 }
 329 
 330 static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
 331 {
 332         struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
 333         struct regmap *map = icdc->regmap;
 334 
 335         clk_prepare_enable(icdc->clk);
 336 
 337         /* Write CONFIGn (n=1 to 8) bits.
 338          * The value 0x0f is specified in the datasheet as a requirement.
 339          */
 340         regmap_write(map, JZ4725B_CODEC_REG_AICR,
 341                      0xf << REG_AICR_CONFIG1_OFFSET);
 342         regmap_write(map, JZ4725B_CODEC_REG_CCR1,
 343                      0x0 << REG_CCR1_CONFIG4_OFFSET);
 344 
 345         return 0;
 346 }
 347 
 348 static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
 349 {
 350         struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
 351 
 352         clk_disable_unprepare(icdc->clk);
 353 }
 354 
 355 static const struct snd_soc_component_driver jz4725b_codec = {
 356         .probe                  = jz4725b_codec_dev_probe,
 357         .remove                 = jz4725b_codec_dev_remove,
 358         .set_bias_level         = jz4725b_codec_set_bias_level,
 359         .controls               = jz4725b_codec_controls,
 360         .num_controls           = ARRAY_SIZE(jz4725b_codec_controls),
 361         .dapm_widgets           = jz4725b_codec_dapm_widgets,
 362         .num_dapm_widgets       = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
 363         .dapm_routes            = jz4725b_codec_dapm_routes,
 364         .num_dapm_routes        = ARRAY_SIZE(jz4725b_codec_dapm_routes),
 365         .suspend_bias_off       = 1,
 366         .use_pmdown_time        = 1,
 367 };
 368 
 369 static const unsigned int jz4725b_codec_sample_rates[] = {
 370         96000, 48000, 44100, 32000,
 371         24000, 22050, 16000, 12000,
 372         11025, 9600, 8000,
 373 };
 374 
 375 static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
 376         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 377 {
 378         struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
 379         unsigned int rate, bit_width;
 380 
 381         switch (params_format(params)) {
 382         case SNDRV_PCM_FORMAT_S16_LE:
 383                 bit_width = 0;
 384                 break;
 385         case SNDRV_PCM_FORMAT_S18_3LE:
 386                 bit_width = 1;
 387                 break;
 388         case SNDRV_PCM_FORMAT_S20_3LE:
 389                 bit_width = 2;
 390                 break;
 391         case SNDRV_PCM_FORMAT_S24_3LE:
 392                 bit_width = 3;
 393                 break;
 394         default:
 395                 return -EINVAL;
 396         }
 397 
 398         for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
 399                 if (jz4725b_codec_sample_rates[rate] == params_rate(params))
 400                         break;
 401         }
 402 
 403         if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
 404                 return -EINVAL;
 405 
 406         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 407                 regmap_update_bits(icdc->regmap,
 408                                    JZ4725B_CODEC_REG_CR2,
 409                                    REG_CR2_DAC_ADWL_MASK,
 410                                    bit_width << REG_CR2_DAC_ADWL_OFFSET);
 411 
 412                 regmap_update_bits(icdc->regmap,
 413                                    JZ4725B_CODEC_REG_CCR2,
 414                                    REG_CCR2_DFREQ_MASK,
 415                                    rate << REG_CCR2_DFREQ_OFFSET);
 416         } else {
 417                 regmap_update_bits(icdc->regmap,
 418                                    JZ4725B_CODEC_REG_CR2,
 419                                    REG_CR2_ADC_ADWL_MASK,
 420                                    bit_width << REG_CR2_ADC_ADWL_OFFSET);
 421 
 422                 regmap_update_bits(icdc->regmap,
 423                                    JZ4725B_CODEC_REG_CCR2,
 424                                    REG_CCR2_AFREQ_MASK,
 425                                    rate << REG_CCR2_AFREQ_OFFSET);
 426         }
 427 
 428         return 0;
 429 }
 430 
 431 static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
 432         .hw_params = jz4725b_codec_hw_params,
 433 };
 434 
 435 #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S18_3LE | \
 436                          SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
 437 
 438 static struct snd_soc_dai_driver jz4725b_codec_dai = {
 439         .name = "jz4725b-hifi",
 440         .playback = {
 441                 .stream_name = "Playback",
 442                 .channels_min = 2,
 443                 .channels_max = 2,
 444                 .rates = SNDRV_PCM_RATE_8000_96000,
 445                 .formats = JZ_ICDC_FORMATS,
 446         },
 447         .capture = {
 448                 .stream_name = "Capture",
 449                 .channels_min = 2,
 450                 .channels_max = 2,
 451                 .rates = SNDRV_PCM_RATE_8000_96000,
 452                 .formats = JZ_ICDC_FORMATS,
 453         },
 454         .ops = &jz4725b_codec_dai_ops,
 455 };
 456 
 457 static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
 458 {
 459         return reg == JZ4725B_CODEC_REG_IFR;
 460 }
 461 
 462 static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
 463 {
 464         return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
 465 }
 466 
 467 static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
 468 {
 469         u32 reg;
 470 
 471         return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
 472                                   !(reg & ICDC_RGADW_RGWR), 1000, 10000);
 473 }
 474 
 475 static int jz4725b_codec_reg_read(void *context, unsigned int reg,
 476                                   unsigned int *val)
 477 {
 478         struct jz_icdc *icdc = context;
 479         unsigned int i;
 480         u32 tmp;
 481         int ret;
 482 
 483         ret = jz4725b_codec_io_wait(icdc);
 484         if (ret)
 485                 return ret;
 486 
 487         tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
 488         tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
 489             | (reg << ICDC_RGADW_RGADDR_OFFSET);
 490         writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
 491 
 492         /* wait 6+ cycles */
 493         for (i = 0; i < 6; i++)
 494                 *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
 495                         ICDC_RGDATA_RGDOUT_MASK;
 496 
 497         return 0;
 498 }
 499 
 500 static int jz4725b_codec_reg_write(void *context, unsigned int reg,
 501                                    unsigned int val)
 502 {
 503         struct jz_icdc *icdc = context;
 504         int ret;
 505 
 506         ret = jz4725b_codec_io_wait(icdc);
 507         if (ret)
 508                 return ret;
 509 
 510         writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
 511                         icdc->base + ICDC_RGADW_OFFSET);
 512 
 513         ret = jz4725b_codec_io_wait(icdc);
 514         if (ret)
 515                 return ret;
 516 
 517         return 0;
 518 }
 519 
 520 static const u8 jz4725b_codec_reg_defaults[] = {
 521         0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
 522         0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
 523         0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
 524         0x07, 0x44, 0x1f, 0x00,
 525 };
 526 
 527 static const struct regmap_config jz4725b_codec_regmap_config = {
 528         .reg_bits = 7,
 529         .val_bits = 8,
 530 
 531         .max_register = JZ4725B_CODEC_REG_AGC5,
 532         .volatile_reg = jz4725b_codec_volatile,
 533         .readable_reg = jz4725b_codec_can_access_reg,
 534         .writeable_reg = jz4725b_codec_can_access_reg,
 535 
 536         .reg_read = jz4725b_codec_reg_read,
 537         .reg_write = jz4725b_codec_reg_write,
 538 
 539         .reg_defaults_raw = jz4725b_codec_reg_defaults,
 540         .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
 541         .cache_type = REGCACHE_FLAT,
 542 };
 543 
 544 static int jz4725b_codec_probe(struct platform_device *pdev)
 545 {
 546         struct device *dev = &pdev->dev;
 547         struct jz_icdc *icdc;
 548         int ret;
 549 
 550         icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
 551         if (!icdc)
 552                 return -ENOMEM;
 553 
 554         icdc->base = devm_platform_ioremap_resource(pdev, 0);
 555         if (IS_ERR(icdc->base))
 556                 return PTR_ERR(icdc->base);
 557 
 558         icdc->regmap = devm_regmap_init(dev, NULL, icdc,
 559                                         &jz4725b_codec_regmap_config);
 560         if (IS_ERR(icdc->regmap))
 561                 return PTR_ERR(icdc->regmap);
 562 
 563         icdc->clk = devm_clk_get(&pdev->dev, "aic");
 564         if (IS_ERR(icdc->clk))
 565                 return PTR_ERR(icdc->clk);
 566 
 567         platform_set_drvdata(pdev, icdc);
 568 
 569         ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
 570                                               &jz4725b_codec_dai, 1);
 571         if (ret)
 572                 dev_err(dev, "Failed to register codec\n");
 573 
 574         return ret;
 575 }
 576 
 577 #ifdef CONFIG_OF
 578 static const struct of_device_id jz4725b_codec_of_matches[] = {
 579         { .compatible = "ingenic,jz4725b-codec", },
 580         { }
 581 };
 582 MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
 583 #endif
 584 
 585 static struct platform_driver jz4725b_codec_driver = {
 586         .probe = jz4725b_codec_probe,
 587         .driver = {
 588                 .name = "jz4725b-codec",
 589                 .of_match_table = of_match_ptr(jz4725b_codec_of_matches),
 590         },
 591 };
 592 module_platform_driver(jz4725b_codec_driver);
 593 
 594 MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
 595 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
 596 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */