Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Add support for an external Master Clock in the

Merge series from Herve Codina <herve.codina@bootlin.com>:

The Cirrus CS4271 codec can have its Master Clock provided by an
external clock when no crystal is used.

This series adds support for this external Master clock.

+40 -3
+10
Documentation/devicetree/bindings/sound/cirrus,cs4271.yaml
··· 25 25 reg: 26 26 maxItems: 1 27 27 28 + clocks: 29 + items: 30 + - description: 31 + Master clock connected to the MCLK pin if MCLK is an input (i.e. no 32 + crystal used). 33 + 34 + clock-names: 35 + items: 36 + - const: mclk 37 + 28 38 spi-cpha: true 29 39 30 40 spi-cpol: true
+30 -3
sound/soc/codecs/cs4271.c
··· 10 10 * DAPM support not implemented. 11 11 */ 12 12 13 + #include <linux/clk.h> 13 14 #include <linux/module.h> 14 15 #include <linux/slab.h> 15 16 #include <linux/delay.h> ··· 164 163 /* enable soft reset workaround */ 165 164 bool enable_soft_reset; 166 165 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 166 + struct clk *clk; 167 167 }; 168 168 169 169 static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = { ··· 507 505 return ret; 508 506 509 507 regcache_mark_dirty(cs4271->regmap); 508 + clk_disable_unprepare(cs4271->clk); 510 509 regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies); 511 510 512 511 return 0; ··· 522 519 cs4271->supplies); 523 520 if (ret < 0) { 524 521 dev_err(component->dev, "Failed to enable regulators: %d\n", ret); 522 + return ret; 523 + } 524 + 525 + ret = clk_prepare_enable(cs4271->clk); 526 + if (ret) { 527 + dev_err(component->dev, "Failed to enable clk: %d\n", ret); 525 528 return ret; 526 529 } 527 530 ··· 585 576 cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; 586 577 } 587 578 579 + ret = clk_prepare_enable(cs4271->clk); 580 + if (ret) { 581 + dev_err(component->dev, "Failed to enable clk: %d\n", ret); 582 + goto err_disable_regulators; 583 + } 584 + 588 585 /* Reset codec */ 589 586 cs4271_reset(component); 590 587 591 588 ret = regcache_sync(cs4271->regmap); 592 589 if (ret < 0) 593 - return ret; 590 + goto err_disable_clk; 594 591 595 592 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, 596 593 CS4271_MODE2_PDN | CS4271_MODE2_CPEN, 597 594 CS4271_MODE2_PDN | CS4271_MODE2_CPEN); 598 595 if (ret < 0) 599 - return ret; 596 + goto err_disable_clk; 600 597 ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2, 601 598 CS4271_MODE2_PDN, 0); 602 599 if (ret < 0) 603 - return ret; 600 + goto err_disable_clk; 601 + 604 602 /* Power-up sequence requires 85 uS */ 605 603 udelay(85); 606 604 ··· 617 601 CS4271_MODE2_MUTECAEQUB); 618 602 619 603 return 0; 604 + 605 + err_disable_clk: 606 + clk_disable_unprepare(cs4271->clk); 607 + err_disable_regulators: 608 + regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies); 609 + return ret; 620 610 } 621 611 622 612 static void cs4271_component_remove(struct snd_soc_component *component) ··· 634 612 635 613 regcache_mark_dirty(cs4271->regmap); 636 614 regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies); 615 + clk_disable_unprepare(cs4271->clk); 637 616 }; 638 617 639 618 static const struct snd_soc_component_driver soc_component_dev_cs4271 = { ··· 668 645 return dev_err_probe(dev, PTR_ERR(cs4271->reset), 669 646 "error retrieving RESET GPIO\n"); 670 647 gpiod_set_consumer_name(cs4271->reset, "CS4271 Reset"); 648 + 649 + cs4271->clk = devm_clk_get_optional(dev, "mclk"); 650 + if (IS_ERR(cs4271->clk)) 651 + return dev_err_probe(dev, PTR_ERR(cs4271->clk), "Failed to get mclk\n"); 671 652 672 653 for (i = 0; i < ARRAY_SIZE(supply_names); i++) 673 654 cs4271->supplies[i].supply = supply_names[i];