···5555 description: TDM TX current sense time slot.56565757 '#sound-dai-cells':5858- const: 15858+ # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward5959+ # compatibility but is deprecated.6060+ enum: [0, 1]59616062required:6163 - compatible···7472 codec: codec@4c {7573 compatible = "ti,tas2562";7674 reg = <0x4c>;7777- #sound-dai-cells = <1>;7575+ #sound-dai-cells = <0>;7876 interrupt-parent = <&gpio1>;7977 interrupts = <14>;8078 shutdown-gpios = <&gpio1 15 0>;
···5757 - 1 # Falling edge58585959 '#sound-dai-cells':6060- const: 16060+ # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward6161+ # compatibility but is deprecated.6262+ enum: [0, 1]61636264required:6365 - compatible···7674 codec: codec@41 {7775 compatible = "ti,tas2770";7876 reg = <0x41>;7979- #sound-dai-cells = <1>;7777+ #sound-dai-cells = <0>;8078 interrupt-parent = <&gpio1>;8179 interrupts = <14>;8280 reset-gpio = <&gpio1 15 0>;
···5050 description: TDM TX voltage sense time slot.51515252 '#sound-dai-cells':5353- const: 15353+ # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward5454+ # compatibility but is deprecated.5555+ enum: [0, 1]54565557required:5658 - compatible···6967 codec: codec@38 {7068 compatible = "ti,tas2764";7169 reg = <0x38>;7272- #sound-dai-cells = <1>;7070+ #sound-dai-cells = <0>;7371 interrupt-parent = <&gpio1>;7472 interrupts = <14>;7573 reset-gpios = <&gpio1 15 0>;
···218218 return 0;219219}220220221221+static int jz4740_i2s_get_i2sdiv(unsigned long mclk, unsigned long rate,222222+ unsigned long i2sdiv_max)223223+{224224+ unsigned long div, rate1, rate2, err1, err2;225225+226226+ div = mclk / (64 * rate);227227+ if (div == 0)228228+ div = 1;229229+230230+ rate1 = mclk / (64 * div);231231+ rate2 = mclk / (64 * (div + 1));232232+233233+ err1 = abs(rate1 - rate);234234+ err2 = abs(rate2 - rate);235235+236236+ /*237237+ * Choose the divider that produces the smallest error in the238238+ * output rate and reject dividers with a 5% or higher error.239239+ * In the event that both dividers are outside the acceptable240240+ * error margin, reject the rate to prevent distorted audio.241241+ * (The number 5% is arbitrary.)242242+ */243243+ if (div <= i2sdiv_max && err1 <= err2 && err1 < rate/20)244244+ return div;245245+ if (div < i2sdiv_max && err2 < rate/20)246246+ return div + 1;247247+248248+ return -EINVAL;249249+}250250+221251static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,222252 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)223253{224254 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);225255 struct regmap_field *div_field;256256+ unsigned long i2sdiv_max;226257 unsigned int sample_size;227227- uint32_t ctrl;228228- int div;258258+ uint32_t ctrl, conf;259259+ int div = 1;229260230261 regmap_read(i2s->regmap, JZ_REG_AIC_CTRL, &ctrl);231231-232232- div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params));262262+ regmap_read(i2s->regmap, JZ_REG_AIC_CONF, &conf);233263234264 switch (params_format(params)) {235265 case SNDRV_PCM_FORMAT_S8:···288258 ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;289259290260 div_field = i2s->field_i2sdiv_playback;261261+ i2sdiv_max = GENMASK(i2s->soc_info->field_i2sdiv_playback.msb,262262+ i2s->soc_info->field_i2sdiv_playback.lsb);291263 } else {292264 ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE;293265 ctrl |= FIELD_PREP(JZ_AIC_CTRL_INPUT_SAMPLE_SIZE, sample_size);294266295267 div_field = i2s->field_i2sdiv_capture;268268+ i2sdiv_max = GENMASK(i2s->soc_info->field_i2sdiv_capture.msb,269269+ i2s->soc_info->field_i2sdiv_capture.lsb);270270+ }271271+272272+ /*273273+ * Only calculate I2SDIV if we're supplying the bit or frame clock.274274+ * If the codec is supplying both clocks then the divider output is275275+ * unused, and we don't want it to limit the allowed sample rates.276276+ */277277+ if (conf & (JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER)) {278278+ div = jz4740_i2s_get_i2sdiv(clk_get_rate(i2s->clk_i2s),279279+ params_rate(params), i2sdiv_max);280280+ if (div < 0)281281+ return div;296282 }297283298284 regmap_write(i2s->regmap, JZ_REG_AIC_CTRL, ctrl);