From: Jeff Chang jeff_chang@richtek.com
1. add parsing register initial table via device tree. 2. add applying initial register value function at component driver.
Signed-off-by: Jeff Chang jeff_chang@richtek.com --- Documentation/devicetree/bindings/sound/mt6660.txt | 53 ++++++++++ sound/soc/codecs/mt6660.c | 114 ++++++++++++++++++++- 2 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/mt6660.txt
Following Mr. Mark's Suggestion, I create another patch for applying our chip INIT SETTING.
diff --git a/Documentation/devicetree/bindings/sound/mt6660.txt b/Documentation/devicetree/bindings/sound/mt6660.txt new file mode 100644 index 0000000..2a1736b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt6660.txt @@ -0,0 +1,53 @@ +MT6660 MediaTek Speaker Amplifier + +This device supports I2C mode only. + +Required properties: + + - compatible : "mediatek,mt6660" + + - reg : The I2C slave address + +Optional properties: + + - rt,init_setting_num : The initial register setting element number. + + - rt,init_setting_addr : the addreses array for INIT Setting table. + + - rt,init_setting_mask : the mask array for INIT Setting table. + + - rt,init_setting_val : the value array for INIT Setting table. + +Example: + + mt6660@34 { + status = "ok"; + compatible = "mediatek,mt6660"; + reg = <0x34>; + rt,init_setting_num = <26>; + rt,init_setting_addr = + <0x20 0x30 0x50 0xB1 + 0xD3 0xE0 0x98 0xB9 + 0xB7 0xB6 0x6B 0x07 + 0xBB 0x69 0xBD 0x70 + 0x7C 0x46 0x1A 0x1B + 0x51 0xA2 0x33 0x4C + 0x15 0x68>; + rt,init_setting_mask = + <0x80 0x01 0x1c 0x0c + 0x03 0x01 0x44 0xff + 0x7777 0x07 0xe0 0xff + 0xff 0xff 0xffff 0xff + 0xff 0xff 0xffffffff 0xffffffff + 0xff 0xff 0xffff 0xffff + 0x1800 0x1f>; + rt,init_setting_val = + <0x00 0x00 0x04 0x00 + 0x03 0x00 0x04 0x82 + 0x7273 0x03 0x20 0x70 + 0x20 0x40 0x17f8 0x15 + 0x00 0x1d 0x7fdb7ffe 0x7fdb7ffe + 0x58 0xce 0x7fff 0x0116 + 0x0800 0x07>; + }; + diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index a36c416..5df2780 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -9,7 +9,6 @@ #include <linux/i2c.h> #include <linux/pm_runtime.h> #include <linux/delay.h> -#include <linux/debugfs.h> #include <sound/soc.h> #include <sound/tlv.h> #include <sound/pcm_params.h> @@ -225,14 +224,48 @@ static int _mt6660_chip_power_on(struct mt6660_chip *chip, int on_off) 0x01, on_off ? 0x00 : 0x01); }
+static int mt6660_apply_plat_data(struct mt6660_chip *chip, + struct snd_soc_component *component) +{ + size_t i; + int num = chip->plat_data.init_setting_num; + int ret; + + ret = _mt6660_chip_power_on(chip, 1); + if (ret < 0) { + dev_err(chip->dev, "%s power on failed\n", __func__); + return ret; + } + + for (i = 0; i < num; i++) { + ret = snd_soc_component_update_bits(component, + chip->plat_data.init_setting_addr[i], + chip->plat_data.init_setting_mask[i], + chip->plat_data.init_setting_val[i]); + if (ret < 0) + return ret; + } + ret = _mt6660_chip_power_on(chip, 0); + if (ret < 0) { + dev_err(chip->dev, "%s power on failed\n", __func__); + return ret; + } + return 0; +} + static int mt6660_component_probe(struct snd_soc_component *component) { struct mt6660_chip *chip = snd_soc_component_get_drvdata(component); + int ret;
dev_dbg(component->dev, "%s\n", __func__); snd_soc_component_init_regmap(component, chip->regmap);
- return 0; + ret = mt6660_apply_plat_data(chip, component); + if (ret < 0) + dev_err(chip->dev, "mt6660 apply plat data failed\n"); + + return ret; }
static void mt6660_component_remove(struct snd_soc_component *component) @@ -386,6 +419,75 @@ static int _mt6660_read_chip_revision(struct mt6660_chip *chip) return 0; }
+static int mt6660_parse_dt(struct mt6660_chip *chip, struct device *dev) +{ + struct device_node *np = dev->of_node; + u32 val; + size_t i; + + if (!np) { + dev_err(dev, "no device node\n"); + return -EINVAL; + } + + if (of_property_read_u32(np, "rt,init_setting_num", &val)) { + dev_err(dev, "no init setting\n"); + chip->plat_data.init_setting_num = 0; + } else { + chip->plat_data.init_setting_num = val; + } + + if (chip->plat_data.init_setting_num) { + chip->plat_data.init_setting_addr = + devm_kzalloc(dev, sizeof(u32) * + chip->plat_data.init_setting_num, GFP_KERNEL); + if (!chip->plat_data.init_setting_addr) { + dev_err(dev, "%s addr memory alloc failed\n", __func__); + return -ENOMEM; + } + chip->plat_data.init_setting_mask = + devm_kzalloc(dev, sizeof(u32) * + chip->plat_data.init_setting_num, GFP_KERNEL); + if (!chip->plat_data.init_setting_mask) { + dev_err(dev, "%s mask memory alloc failed\n", __func__); + return -ENOMEM; + } + chip->plat_data.init_setting_val = + devm_kzalloc(dev, sizeof(u32) * + chip->plat_data.init_setting_num, GFP_KERNEL); + if (!chip->plat_data.init_setting_val) { + dev_err(dev, "%s val memory alloc failed\n", __func__); + return -ENOMEM; + } + + if (of_property_read_u32_array(np, "rt,init_setting_addr", + chip->plat_data.init_setting_addr, + chip->plat_data.init_setting_num)) { + dev_err(dev, "no init setting addr\n"); + } + if (of_property_read_u32_array(np, "rt,init_setting_mask", + chip->plat_data.init_setting_mask, + chip->plat_data.init_setting_num)) { + dev_err(dev, "no init setting mask\n"); + } + if (of_property_read_u32_array(np, "rt,init_setting_val", + chip->plat_data.init_setting_val, + chip->plat_data.init_setting_num)) { + dev_err(dev, "no init setting val\n"); + } + } + + dev_dbg(dev, "%s, init stting table, num = %d\n", __func__, + chip->plat_data.init_setting_num); + for (i = 0; i < chip->plat_data.init_setting_num; i++) { + dev_dbg(dev, "0x%02x, 0x%08x, 0x%08x\n", + chip->plat_data.init_setting_addr[i], + chip->plat_data.init_setting_mask[i], + chip->plat_data.init_setting_val[i]); + } + return 0; +} + static int mt6660_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -401,6 +503,12 @@ static int mt6660_i2c_probe(struct i2c_client *client, mutex_init(&chip->io_lock); i2c_set_clientdata(client, chip);
+ ret = mt6660_parse_dt(chip, &client->dev); + if (ret < 0) { + dev_err(&client->dev, "parsing dts failed\n"); + return ret; + } + chip->regmap = devm_regmap_init(&client->dev, NULL, chip, &mt6660_regmap_config); if (IS_ERR(chip->regmap)) { @@ -506,4 +614,4 @@ module_i2c_driver(mt6660_i2c_driver); MODULE_AUTHOR("Jeff Chang jeff_chang@richtek.com"); MODULE_DESCRIPTION("MT6660 SPKAMP Driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.0.7_G"); +MODULE_VERSION("1.0.8_G");