diff options
Diffstat (limited to 'sound/pci/hda/cs35l41_hda.c')
-rw-r--r-- | sound/pci/hda/cs35l41_hda.c | 438 |
1 files changed, 236 insertions, 202 deletions
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 718595380868..cce27a86267f 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -17,163 +17,88 @@ #include "cs35l41_hda.h" static const struct reg_sequence cs35l41_hda_config[] = { - { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3200000Hz, BCLK Input, PLL_REFCLK_EN = 1 + { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1 { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz { CS35L41_SP_ENABLES, 0x00010000 }, // ASP_RX1_EN = 1 { CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz - { CS35L41_SP_FORMAT, 0x20200200 }, // 24 bits, I2S, BCLK Slave, FSYNC Slave + { CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer { CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1 { CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB - { CS35L41_PWR_CTRL2, 0x00000001 }, // AMP_EN = 1 }; -static const struct reg_sequence cs35l41_hda_start_bst[] = { - { CS35L41_PWR_CTRL2, 0x00000021 }, // BST_EN = 10, AMP_EN = 1 - { CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1 -}; - -static const struct reg_sequence cs35l41_hda_stop_bst[] = { - { CS35L41_PWR_CTRL1, 0x00000000, 3000}, // set GLOBAL_EN = 0 -}; - -// only on amps where GPIO1 is used to control ext. VSPK switch -static const struct reg_sequence cs35l41_start_ext_vspk[] = { - { 0x00000040, 0x00000055 }, - { 0x00000040, 0x000000AA }, - { 0x00007438, 0x00585941 }, - { 0x00007414, 0x08C82222 }, - { 0x0000742C, 0x00000009 }, - { 0x00011008, 0x00008001 }, - { 0x0000742C, 0x0000000F }, - { 0x0000742C, 0x00000079 }, - { 0x00007438, 0x00585941 }, - { CS35L41_PWR_CTRL1, 0x00000001, 3000}, // set GLOBAL_EN = 1 - { 0x0000742C, 0x000000F9 }, - { 0x00007438, 0x00580941 }, - { 0x00000040, 0x000000CC }, - { 0x00000040, 0x00000033 }, -}; - -//only on amps where GPIO1 is used to control ext. VSPK switch -static const struct reg_sequence cs35l41_stop_ext_vspk[] = { - { 0x00000040, 0x00000055 }, - { 0x00000040, 0x000000AA }, - { 0x00007438, 0x00585941 }, - { 0x00002014, 0x00000000, 3000}, // set GLOBAL_EN = 0 - { 0x0000742C, 0x00000009 }, - { 0x00007438, 0x00580941 }, - { 0x00011008, 0x00000001 }, - { 0x0000393C, 0x000000C0, 6000}, - { 0x0000393C, 0x00000000 }, - { 0x00007414, 0x00C82222 }, - { 0x0000742C, 0x00000000 }, - { 0x00000040, 0x000000CC }, - { 0x00000040, 0x00000033 }, -}; - -static const struct reg_sequence cs35l41_safe_to_active[] = { - { 0x00000040, 0x00000055 }, - { 0x00000040, 0x000000AA }, - { 0x0000742C, 0x0000000F }, - { 0x0000742C, 0x00000079 }, - { 0x00007438, 0x00585941 }, - { CS35L41_PWR_CTRL1, 0x00000001, 2000 }, // GLOBAL_EN = 1 - { 0x0000742C, 0x000000F9 }, - { 0x00007438, 0x00580941 }, - { 0x00000040, 0x000000CC }, - { 0x00000040, 0x00000033 }, -}; - -static const struct reg_sequence cs35l41_active_to_safe[] = { - { 0x00000040, 0x00000055 }, - { 0x00000040, 0x000000AA }, - { 0x00007438, 0x00585941 }, +static const struct reg_sequence cs35l41_hda_mute[] = { + { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute - { CS35L41_PWR_CTRL2, 0x00000000 }, // AMP_EN = 0 - { CS35L41_PWR_CTRL1, 0x00000000 }, - { 0x0000742C, 0x00000009, 2000 }, - { 0x00007438, 0x00580941 }, - { 0x00000040, 0x000000CC }, - { 0x00000040, 0x00000033 }, -}; - -static const struct reg_sequence cs35l41_reset_to_safe[] = { - { 0x00000040, 0x00000055 }, - { 0x00000040, 0x000000AA }, - { 0x00007438, 0x00585941 }, - { 0x00007414, 0x08C82222 }, - { 0x0000742C, 0x00000009 }, - { 0x00000040, 0x000000CC }, - { 0x00000040, 0x00000033 }, -}; - -static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_no_bst = { - .probe = cs35l41_reset_to_safe, - .num_probe = ARRAY_SIZE(cs35l41_reset_to_safe), - .open = cs35l41_hda_config, - .num_open = ARRAY_SIZE(cs35l41_hda_config), - .prepare = cs35l41_safe_to_active, - .num_prepare = ARRAY_SIZE(cs35l41_safe_to_active), - .cleanup = cs35l41_active_to_safe, - .num_cleanup = ARRAY_SIZE(cs35l41_active_to_safe), }; -static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_ext_bst = { - .open = cs35l41_hda_config, - .num_open = ARRAY_SIZE(cs35l41_hda_config), - .prepare = cs35l41_start_ext_vspk, - .num_prepare = ARRAY_SIZE(cs35l41_start_ext_vspk), - .cleanup = cs35l41_stop_ext_vspk, - .num_cleanup = ARRAY_SIZE(cs35l41_stop_ext_vspk), -}; +/* Protection release cycle to get the speaker out of Safe-Mode */ +static void cs35l41_error_release(struct device *dev, struct regmap *regmap, unsigned int mask) +{ + regmap_write(regmap, CS35L41_PROTECT_REL_ERR_IGN, 0); + regmap_set_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask); + regmap_clear_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask); +} -static const struct cs35l41_hda_reg_sequence cs35l41_hda_reg_seq_int_bst = { - .open = cs35l41_hda_config, - .num_open = ARRAY_SIZE(cs35l41_hda_config), - .prepare = cs35l41_hda_start_bst, - .num_prepare = ARRAY_SIZE(cs35l41_hda_start_bst), - .cleanup = cs35l41_hda_stop_bst, - .num_cleanup = ARRAY_SIZE(cs35l41_hda_stop_bst), -}; +/* Clear all errors to release safe mode. Global Enable must be cleared first. */ +static void cs35l41_irq_release(struct cs35l41_hda *cs35l41) +{ + cs35l41_error_release(cs35l41->dev, cs35l41->regmap, cs35l41->irq_errors); + cs35l41->irq_errors = 0; +} static void cs35l41_hda_playback_hook(struct device *dev, int action) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); - const struct cs35l41_hda_reg_sequence *reg_seq = cs35l41->reg_seq; struct regmap *reg = cs35l41->regmap; int ret = 0; switch (action) { case HDA_GEN_PCM_ACT_OPEN: - if (reg_seq->open) - ret = regmap_multi_reg_write(reg, reg_seq->open, reg_seq->num_open); + regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config)); + ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2, + CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT); + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) + regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001); break; case HDA_GEN_PCM_ACT_PREPARE: - if (reg_seq->prepare) - ret = regmap_multi_reg_write(reg, reg_seq->prepare, reg_seq->num_prepare); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); break; case HDA_GEN_PCM_ACT_CLEANUP: - if (reg_seq->cleanup) - ret = regmap_multi_reg_write(reg, reg_seq->cleanup, reg_seq->num_cleanup); + regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); + ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0); break; case HDA_GEN_PCM_ACT_CLOSE: - if (reg_seq->close) - ret = regmap_multi_reg_write(reg, reg_seq->close, reg_seq->num_close); + ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2, + CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) + regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001); + cs35l41_irq_release(cs35l41); break; default: - ret = -EINVAL; + dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action); break; } if (ret) - dev_warn(cs35l41->dev, "Failed to apply multi reg write: %d\n", ret); + dev_err(cs35l41->dev, "Regmap access fail: %d\n", ret); } static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + static const char * const channel_name[] = { "L", "R" }; + + if (!cs35l41->amp_name) { + if (*rx_slot >= ARRAY_SIZE(channel_name)) + return -EINVAL; + + cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%s%d", + channel_name[*rx_slot], cs35l41->channel_index); + if (!cs35l41->amp_name) + return -ENOMEM; + } return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num, rx_slot); @@ -194,7 +119,6 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas comps->dev = dev; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); comps->playback_hook = cs35l41_hda_playback_hook; - comps->set_channel_map = cs35l41_hda_channel_map; return 0; } @@ -213,67 +137,169 @@ static const struct component_ops cs35l41_hda_comp_ops = { .unbind = cs35l41_hda_unbind, }; -static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41, - const struct cs35l41_hda_hw_config *hw_cfg) +static irqreturn_t cs35l41_bst_short_err(int irq, void *data) { - bool internal_boost = false; - int ret; + struct cs35l41_hda *cs35l41 = data; - if (!hw_cfg) { - cs35l41->reg_seq = &cs35l41_hda_reg_seq_no_bst; - return 0; - } + dev_crit_ratelimited(cs35l41->dev, "LBST Error\n"); + set_bit(CS35L41_BST_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors); - if (hw_cfg->bst_ind || hw_cfg->bst_cap || hw_cfg->bst_ipk) - internal_boost = true; + return IRQ_HANDLED; +} - switch (hw_cfg->gpio1_func) { - case CS35L41_NOT_USED: - break; - case CS35l41_VSPK_SWITCH: - regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL, - CS35L41_GPIO1_CTRL_MASK, 1 << CS35L41_GPIO1_CTRL_SHIFT); - break; - case CS35l41_SYNC: - regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL, - CS35L41_GPIO1_CTRL_MASK, 2 << CS35L41_GPIO1_CTRL_SHIFT); - break; - default: - dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n", hw_cfg->gpio1_func); - return -EINVAL; - } +static irqreturn_t cs35l41_bst_dcm_uvp_err(int irq, void *data) +{ + struct cs35l41_hda *cs35l41 = data; - switch (hw_cfg->gpio2_func) { - case CS35L41_NOT_USED: - break; - case CS35L41_INTERRUPT: - regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL, - CS35L41_GPIO2_CTRL_MASK, 2 << CS35L41_GPIO2_CTRL_SHIFT); - break; - default: - dev_err(cs35l41->dev, "Invalid function %d for GPIO2\n", hw_cfg->gpio2_func); + dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n"); + set_bit(CS35L41_BST_UVP_ERR_RLS_SHIFT, &cs35l41->irq_errors); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l41_bst_ovp_err(int irq, void *data) +{ + struct cs35l41_hda *cs35l41 = data; + + dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n"); + set_bit(CS35L41_BST_OVP_ERR_RLS_SHIFT, &cs35l41->irq_errors); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l41_temp_err(int irq, void *data) +{ + struct cs35l41_hda *cs35l41 = data; + + dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n"); + set_bit(CS35L41_TEMP_ERR_RLS_SHIFT, &cs35l41->irq_errors); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l41_temp_warn(int irq, void *data) +{ + struct cs35l41_hda *cs35l41 = data; + + dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n"); + set_bit(CS35L41_TEMP_WARN_ERR_RLS_SHIFT, &cs35l41->irq_errors); + + return IRQ_HANDLED; +} + +static irqreturn_t cs35l41_amp_short(int irq, void *data) +{ + struct cs35l41_hda *cs35l41 = data; + + dev_crit_ratelimited(cs35l41->dev, "Amp short error\n"); + set_bit(CS35L41_AMP_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors); + + return IRQ_HANDLED; +} + +static const struct cs35l41_irq cs35l41_irqs[] = { + CS35L41_IRQ(BST_OVP_ERR, "Boost Overvoltage Error", cs35l41_bst_ovp_err), + CS35L41_IRQ(BST_DCM_UVP_ERR, "Boost Undervoltage Error", cs35l41_bst_dcm_uvp_err), + CS35L41_IRQ(BST_SHORT_ERR, "Boost Inductor Short Error", cs35l41_bst_short_err), + CS35L41_IRQ(TEMP_WARN, "Temperature Warning", cs35l41_temp_warn), + CS35L41_IRQ(TEMP_ERR, "Temperature Error", cs35l41_temp_err), + CS35L41_IRQ(AMP_SHORT_ERR, "Amp Short", cs35l41_amp_short), +}; + +static const struct regmap_irq cs35l41_reg_irqs[] = { + CS35L41_REG_IRQ(IRQ1_STATUS1, BST_OVP_ERR), + CS35L41_REG_IRQ(IRQ1_STATUS1, BST_DCM_UVP_ERR), + CS35L41_REG_IRQ(IRQ1_STATUS1, BST_SHORT_ERR), + CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_WARN), + CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_ERR), + CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR), +}; + +static const struct regmap_irq_chip cs35l41_regmap_irq_chip = { + .name = "cs35l41 IRQ1 Controller", + .status_base = CS35L41_IRQ1_STATUS1, + .mask_base = CS35L41_IRQ1_MASK1, + .ack_base = CS35L41_IRQ1_STATUS1, + .num_regs = 4, + .irqs = cs35l41_reg_irqs, + .num_irqs = ARRAY_SIZE(cs35l41_reg_irqs), +}; + +static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) +{ + struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; + bool using_irq = false; + int irq, irq_pol; + int ret; + int i; + + if (!cs35l41->hw_cfg.valid) return -EINVAL; + + ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg); + if (ret) + return ret; + + if (hw_cfg->gpio1.valid) { + switch (hw_cfg->gpio1.func) { + case CS35L41_NOT_USED: + break; + case CS35l41_VSPK_SWITCH: + hw_cfg->gpio1.func = CS35L41_GPIO1_GPIO; + hw_cfg->gpio1.out_en = true; + break; + case CS35l41_SYNC: + hw_cfg->gpio1.func = CS35L41_GPIO1_MDSYNC; + break; + default: + dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n", + hw_cfg->gpio1.func); + return -EINVAL; + } } - if (internal_boost) { - cs35l41->reg_seq = &cs35l41_hda_reg_seq_int_bst; - if (!(hw_cfg->bst_ind && hw_cfg->bst_cap && hw_cfg->bst_ipk)) + if (hw_cfg->gpio2.valid) { + switch (hw_cfg->gpio2.func) { + case CS35L41_NOT_USED: + break; + case CS35L41_INTERRUPT: + using_irq = true; + break; + default: + dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func); return -EINVAL; - ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap, - hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk); + } + } + + irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg); + + if (cs35l41->irq && using_irq) { + ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq, + IRQF_ONESHOT | IRQF_SHARED | irq_pol, + 0, &cs35l41_regmap_irq_chip, &cs35l41->irq_data); if (ret) return ret; - } else { - cs35l41->reg_seq = &cs35l41_hda_reg_seq_ext_bst; + + for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) { + irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL, + cs35l41_irqs[i].handler, + IRQF_ONESHOT | IRQF_SHARED | irq_pol, + cs35l41_irqs[i].name, cs35l41); + if (ret) + return ret; + } } - return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, (unsigned int *)&hw_cfg->spk_pos); + return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos); } -static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, - const char *hid, int id) +static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id) { - struct cs35l41_hda_hw_config *hw_cfg; + struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg; u32 values[HDA_MAX_COMPONENTS]; struct acpi_device *adev; struct device *physdev; @@ -284,7 +310,7 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c adev = acpi_dev_get_first_match_dev(hid, NULL, -1); if (!adev) { dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid); - return ERR_PTR(-ENODEV); + return -ENODEV; } physdev = get_device(acpi_get_first_physical_node(adev)); @@ -324,56 +350,67 @@ static struct cs35l41_hda_hw_config *cs35l41_hda_read_acpi(struct cs35l41_hda *c cs35l41->reset_gpio = fwnode_gpiod_get_index(&adev->fwnode, "reset", cs35l41->index, GPIOD_OUT_LOW, "cs35l41-reset"); - hw_cfg = kzalloc(sizeof(*hw_cfg), GFP_KERNEL); - if (!hw_cfg) { - ret = -ENOMEM; - goto err; - } - property = "cirrus,speaker-position"; ret = device_property_read_u32_array(physdev, property, values, nval); if (ret) - goto err_free; + goto err; hw_cfg->spk_pos = values[cs35l41->index]; + cs35l41->channel_index = 0; + for (i = 0; i < cs35l41->index; i++) + if (values[i] == hw_cfg->spk_pos) + cs35l41->channel_index++; + property = "cirrus,gpio1-func"; ret = device_property_read_u32_array(physdev, property, values, nval); if (ret) - goto err_free; - hw_cfg->gpio1_func = values[cs35l41->index]; + goto err; + hw_cfg->gpio1.func = values[cs35l41->index]; + hw_cfg->gpio1.valid = true; property = "cirrus,gpio2-func"; ret = device_property_read_u32_array(physdev, property, values, nval); if (ret) - goto err_free; - hw_cfg->gpio2_func = values[cs35l41->index]; + goto err; + hw_cfg->gpio2.func = values[cs35l41->index]; + hw_cfg->gpio2.valid = true; property = "cirrus,boost-peak-milliamp"; ret = device_property_read_u32_array(physdev, property, values, nval); if (ret == 0) hw_cfg->bst_ipk = values[cs35l41->index]; + else + hw_cfg->bst_ipk = -1; property = "cirrus,boost-ind-nanohenry"; ret = device_property_read_u32_array(physdev, property, values, nval); if (ret == 0) hw_cfg->bst_ind = values[cs35l41->index]; + else + hw_cfg->bst_ind = -1; property = "cirrus,boost-cap-microfarad"; ret = device_property_read_u32_array(physdev, property, values, nval); if (ret == 0) hw_cfg->bst_cap = values[cs35l41->index]; + else + hw_cfg->bst_cap = -1; + if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0) + hw_cfg->bst_type = CS35L41_INT_BOOST; + else + hw_cfg->bst_type = CS35L41_EXT_BOOST; + + hw_cfg->valid = true; put_device(physdev); - return hw_cfg; + return 0; -err_free: - kfree(hw_cfg); err: put_device(physdev); dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); - return ERR_PTR(ret); + return ret; no_acpi_dsd: /* @@ -384,25 +421,32 @@ no_acpi_dsd: * fwnode. */ if (strncmp(hid, "CLSA0100", 8) != 0) - return ERR_PTR(-EINVAL); + return -EINVAL; /* check I2C address to assign the index */ cs35l41->index = id == 0x40 ? 0 : 1; + cs35l41->hw_cfg.spk_pos = cs35l41->index; + cs35l41->channel_index = 0; cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); - cs35l41->vspk_always_on = true; + cs35l41->hw_cfg.bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; + hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN; + hw_cfg->gpio2.valid = true; + cs35l41->hw_cfg.valid = true; put_device(physdev); - return NULL; + return 0; } int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq, struct regmap *regmap) { unsigned int int_sts, regid, reg_revid, mtl_revid, chipid, int_status; - struct cs35l41_hda_hw_config *acpi_hw_cfg; struct cs35l41_hda *cs35l41; int ret; + BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != ARRAY_SIZE(cs35l41_reg_irqs)); + BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != CS35L41_NUM_IRQ); + if (IS_ERR(regmap)) return PTR_ERR(regmap); @@ -415,9 +459,11 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i cs35l41->regmap = regmap; dev_set_drvdata(dev, cs35l41); - acpi_hw_cfg = cs35l41_hda_read_acpi(cs35l41, device_name, id); - if (IS_ERR(acpi_hw_cfg)) - return PTR_ERR(acpi_hw_cfg); + ret = cs35l41_hda_read_acpi(cs35l41, device_name, id); + if (ret) { + dev_err_probe(cs35l41->dev, ret, "Platform not supported %d\n", ret); + return ret; + } if (IS_ERR(cs35l41->reset_gpio)) { ret = PTR_ERR(cs35l41->reset_gpio); @@ -490,20 +536,9 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i if (ret) goto err; - ret = cs35l41_hda_apply_properties(cs35l41, acpi_hw_cfg); + ret = cs35l41_hda_apply_properties(cs35l41); if (ret) goto err; - kfree(acpi_hw_cfg); - acpi_hw_cfg = NULL; - - if (cs35l41->reg_seq->probe) { - ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41->reg_seq->probe, - cs35l41->reg_seq->num_probe); - if (ret) { - dev_err(cs35l41->dev, "Fail to apply probe reg patch: %d\n", ret); - goto err; - } - } ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops); if (ret) { @@ -516,8 +551,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i return 0; err: - kfree(acpi_hw_cfg); - if (!cs35l41->vspk_always_on) + if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); @@ -531,7 +565,7 @@ void cs35l41_hda_remove(struct device *dev) component_del(cs35l41->dev, &cs35l41_hda_comp_ops); - if (!cs35l41->vspk_always_on) + if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); } |