2187 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// ALSA SoC Texas Instruments PCM6240 Family Audio ADC/DAC Device4//5// Copyright (C) 2022 - 2024 Texas Instruments Incorporated6// https://www.ti.com7//8// The PCM6240 driver implements a flexible and configurable9// algo coefficient setting for one, two, or even multiple10// PCM6240 Family chips.11//12// Author: Shenghao Ding <shenghao-ding@ti.com>13//14 15#include <linux/unaligned.h>16#include <linux/firmware.h>17#include <linux/gpio.h>18#include <linux/i2c.h>19#include <linux/module.h>20#include <linux/of_irq.h>21#include <linux/of_address.h>22#include <linux/regmap.h>23#include <sound/pcm_params.h>24#include <sound/soc.h>25#include <sound/tlv.h>26 27#include "pcm6240.h"28 29static const struct i2c_device_id pcmdevice_i2c_id[] = {30 { "adc3120", ADC3120 },31 { "adc5120", ADC5120 },32 { "adc6120", ADC6120 },33 { "dix4192", DIX4192 },34 { "pcm1690", PCM1690 },35 { "pcm3120", PCM3120 },36 { "pcm3140", PCM3140 },37 { "pcm5120", PCM5120 },38 { "pcm5140", PCM5140 },39 { "pcm6120", PCM6120 },40 { "pcm6140", PCM6140 },41 { "pcm6240", PCM6240 },42 { "pcm6260", PCM6260 },43 { "pcm9211", PCM9211 },44 { "pcmd3140", PCMD3140 },45 { "pcmd3180", PCMD3180 },46 { "pcmd512x", PCMD512X },47 { "taa5212", TAA5212 },48 { "taa5412", TAA5412 },49 { "tad5212", TAD5212 },50 { "tad5412", TAD5412 },51 {}52};53MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id);54 55static const char *const pcmdev_ctrl_name[] = {56 "%s i2c%d Dev%d Ch%d Ana Volume",57 "%s i2c%d Dev%d Ch%d Digi Volume",58 "%s i2c%d Dev%d Ch%d Fine Volume",59};60 61static const struct pcmdevice_mixer_control adc5120_analog_gain_ctl[] = {62 {63 .shift = 1,64 .reg = ADC5120_REG_CH1_ANALOG_GAIN,65 .max = 0x54,66 .invert = 0,67 },68 {69 .shift = 1,70 .reg = ADC5120_REG_CH2_ANALOG_GAIN,71 .max = 0x54,72 .invert = 0,73 }74};75 76static const struct pcmdevice_mixer_control adc5120_digi_gain_ctl[] = {77 {78 .shift = 0,79 .reg = ADC5120_REG_CH1_DIGITAL_GAIN,80 .max = 0xff,81 .invert = 0,82 },83 {84 .shift = 0,85 .reg = ADC5120_REG_CH2_DIGITAL_GAIN,86 .max = 0xff,87 .invert = 0,88 }89};90 91static const struct pcmdevice_mixer_control pcm1690_digi_gain_ctl[] = {92 {93 .shift = 0,94 .reg = PCM1690_REG_CH1_DIGITAL_GAIN,95 .max = 0xff,96 .invert = 0,97 },98 {99 .shift = 0,100 .reg = PCM1690_REG_CH2_DIGITAL_GAIN,101 .max = 0xff,102 .invert = 0,103 },104 {105 .shift = 0,106 .reg = PCM1690_REG_CH3_DIGITAL_GAIN,107 .max = 0xff,108 .invert = 0,109 },110 {111 .shift = 0,112 .reg = PCM1690_REG_CH4_DIGITAL_GAIN,113 .max = 0xff,114 .invert = 0,115 },116 {117 .shift = 0,118 .reg = PCM1690_REG_CH5_DIGITAL_GAIN,119 .max = 0xff,120 .invert = 0,121 },122 {123 .shift = 0,124 .reg = PCM1690_REG_CH6_DIGITAL_GAIN,125 .max = 0xff,126 .invert = 0,127 },128 {129 .shift = 0,130 .reg = PCM1690_REG_CH7_DIGITAL_GAIN,131 .max = 0xff,132 .invert = 0,133 },134 {135 .shift = 0,136 .reg = PCM1690_REG_CH8_DIGITAL_GAIN,137 .max = 0xff,138 .invert = 0,139 }140};141 142static const struct pcmdevice_mixer_control pcm6240_analog_gain_ctl[] = {143 {144 .shift = 2,145 .reg = PCM6240_REG_CH1_ANALOG_GAIN,146 .max = 0x42,147 .invert = 0,148 },149 {150 .shift = 2,151 .reg = PCM6240_REG_CH2_ANALOG_GAIN,152 .max = 0x42,153 .invert = 0,154 },155 {156 .shift = 2,157 .reg = PCM6240_REG_CH3_ANALOG_GAIN,158 .max = 0x42,159 .invert = 0,160 },161 {162 .shift = 2,163 .reg = PCM6240_REG_CH4_ANALOG_GAIN,164 .max = 0x42,165 .invert = 0,166 }167};168 169static const struct pcmdevice_mixer_control pcm6240_digi_gain_ctl[] = {170 {171 .shift = 0,172 .reg = PCM6240_REG_CH1_DIGITAL_GAIN,173 .max = 0xff,174 .invert = 0,175 },176 {177 .shift = 0,178 .reg = PCM6240_REG_CH2_DIGITAL_GAIN,179 .max = 0xff,180 .invert = 0,181 },182 {183 .shift = 0,184 .reg = PCM6240_REG_CH3_DIGITAL_GAIN,185 .max = 0xff,186 .invert = 0,187 },188 {189 .shift = 0,190 .reg = PCM6240_REG_CH4_DIGITAL_GAIN,191 .max = 0xff,192 .invert = 0,193 }194};195 196static const struct pcmdevice_mixer_control pcm6260_analog_gain_ctl[] = {197 {198 .shift = 2,199 .reg = PCM6260_REG_CH1_ANALOG_GAIN,200 .max = 0x42,201 .invert = 0,202 },203 {204 .shift = 2,205 .reg = PCM6260_REG_CH2_ANALOG_GAIN,206 .max = 0x42,207 .invert = 0,208 },209 {210 .shift = 2,211 .reg = PCM6260_REG_CH3_ANALOG_GAIN,212 .max = 0x42,213 .invert = 0,214 },215 {216 .shift = 2,217 .reg = PCM6260_REG_CH4_ANALOG_GAIN,218 .max = 0x42,219 .invert = 0,220 },221 {222 .shift = 2,223 .reg = PCM6260_REG_CH5_ANALOG_GAIN,224 .max = 0x42,225 .invert = 0,226 },227 {228 .shift = 2,229 .reg = PCM6260_REG_CH6_ANALOG_GAIN,230 .max = 0x42,231 .invert = 0,232 }233};234 235static const struct pcmdevice_mixer_control pcm6260_digi_gain_ctl[] = {236 {237 .shift = 0,238 .reg = PCM6260_REG_CH1_DIGITAL_GAIN,239 .max = 0xff,240 .invert = 0,241 },242 {243 .shift = 0,244 .reg = PCM6260_REG_CH2_DIGITAL_GAIN,245 .max = 0xff,246 .invert = 0,247 },248 {249 .shift = 0,250 .reg = PCM6260_REG_CH3_DIGITAL_GAIN,251 .max = 0xff,252 .invert = 0,253 },254 {255 .shift = 0,256 .reg = PCM6260_REG_CH4_DIGITAL_GAIN,257 .max = 0xff,258 .invert = 0,259 },260 {261 .shift = 0,262 .reg = PCM6260_REG_CH5_DIGITAL_GAIN,263 .max = 0xff,264 .invert = 0,265 },266 {267 .shift = 0,268 .reg = PCM6260_REG_CH6_DIGITAL_GAIN,269 .max = 0xff,270 .invert = 0,271 }272};273 274static const struct pcmdevice_mixer_control pcm9211_digi_gain_ctl[] = {275 {276 .shift = 0,277 .reg = PCM9211_REG_CH1_DIGITAL_GAIN,278 .max = 0xff,279 .invert = 0,280 },281 {282 .shift = 0,283 .reg = PCM9211_REG_CH2_DIGITAL_GAIN,284 .max = 0xff,285 .invert = 0,286 }287};288 289static const struct pcmdevice_mixer_control pcmd3140_digi_gain_ctl[] = {290 {291 .shift = 0,292 .reg = PCMD3140_REG_CH1_DIGITAL_GAIN,293 .max = 0xff,294 .invert = 0,295 },296 {297 .shift = 0,298 .reg = PCMD3140_REG_CH2_DIGITAL_GAIN,299 .max = 0xff,300 .invert = 0,301 },302 {303 .shift = 0,304 .reg = PCMD3140_REG_CH3_DIGITAL_GAIN,305 .max = 0xff,306 .invert = 0,307 },308 {309 .shift = 0,310 .reg = PCMD3140_REG_CH4_DIGITAL_GAIN,311 .max = 0xff,312 .invert = 0,313 }314};315 316static const struct pcmdevice_mixer_control pcmd3140_fine_gain_ctl[] = {317 {318 .shift = 4,319 .reg = PCMD3140_REG_CH1_FINE_GAIN,320 .max = 0xf,321 .invert = 0,322 },323 {324 .shift = 4,325 .reg = PCMD3140_REG_CH2_FINE_GAIN,326 .max = 0xf,327 .invert = 0,328 },329 {330 .shift = 4,331 .reg = PCMD3140_REG_CH3_FINE_GAIN,332 .max = 0xf,333 .invert = 0,334 },335 {336 .shift = 4,337 .reg = PCMD3140_REG_CH4_FINE_GAIN,338 .max = 0xf,339 .invert = 0,340 }341};342 343static const struct pcmdevice_mixer_control pcmd3180_digi_gain_ctl[] = {344 {345 .shift = 0,346 .reg = PCMD3180_REG_CH1_DIGITAL_GAIN,347 .max = 0xff,348 .invert = 0,349 },350 {351 .shift = 0,352 .reg = PCMD3180_REG_CH2_DIGITAL_GAIN,353 .max = 0xff,354 .invert = 0,355 },356 {357 .shift = 0,358 .reg = PCMD3180_REG_CH3_DIGITAL_GAIN,359 .max = 0xff,360 .invert = 0,361 },362 {363 .shift = 0,364 .reg = PCMD3180_REG_CH4_DIGITAL_GAIN,365 .max = 0xff,366 .invert = 0,367 },368 {369 .shift = 0,370 .reg = PCMD3180_REG_CH5_DIGITAL_GAIN,371 .max = 0xff,372 .invert = 0,373 },374 {375 .shift = 0,376 .reg = PCMD3180_REG_CH6_DIGITAL_GAIN,377 .max = 0xff,378 .invert = 0,379 },380 {381 .shift = 0,382 .reg = PCMD3180_REG_CH7_DIGITAL_GAIN,383 .max = 0xff,384 .invert = 0,385 },386 {387 .shift = 0,388 .reg = PCMD3180_REG_CH8_DIGITAL_GAIN,389 .max = 0xff,390 .invert = 0,391 }392};393 394static const struct pcmdevice_mixer_control pcmd3180_fine_gain_ctl[] = {395 {396 .shift = 4,397 .reg = PCMD3180_REG_CH1_FINE_GAIN,398 .max = 0xf,399 .invert = 0,400 },401 {402 .shift = 4,403 .reg = PCMD3180_REG_CH2_FINE_GAIN,404 .max = 0xf,405 .invert = 0,406 },407 {408 .shift = 4,409 .reg = PCMD3180_REG_CH3_FINE_GAIN,410 .max = 0xf,411 .invert = 0,412 },413 {414 .shift = 4,415 .reg = PCMD3180_REG_CH4_FINE_GAIN,416 .max = 0xf,417 .invert = 0,418 },419 {420 .shift = 4,421 .reg = PCMD3180_REG_CH5_FINE_GAIN,422 .max = 0xf,423 .invert = 0,424 },425 {426 .shift = 4,427 .reg = PCMD3180_REG_CH6_FINE_GAIN,428 .max = 0xf,429 .invert = 0,430 },431 {432 .shift = 4,433 .reg = PCMD3180_REG_CH7_FINE_GAIN,434 .max = 0xf,435 .invert = 0,436 },437 {438 .shift = 4,439 .reg = PCMD3180_REG_CH8_FINE_GAIN,440 .max = 0xf,441 .invert = 0,442 }443};444 445static const struct pcmdevice_mixer_control taa5412_digi_vol_ctl[] = {446 {447 .shift = 0,448 .reg = TAA5412_REG_CH1_DIGITAL_VOLUME,449 .max = 0xff,450 .invert = 0,451 },452 {453 .shift = 0,454 .reg = TAA5412_REG_CH2_DIGITAL_VOLUME,455 .max = 0xff,456 .invert = 0,457 },458 {459 .shift = 0,460 .reg = TAA5412_REG_CH3_DIGITAL_VOLUME,461 .max = 0xff,462 .invert = 0,463 },464 {465 .shift = 0,466 .reg = TAA5412_REG_CH4_DIGITAL_VOLUME,467 .max = 0xff,468 .invert = 0,469 }470};471 472static const struct pcmdevice_mixer_control taa5412_fine_gain_ctl[] = {473 {474 .shift = 4,475 .reg = TAA5412_REG_CH1_FINE_GAIN,476 .max = 0xf,477 .invert = 0,478 },479 {480 .shift = 4,481 .reg = TAA5412_REG_CH2_FINE_GAIN,482 .max = 0xf,483 .invert = 0,484 },485 {486 .shift = 4,487 .reg = TAA5412_REG_CH3_FINE_GAIN,488 .max = 0xf,489 .invert = 4,490 },491 {492 .shift = 0,493 .reg = TAA5412_REG_CH4_FINE_GAIN,494 .max = 0xf,495 .invert = 4,496 }497};498 499static const DECLARE_TLV_DB_MINMAX_MUTE(pcmd3140_dig_gain_tlv,500 -10000, 2700);501static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_fine_dig_gain_tlv,502 -12750, 0);503static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_dig_gain_tlv,504 -25500, 0);505static const DECLARE_TLV_DB_MINMAX_MUTE(pcm9211_dig_gain_tlv,506 -11450, 2000);507static const DECLARE_TLV_DB_MINMAX_MUTE(adc5120_fgain_tlv,508 -10050, 2700);509static const DECLARE_TLV_DB_LINEAR(adc5120_chgain_tlv, 0, 4200);510static const DECLARE_TLV_DB_MINMAX_MUTE(pcm6260_fgain_tlv,511 -10000, 2700);512static const DECLARE_TLV_DB_LINEAR(pcm6260_chgain_tlv, 0, 4200);513static const DECLARE_TLV_DB_MINMAX_MUTE(taa5412_dig_vol_tlv,514 -8050, 4700);515static const DECLARE_TLV_DB_LINEAR(taa5412_fine_gain_tlv,516 -80, 70);517 518static int pcmdev_change_dev(struct pcmdevice_priv *pcm_priv,519 unsigned short dev_no)520{521 struct i2c_client *client = (struct i2c_client *)pcm_priv->client;522 struct regmap *map = pcm_priv->regmap;523 int ret;524 525 if (client->addr == pcm_priv->addr[dev_no])526 return 0;527 528 client->addr = pcm_priv->addr[dev_no];529 /* All pcmdevices share the same regmap, clear the page530 * inside regmap once switching to another pcmdevice.531 * Register 0 at any pages inside pcmdevice is the same532 * one for page-switching.533 */534 ret = regmap_write(map, PCMDEVICE_PAGE_SELECT, 0);535 if (ret < 0)536 dev_err(pcm_priv->dev, "%s: err = %d\n", __func__, ret);537 538 return ret;539}540 541static int pcmdev_dev_read(struct pcmdevice_priv *pcm_dev,542 unsigned int dev_no, unsigned int reg, unsigned int *val)543{544 struct regmap *map = pcm_dev->regmap;545 int ret;546 547 if (dev_no >= pcm_dev->ndev) {548 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,549 dev_no);550 return -EINVAL;551 }552 553 ret = pcmdev_change_dev(pcm_dev, dev_no);554 if (ret < 0) {555 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);556 return ret;557 }558 559 ret = regmap_read(map, reg, val);560 if (ret < 0)561 dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret);562 563 return ret;564}565 566static int pcmdev_dev_update_bits(struct pcmdevice_priv *pcm_dev,567 unsigned int dev_no, unsigned int reg, unsigned int mask,568 unsigned int value)569{570 struct regmap *map = pcm_dev->regmap;571 int ret;572 573 if (dev_no >= pcm_dev->ndev) {574 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,575 dev_no);576 return -EINVAL;577 }578 579 ret = pcmdev_change_dev(pcm_dev, dev_no);580 if (ret < 0) {581 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);582 return ret;583 }584 585 ret = regmap_update_bits(map, reg, mask, value);586 if (ret < 0)587 dev_err(pcm_dev->dev, "%s: update_bits err=%d\n",588 __func__, ret);589 590 return ret;591}592 593static int pcmdev_get_volsw(struct snd_kcontrol *kcontrol,594 struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type)595{596 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);597 struct pcmdevice_priv *pcm_dev =598 snd_soc_component_get_drvdata(component);599 struct pcmdevice_mixer_control *mc =600 (struct pcmdevice_mixer_control *)kcontrol->private_value;601 int max = mc->max, ret;602 unsigned int mask = BIT(fls(max)) - 1;603 unsigned int dev_no = mc->dev_no;604 unsigned int shift = mc->shift;605 unsigned int reg = mc->reg;606 unsigned int val;607 608 mutex_lock(&pcm_dev->codec_lock);609 610 if (pcm_dev->chip_id == PCM1690) {611 ret = pcmdev_dev_read(pcm_dev, dev_no, PCM1690_REG_MODE_CTRL,612 &val);613 if (ret) {614 dev_err(pcm_dev->dev, "%s: read mode err=%d\n",615 __func__, ret);616 goto out;617 }618 val &= PCM1690_REG_MODE_CTRL_DAMS_MSK;619 /* Set to wide-range mode, before using vol ctrl. */620 if (!val && vol_ctrl_type == PCMDEV_PCM1690_VOL_CTRL) {621 ucontrol->value.integer.value[0] = -25500;622 goto out;623 }624 /* Set to fine mode, before using fine vol ctrl. */625 if (val && vol_ctrl_type == PCMDEV_PCM1690_FINE_VOL_CTRL) {626 ucontrol->value.integer.value[0] = -12750;627 goto out;628 }629 }630 631 ret = pcmdev_dev_read(pcm_dev, dev_no, reg, &val);632 if (ret) {633 dev_err(pcm_dev->dev, "%s: read err=%d\n",634 __func__, ret);635 goto out;636 }637 638 val = (val >> shift) & mask;639 val = (val > max) ? max : val;640 val = mc->invert ? max - val : val;641 ucontrol->value.integer.value[0] = val;642out:643 mutex_unlock(&pcm_dev->codec_lock);644 return ret;645}646 647static int pcmdevice_get_volsw(struct snd_kcontrol *kcontrol,648 struct snd_ctl_elem_value *ucontrol)649{650 return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL);651}652 653static int pcm1690_get_volsw(struct snd_kcontrol *kcontrol,654 struct snd_ctl_elem_value *ucontrol)655{656 return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL);657}658 659static int pcm1690_get_finevolsw(struct snd_kcontrol *kcontrol,660 struct snd_ctl_elem_value *ucontrol)661{662 return pcmdev_get_volsw(kcontrol, ucontrol,663 PCMDEV_PCM1690_FINE_VOL_CTRL);664}665 666static int pcmdev_put_volsw(struct snd_kcontrol *kcontrol,667 struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type)668{669 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);670 struct pcmdevice_priv *pcm_dev =671 snd_soc_component_get_drvdata(component);672 struct pcmdevice_mixer_control *mc =673 (struct pcmdevice_mixer_control *)kcontrol->private_value;674 int max = mc->max, rc;675 unsigned int mask = BIT(fls(max)) - 1;676 unsigned int dev_no = mc->dev_no;677 unsigned int shift = mc->shift;678 unsigned int val, val_mask;679 unsigned int reg = mc->reg;680 681 mutex_lock(&pcm_dev->codec_lock);682 val = ucontrol->value.integer.value[0] & mask;683 val = (val > max) ? max : val;684 val = mc->invert ? max - val : val;685 val_mask = mask << shift;686 val = val << shift;687 688 switch (vol_ctrl_type) {689 case PCMDEV_PCM1690_VOL_CTRL:690 val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK;691 val |= PCM1690_REG_MODE_CTRL_DAMS_WIDE_RANGE;692 break;693 case PCMDEV_PCM1690_FINE_VOL_CTRL:694 val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK;695 val |= PCM1690_REG_MODE_CTRL_DAMS_FINE_STEP;696 break;697 }698 699 rc = pcmdev_dev_update_bits(pcm_dev, dev_no, reg, val_mask, val);700 if (rc < 0)701 dev_err(pcm_dev->dev, "%s: update_bits err = %d\n",702 __func__, rc);703 else704 rc = 1;705 mutex_unlock(&pcm_dev->codec_lock);706 return rc;707}708 709static int pcmdevice_put_volsw(struct snd_kcontrol *kcontrol,710 struct snd_ctl_elem_value *ucontrol)711{712 return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL);713}714 715static int pcm1690_put_volsw(struct snd_kcontrol *kcontrol,716 struct snd_ctl_elem_value *ucontrol)717{718 return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL);719}720 721static int pcm1690_put_finevolsw(struct snd_kcontrol *kcontrol,722 struct snd_ctl_elem_value *ucontrol)723{724 return pcmdev_put_volsw(kcontrol, ucontrol,725 PCMDEV_PCM1690_FINE_VOL_CTRL);726}727 728static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = {729 // ADC3120730 {731 {732 .gain = adc5120_chgain_tlv,733 .pcmdev_ctrl = adc5120_analog_gain_ctl,734 .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),735 .get = pcmdevice_get_volsw,736 .put = pcmdevice_put_volsw,737 .pcmdev_ctrl_name_id = 0,738 },739 {740 .gain = adc5120_fgain_tlv,741 .pcmdev_ctrl = adc5120_digi_gain_ctl,742 .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),743 .get = pcmdevice_get_volsw,744 .put = pcmdevice_put_volsw,745 .pcmdev_ctrl_name_id = 1,746 },747 },748 // ADC5120749 {750 {751 .gain = adc5120_chgain_tlv,752 .pcmdev_ctrl = adc5120_analog_gain_ctl,753 .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),754 .get = pcmdevice_get_volsw,755 .put = pcmdevice_put_volsw,756 .pcmdev_ctrl_name_id = 0,757 },758 {759 .gain = adc5120_fgain_tlv,760 .pcmdev_ctrl = adc5120_digi_gain_ctl,761 .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),762 .get = pcmdevice_get_volsw,763 .put = pcmdevice_put_volsw,764 .pcmdev_ctrl_name_id = 1,765 },766 },767 // ADC6120768 {769 {770 .gain = adc5120_chgain_tlv,771 .pcmdev_ctrl = adc5120_analog_gain_ctl,772 .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),773 .get = pcmdevice_get_volsw,774 .put = pcmdevice_put_volsw,775 .pcmdev_ctrl_name_id = 0,776 },777 {778 .gain = adc5120_fgain_tlv,779 .pcmdev_ctrl = adc5120_digi_gain_ctl,780 .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),781 .get = pcmdevice_get_volsw,782 .put = pcmdevice_put_volsw,783 .pcmdev_ctrl_name_id = 1,784 },785 },786 // DIX4192787 {788 {789 .ctrl_array_size = 0,790 },791 {792 .ctrl_array_size = 0,793 },794 },795 // PCM1690796 {797 {798 .gain = pcm1690_fine_dig_gain_tlv,799 .pcmdev_ctrl = pcm1690_digi_gain_ctl,800 .ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl),801 .get = pcm1690_get_volsw,802 .put = pcm1690_put_volsw,803 .pcmdev_ctrl_name_id = 1,804 },805 {806 .gain = pcm1690_dig_gain_tlv,807 .pcmdev_ctrl = pcm1690_digi_gain_ctl,808 .ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl),809 .get = pcm1690_get_finevolsw,810 .put = pcm1690_put_finevolsw,811 .pcmdev_ctrl_name_id = 2,812 },813 },814 // PCM3120815 {816 {817 .gain = adc5120_chgain_tlv,818 .pcmdev_ctrl = adc5120_analog_gain_ctl,819 .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),820 .get = pcmdevice_get_volsw,821 .put = pcmdevice_put_volsw,822 .pcmdev_ctrl_name_id = 0,823 },824 {825 .gain = adc5120_fgain_tlv,826 .pcmdev_ctrl = adc5120_digi_gain_ctl,827 .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),828 .get = pcmdevice_get_volsw,829 .put = pcmdevice_put_volsw,830 .pcmdev_ctrl_name_id = 1,831 },832 },833 // PCM3140834 {835 {836 .gain = pcm6260_chgain_tlv,837 .pcmdev_ctrl = pcm6240_analog_gain_ctl,838 .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),839 .get = pcmdevice_get_volsw,840 .put = pcmdevice_put_volsw,841 .pcmdev_ctrl_name_id = 0,842 },843 {844 .gain = pcm6260_fgain_tlv,845 .pcmdev_ctrl = pcm6240_digi_gain_ctl,846 .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),847 .get = pcmdevice_get_volsw,848 .put = pcmdevice_put_volsw,849 .pcmdev_ctrl_name_id = 1,850 },851 },852 // PCM5120853 {854 {855 .gain = adc5120_chgain_tlv,856 .pcmdev_ctrl = adc5120_analog_gain_ctl,857 .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),858 .get = pcmdevice_get_volsw,859 .put = pcmdevice_put_volsw,860 .pcmdev_ctrl_name_id = 0,861 },862 {863 .gain = adc5120_fgain_tlv,864 .pcmdev_ctrl = adc5120_digi_gain_ctl,865 .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),866 .get = pcmdevice_get_volsw,867 .put = pcmdevice_put_volsw,868 .pcmdev_ctrl_name_id = 1,869 },870 },871 // PCM5140872 {873 {874 .gain = pcm6260_chgain_tlv,875 .pcmdev_ctrl = pcm6240_analog_gain_ctl,876 .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),877 .get = pcmdevice_get_volsw,878 .put = pcmdevice_put_volsw,879 .pcmdev_ctrl_name_id = 0,880 },881 {882 .gain = pcm6260_fgain_tlv,883 .pcmdev_ctrl = pcm6240_digi_gain_ctl,884 .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),885 .get = pcmdevice_get_volsw,886 .put = pcmdevice_put_volsw,887 .pcmdev_ctrl_name_id = 1,888 },889 },890 // PCM6120891 {892 {893 .gain = adc5120_chgain_tlv,894 .pcmdev_ctrl = adc5120_analog_gain_ctl,895 .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl),896 .get = pcmdevice_get_volsw,897 .put = pcmdevice_put_volsw,898 .pcmdev_ctrl_name_id = 0,899 },900 {901 .gain = adc5120_fgain_tlv,902 .pcmdev_ctrl = adc5120_digi_gain_ctl,903 .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl),904 .get = pcmdevice_get_volsw,905 .put = pcmdevice_put_volsw,906 .pcmdev_ctrl_name_id = 1,907 },908 },909 // PCM6140910 {911 {912 .gain = pcm6260_chgain_tlv,913 .pcmdev_ctrl = pcm6240_analog_gain_ctl,914 .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),915 .get = pcmdevice_get_volsw,916 .put = pcmdevice_put_volsw,917 .pcmdev_ctrl_name_id = 0,918 },919 {920 .gain = pcm6260_fgain_tlv,921 .pcmdev_ctrl = pcm6240_digi_gain_ctl,922 .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),923 .get = pcmdevice_get_volsw,924 .put = pcmdevice_put_volsw,925 .pcmdev_ctrl_name_id = 1,926 },927 },928 // PCM6240929 {930 {931 .gain = pcm6260_chgain_tlv,932 .pcmdev_ctrl = pcm6240_analog_gain_ctl,933 .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl),934 .get = pcmdevice_get_volsw,935 .put = pcmdevice_put_volsw,936 .pcmdev_ctrl_name_id = 0,937 },938 {939 .gain = pcm6260_fgain_tlv,940 .pcmdev_ctrl = pcm6240_digi_gain_ctl,941 .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl),942 .get = pcmdevice_get_volsw,943 .put = pcmdevice_put_volsw,944 .pcmdev_ctrl_name_id = 1,945 },946 },947 // PCM6260948 {949 {950 .gain = pcm6260_chgain_tlv,951 .pcmdev_ctrl = pcm6260_analog_gain_ctl,952 .ctrl_array_size = ARRAY_SIZE(pcm6260_analog_gain_ctl),953 .get = pcmdevice_get_volsw,954 .put = pcmdevice_put_volsw,955 .pcmdev_ctrl_name_id = 0,956 },957 {958 .gain = pcm6260_fgain_tlv,959 .pcmdev_ctrl = pcm6260_digi_gain_ctl,960 .ctrl_array_size = ARRAY_SIZE(pcm6260_digi_gain_ctl),961 .get = pcmdevice_get_volsw,962 .put = pcmdevice_put_volsw,963 .pcmdev_ctrl_name_id = 1,964 },965 },966 // PCM9211967 {968 {969 .ctrl_array_size = 0,970 },971 {972 .gain = pcm9211_dig_gain_tlv,973 .pcmdev_ctrl = pcm9211_digi_gain_ctl,974 .ctrl_array_size = ARRAY_SIZE(pcm9211_digi_gain_ctl),975 .get = pcmdevice_get_volsw,976 .put = pcmdevice_put_volsw,977 .pcmdev_ctrl_name_id = 1,978 },979 980 },981 // PCMD3140982 {983 {984 .gain = taa5412_fine_gain_tlv,985 .pcmdev_ctrl = pcmd3140_fine_gain_ctl,986 .ctrl_array_size = ARRAY_SIZE(pcmd3140_fine_gain_ctl),987 .get = pcmdevice_get_volsw,988 .put = pcmdevice_put_volsw,989 .pcmdev_ctrl_name_id = 2,990 },991 {992 .gain = pcmd3140_dig_gain_tlv,993 .pcmdev_ctrl = pcmd3140_digi_gain_ctl,994 .ctrl_array_size = ARRAY_SIZE(pcmd3140_digi_gain_ctl),995 .get = pcmdevice_get_volsw,996 .put = pcmdevice_put_volsw,997 .pcmdev_ctrl_name_id = 1,998 },999 },1000 // PCMD31801001 {1002 {1003 .gain = taa5412_fine_gain_tlv,1004 .pcmdev_ctrl = pcmd3180_fine_gain_ctl,1005 .ctrl_array_size = ARRAY_SIZE(pcmd3180_fine_gain_ctl),1006 .get = pcmdevice_get_volsw,1007 .put = pcmdevice_put_volsw,1008 .pcmdev_ctrl_name_id = 2,1009 },1010 {1011 .gain = pcmd3140_dig_gain_tlv,1012 .pcmdev_ctrl = pcmd3180_digi_gain_ctl,1013 .ctrl_array_size = ARRAY_SIZE(pcmd3180_digi_gain_ctl),1014 .get = pcmdevice_get_volsw,1015 .put = pcmdevice_put_volsw,1016 .pcmdev_ctrl_name_id = 1,1017 },1018 },1019 // PCMD512X1020 {1021 {1022 .ctrl_array_size = 0,1023 },1024 {1025 .ctrl_array_size = 0,1026 },1027 },1028 // TAA52121029 {1030 {1031 .gain = taa5412_fine_gain_tlv,1032 .pcmdev_ctrl = taa5412_fine_gain_ctl,1033 .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl),1034 .get = pcmdevice_get_volsw,1035 .put = pcmdevice_put_volsw,1036 .pcmdev_ctrl_name_id = 2,1037 },1038 {1039 .gain = taa5412_dig_vol_tlv,1040 .pcmdev_ctrl = taa5412_digi_vol_ctl,1041 .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl),1042 .get = pcmdevice_get_volsw,1043 .put = pcmdevice_put_volsw,1044 .pcmdev_ctrl_name_id = 1,1045 },1046 },1047 // TAA54121048 {1049 {1050 .gain = taa5412_fine_gain_tlv,1051 .pcmdev_ctrl = taa5412_fine_gain_ctl,1052 .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl),1053 .get = pcmdevice_get_volsw,1054 .put = pcmdevice_put_volsw,1055 .pcmdev_ctrl_name_id = 2,1056 },1057 {1058 .gain = taa5412_dig_vol_tlv,1059 .pcmdev_ctrl = taa5412_digi_vol_ctl,1060 .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl),1061 .get = pcmdevice_get_volsw,1062 .put = pcmdevice_put_volsw,1063 .pcmdev_ctrl_name_id = 1,1064 },1065 },1066 // TAD52121067 {1068 {1069 .ctrl_array_size = 0,1070 },1071 {1072 .ctrl_array_size = 0,1073 },1074 },1075 // TAD54121076 {1077 {1078 .ctrl_array_size = 0,1079 },1080 {1081 .ctrl_array_size = 0,1082 },1083 },1084};1085 1086static int pcmdev_dev_bulk_write(struct pcmdevice_priv *pcm_dev,1087 unsigned int dev_no, unsigned int reg, unsigned char *data,1088 unsigned int len)1089{1090 struct regmap *map = pcm_dev->regmap;1091 int ret;1092 1093 if (dev_no >= pcm_dev->ndev) {1094 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,1095 dev_no);1096 return -EINVAL;1097 }1098 1099 ret = pcmdev_change_dev(pcm_dev, dev_no);1100 if (ret < 0) {1101 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);1102 return ret;1103 }1104 1105 ret = regmap_bulk_write(map, reg, data, len);1106 if (ret < 0)1107 dev_err(pcm_dev->dev, "%s: bulk_write err = %d\n", __func__,1108 ret);1109 1110 return ret;1111}1112 1113static int pcmdev_dev_write(struct pcmdevice_priv *pcm_dev,1114 unsigned int dev_no, unsigned int reg, unsigned int value)1115{1116 struct regmap *map = pcm_dev->regmap;1117 int ret;1118 1119 if (dev_no >= pcm_dev->ndev) {1120 dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__,1121 dev_no);1122 return -EINVAL;1123 }1124 1125 ret = pcmdev_change_dev(pcm_dev, dev_no);1126 if (ret < 0) {1127 dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret);1128 return ret;1129 }1130 1131 ret = regmap_write(map, reg, value);1132 if (ret < 0)1133 dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret);1134 1135 return ret;1136}1137 1138static int pcmdevice_info_profile(1139 struct snd_kcontrol *kcontrol,1140 struct snd_ctl_elem_info *uinfo)1141{1142 struct snd_soc_component *codec1143 = snd_soc_kcontrol_component(kcontrol);1144 struct pcmdevice_priv *pcm_dev =1145 snd_soc_component_get_drvdata(codec);1146 1147 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1148 uinfo->count = 1;1149 uinfo->value.integer.min = 0;1150 uinfo->value.integer.max = max(0, pcm_dev->regbin.ncfgs - 1);1151 1152 return 0;1153}1154 1155static int pcmdevice_get_profile_id(1156 struct snd_kcontrol *kcontrol,1157 struct snd_ctl_elem_value *ucontrol)1158{1159 struct snd_soc_component *codec1160 = snd_soc_kcontrol_component(kcontrol);1161 struct pcmdevice_priv *pcm_dev =1162 snd_soc_component_get_drvdata(codec);1163 1164 ucontrol->value.integer.value[0] = pcm_dev->cur_conf;1165 1166 return 0;1167}1168 1169static int pcmdevice_set_profile_id(1170 struct snd_kcontrol *kcontrol,1171 struct snd_ctl_elem_value *ucontrol)1172{1173 struct snd_soc_component *codec1174 = snd_soc_kcontrol_component(kcontrol);1175 struct pcmdevice_priv *pcm_dev =1176 snd_soc_component_get_drvdata(codec);1177 int nr_profile = ucontrol->value.integer.value[0];1178 int max = pcm_dev->regbin.ncfgs - 1;1179 int ret = 0;1180 1181 nr_profile = clamp(nr_profile, 0, max);1182 1183 if (pcm_dev->cur_conf != nr_profile) {1184 pcm_dev->cur_conf = nr_profile;1185 ret = 1;1186 }1187 1188 return ret;1189}1190 1191static int pcmdevice_info_volsw(struct snd_kcontrol *kcontrol,1192 struct snd_ctl_elem_info *uinfo)1193{1194 struct pcmdevice_mixer_control *mc =1195 (struct pcmdevice_mixer_control *)kcontrol->private_value;1196 1197 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;1198 uinfo->count = 1;1199 uinfo->value.integer.min = 0;1200 uinfo->value.integer.max = mc->max;1201 return 0;1202}1203 1204static void pcm9211_sw_rst(struct pcmdevice_priv *pcm_dev)1205{1206 int ret, i;1207 1208 for (i = 0; i < pcm_dev->ndev; i++) {1209 ret = pcmdev_dev_update_bits(pcm_dev, i,1210 PCM9211_REG_SW_CTRL, PCM9211_REG_SW_CTRL_MRST_MSK,1211 PCM9211_REG_SW_CTRL_MRST);1212 if (ret < 0)1213 dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n",1214 __func__, i, ret);1215 }1216}1217 1218static void pcmdevice_sw_rst(struct pcmdevice_priv *pcm_dev)1219{1220 int ret, i;1221 1222 for (i = 0; i < pcm_dev->ndev; i++) {1223 ret = pcmdev_dev_write(pcm_dev, i, PCMDEVICE_REG_SWRESET,1224 PCMDEVICE_REG_SWRESET_RESET);1225 if (ret < 0)1226 dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n",1227 __func__, i, ret);1228 }1229}1230 1231static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt,1232 const unsigned char *config_data, unsigned int config_size,1233 int *status)1234{1235 struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;1236 struct pcmdevice_config_info *cfg_info;1237 struct pcmdevice_block_data **bk_da;1238 unsigned int config_offset = 0, i;1239 1240 cfg_info = kzalloc(sizeof(struct pcmdevice_config_info), GFP_KERNEL);1241 if (!cfg_info) {1242 *status = -ENOMEM;1243 goto out;1244 }1245 1246 if (pcm_dev->regbin.fw_hdr.binary_version_num >= 0x105) {1247 if (config_offset + 64 > (int)config_size) {1248 *status = -EINVAL;1249 dev_err(pcm_dev->dev,1250 "%s: cfg_name out of boundary\n", __func__);1251 goto out;1252 }1253 memcpy(cfg_info->cfg_name, &config_data[config_offset], 64);1254 config_offset += 64;1255 }1256 1257 if (config_offset + 4 > config_size) {1258 *status = -EINVAL;1259 dev_err(pcm_dev->dev, "%s: nblocks out of boundary\n",1260 __func__);1261 goto out;1262 }1263 cfg_info->nblocks =1264 get_unaligned_be32(&config_data[config_offset]);1265 config_offset += 4;1266 1267 bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks,1268 sizeof(struct pcmdevice_block_data *), GFP_KERNEL);1269 if (!bk_da) {1270 *status = -ENOMEM;1271 goto out;1272 }1273 cfg_info->real_nblocks = 0;1274 for (i = 0; i < cfg_info->nblocks; i++) {1275 if (config_offset + 12 > config_size) {1276 *status = -EINVAL;1277 dev_err(pcm_dev->dev,1278 "%s: out of boundary i = %d nblocks = %u\n",1279 __func__, i, cfg_info->nblocks);1280 break;1281 }1282 bk_da[i] = kzalloc(sizeof(struct pcmdevice_block_data),1283 GFP_KERNEL);1284 if (!bk_da[i]) {1285 *status = -ENOMEM;1286 break;1287 }1288 bk_da[i]->dev_idx = config_data[config_offset];1289 config_offset++;1290 1291 bk_da[i]->block_type = config_data[config_offset];1292 config_offset++;1293 1294 if (bk_da[i]->block_type == PCMDEVICE_BIN_BLK_PRE_POWER_UP) {1295 if (bk_da[i]->dev_idx == 0)1296 cfg_info->active_dev =1297 (1 << pcm_dev->ndev) - 1;1298 else1299 cfg_info->active_dev =1300 1 << (bk_da[i]->dev_idx - 1);1301 }1302 1303 bk_da[i]->yram_checksum =1304 get_unaligned_be16(&config_data[config_offset]);1305 config_offset += 2;1306 bk_da[i]->block_size =1307 get_unaligned_be32(&config_data[config_offset]);1308 config_offset += 4;1309 1310 bk_da[i]->n_subblks =1311 get_unaligned_be32(&config_data[config_offset]);1312 1313 config_offset += 4;1314 1315 if (config_offset + bk_da[i]->block_size > config_size) {1316 *status = -EINVAL;1317 dev_err(pcm_dev->dev,1318 "%s: out of boundary: i = %d blks = %u\n",1319 __func__, i, cfg_info->nblocks);1320 break;1321 }1322 1323 bk_da[i]->regdata = kmemdup(&config_data[config_offset],1324 bk_da[i]->block_size, GFP_KERNEL);1325 if (!bk_da[i]->regdata) {1326 *status = -ENOMEM;1327 goto out;1328 }1329 config_offset += bk_da[i]->block_size;1330 cfg_info->real_nblocks += 1;1331 }1332out:1333 return cfg_info;1334}1335 1336static int pcmdev_gain_ctrl_add(struct pcmdevice_priv *pcm_dev,1337 int dev_no, int ctl_id)1338{1339 struct i2c_adapter *adap = pcm_dev->client->adapter;1340 struct snd_soc_component *comp = pcm_dev->component;1341 struct pcmdevice_mixer_control *pcmdev_ctrl;1342 struct snd_kcontrol_new *pcmdev_controls;1343 int ret, mix_index = 0, name_id, chn;1344 unsigned int id = pcm_dev->chip_id;1345 const int nr_chn =1346 pcmdev_gain_ctl_info[id][ctl_id].ctrl_array_size;1347 const char *ctrl_name;1348 char *name;1349 1350 if (!nr_chn) {1351 dev_dbg(pcm_dev->dev, "%s: no gain ctrl for %s\n", __func__,1352 pcm_dev->dev_name);1353 return 0;1354 }1355 1356 pcmdev_controls = devm_kzalloc(pcm_dev->dev,1357 nr_chn * sizeof(struct snd_kcontrol_new), GFP_KERNEL);1358 if (!pcmdev_controls)1359 return -ENOMEM;1360 1361 name_id = pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl_name_id;1362 1363 ctrl_name = pcmdev_ctrl_name[name_id];1364 1365 for (chn = 1; chn <= nr_chn; chn++) {1366 name = devm_kzalloc(pcm_dev->dev,1367 SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL);1368 if (!name) {1369 ret = -ENOMEM;1370 goto out;1371 }1372 scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,1373 ctrl_name, pcm_dev->upper_dev_name, adap->nr,1374 dev_no, chn);1375 pcmdev_controls[mix_index].tlv.p =1376 pcmdev_gain_ctl_info[id][ctl_id].gain;1377 pcmdev_ctrl = devm_kmemdup(pcm_dev->dev,1378 &pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl[chn - 1],1379 sizeof(*pcmdev_ctrl), GFP_KERNEL);1380 if (!pcmdev_ctrl) {1381 ret = -ENOMEM;1382 goto out;1383 }1384 pcmdev_ctrl->dev_no = dev_no;1385 pcmdev_controls[mix_index].private_value =1386 (unsigned long)pcmdev_ctrl;1387 pcmdev_controls[mix_index].name = name;1388 pcmdev_controls[mix_index].access =1389 SNDRV_CTL_ELEM_ACCESS_TLV_READ |1390 SNDRV_CTL_ELEM_ACCESS_READWRITE;1391 pcmdev_controls[mix_index].iface =1392 SNDRV_CTL_ELEM_IFACE_MIXER;1393 pcmdev_controls[mix_index].info = pcmdevice_info_volsw;1394 pcmdev_controls[mix_index].get =1395 pcmdev_gain_ctl_info[id][ctl_id].get;1396 pcmdev_controls[mix_index].put =1397 pcmdev_gain_ctl_info[id][ctl_id].put;1398 mix_index++;1399 }1400 1401 ret = snd_soc_add_component_controls(comp, pcmdev_controls, mix_index);1402 if (ret)1403 dev_err(pcm_dev->dev, "%s: add_controls err = %d\n",1404 __func__, ret);1405out:1406 return ret;1407}1408 1409static int pcmdev_profile_ctrl_add(struct pcmdevice_priv *pcm_dev)1410{1411 struct snd_soc_component *comp = pcm_dev->component;1412 struct i2c_adapter *adap = pcm_dev->client->adapter;1413 struct snd_kcontrol_new *pcmdev_ctrl;1414 char *name;1415 int ret;1416 1417 pcmdev_ctrl = devm_kzalloc(pcm_dev->dev,1418 sizeof(struct snd_kcontrol_new), GFP_KERNEL);1419 if (!pcmdev_ctrl)1420 return -ENOMEM;1421 1422 /* Create a mixer item for selecting the active profile */1423 name = devm_kzalloc(pcm_dev->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,1424 GFP_KERNEL);1425 if (!name)1426 return -ENOMEM;1427 1428 scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,1429 "%s i2c%d Profile id", pcm_dev->upper_dev_name, adap->nr);1430 pcmdev_ctrl->name = name;1431 pcmdev_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER;1432 pcmdev_ctrl->info = pcmdevice_info_profile;1433 pcmdev_ctrl->get = pcmdevice_get_profile_id;1434 pcmdev_ctrl->put = pcmdevice_set_profile_id;1435 1436 ret = snd_soc_add_component_controls(comp, pcmdev_ctrl, 1);1437 if (ret)1438 dev_err(pcm_dev->dev, "%s: add_controls err = %d\n",1439 __func__, ret);1440 1441 return ret;1442}1443 1444static void pcmdevice_config_info_remove(void *ctxt)1445{1446 struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *) ctxt;1447 struct pcmdevice_regbin *regbin = &(pcm_dev->regbin);1448 struct pcmdevice_config_info **cfg_info = regbin->cfg_info;1449 int i, j;1450 1451 if (!cfg_info)1452 return;1453 for (i = 0; i < regbin->ncfgs; i++) {1454 if (!cfg_info[i])1455 continue;1456 if (cfg_info[i]->blk_data) {1457 for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) {1458 if (!cfg_info[i]->blk_data[j])1459 continue;1460 kfree(cfg_info[i]->blk_data[j]->regdata);1461 kfree(cfg_info[i]->blk_data[j]);1462 }1463 kfree(cfg_info[i]->blk_data);1464 }1465 kfree(cfg_info[i]);1466 }1467 kfree(cfg_info);1468}1469 1470static int pcmdev_regbin_ready(const struct firmware *fmw, void *ctxt)1471{1472 struct pcmdevice_config_info **cfg_info;1473 struct pcmdevice_priv *pcm_dev = ctxt;1474 struct pcmdevice_regbin_hdr *fw_hdr;1475 struct pcmdevice_regbin *regbin;1476 unsigned int total_config_sz = 0;1477 int offset = 0, ret = 0, i;1478 unsigned char *buf;1479 1480 regbin = &(pcm_dev->regbin);1481 fw_hdr = &(regbin->fw_hdr);1482 if (!fmw || !fmw->data) {1483 dev_err(pcm_dev->dev, "%s: failed to read %s\n",1484 __func__, pcm_dev->bin_name);1485 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1486 ret = -EINVAL;1487 goto out;1488 }1489 buf = (unsigned char *)fmw->data;1490 1491 fw_hdr->img_sz = get_unaligned_be32(&buf[offset]);1492 offset += 4;1493 if (fw_hdr->img_sz != fmw->size) {1494 dev_err(pcm_dev->dev, "%s: file size(%d) not match %u",1495 __func__, (int)fmw->size, fw_hdr->img_sz);1496 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1497 ret = -EINVAL;1498 goto out;1499 }1500 1501 fw_hdr->checksum = get_unaligned_be32(&buf[offset]);1502 offset += 4;1503 fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]);1504 if (fw_hdr->binary_version_num < 0x103) {1505 dev_err(pcm_dev->dev, "%s: bin version 0x%04x is out of date",1506 __func__, fw_hdr->binary_version_num);1507 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1508 ret = -EINVAL;1509 goto out;1510 }1511 offset += 4;1512 fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]);1513 offset += 8;1514 fw_hdr->plat_type = buf[offset];1515 offset += 1;1516 fw_hdr->dev_family = buf[offset];1517 offset += 1;1518 fw_hdr->reserve = buf[offset];1519 offset += 1;1520 fw_hdr->ndev = buf[offset];1521 offset += 1;1522 if (fw_hdr->ndev != pcm_dev->ndev) {1523 dev_err(pcm_dev->dev, "%s: invalid ndev(%u)\n", __func__,1524 fw_hdr->ndev);1525 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1526 ret = -EINVAL;1527 goto out;1528 }1529 1530 if (offset + PCMDEVICE_MAX_REGBIN_DEVICES > fw_hdr->img_sz) {1531 dev_err(pcm_dev->dev, "%s: devs out of boundary!\n", __func__);1532 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1533 ret = -EINVAL;1534 goto out;1535 }1536 1537 for (i = 0; i < PCMDEVICE_MAX_REGBIN_DEVICES; i++, offset++)1538 fw_hdr->devs[i] = buf[offset];1539 1540 fw_hdr->nconfig = get_unaligned_be32(&buf[offset]);1541 offset += 4;1542 1543 for (i = 0; i < PCMDEVICE_CONFIG_SUM; i++) {1544 fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]);1545 offset += 4;1546 total_config_sz += fw_hdr->config_size[i];1547 }1548 1549 if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) {1550 dev_err(pcm_dev->dev, "%s: bin file error!\n", __func__);1551 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1552 ret = -EINVAL;1553 goto out;1554 }1555 cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL);1556 if (!cfg_info) {1557 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1558 ret = -ENOMEM;1559 goto out;1560 }1561 regbin->cfg_info = cfg_info;1562 regbin->ncfgs = 0;1563 for (i = 0; i < (int)fw_hdr->nconfig; i++) {1564 cfg_info[i] = pcmdevice_add_config(ctxt, &buf[offset],1565 fw_hdr->config_size[i], &ret);1566 if (ret) {1567 /* In case the bin file is partially destroyed. */1568 if (regbin->ncfgs == 0)1569 pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED;1570 break;1571 }1572 offset += (int)fw_hdr->config_size[i];1573 regbin->ncfgs += 1;1574 }1575 1576out:1577 if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) {1578 dev_err(pcm_dev->dev,1579 "%s: remove config due to fw load error!\n", __func__);1580 pcmdevice_config_info_remove(pcm_dev);1581 }1582 1583 return ret;1584}1585 1586static int pcmdevice_comp_probe(struct snd_soc_component *comp)1587{1588 struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(comp);1589 struct i2c_adapter *adap = pcm_dev->client->adapter;1590 const struct firmware *fw_entry = NULL;1591 int ret, i, j;1592 1593 mutex_lock(&pcm_dev->codec_lock);1594 1595 pcm_dev->component = comp;1596 1597 for (i = 0; i < pcm_dev->ndev; i++) {1598 for (j = 0; j < 2; j++) {1599 ret = pcmdev_gain_ctrl_add(pcm_dev, i, j);1600 if (ret < 0)1601 goto out;1602 }1603 }1604 1605 if (comp->name_prefix) {1606 /* There's name_prefix defined in DTS. Bin file name will be1607 * name_prefix.bin stores the firmware including register1608 * setting and params for different filters inside chips, it1609 * must be copied into firmware folder. The same types of1610 * pcmdevices sitting on the same i2c bus will be aggregated as1611 * one single codec, all of them share the same bin file.1612 */1613 scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN,1614 "%s.bin", comp->name_prefix);1615 } else {1616 /* There's NO name_prefix defined in DTS. Bin file name will be1617 * device-name[defined in pcmdevice_i2c_id]-i2c-bus_id1618 * [0,1,...,N]-sum[1,...,4]dev.bin stores the firmware1619 * including register setting and params for different filters1620 * inside chips, it must be copied into firmware folder. The1621 * same types of pcmdevices sitting on the same i2c bus will be1622 * aggregated as one single codec, all of them share the same1623 * bin file.1624 */1625 scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN,1626 "%s-i2c-%d-%udev.bin", pcm_dev->dev_name, adap->nr,1627 pcm_dev->ndev);1628 }1629 1630 ret = request_firmware(&fw_entry, pcm_dev->bin_name, pcm_dev->dev);1631 if (ret) {1632 dev_err(pcm_dev->dev, "%s: request %s err = %d\n", __func__,1633 pcm_dev->bin_name, ret);1634 goto out;1635 }1636 1637 ret = pcmdev_regbin_ready(fw_entry, pcm_dev);1638 if (ret) {1639 dev_err(pcm_dev->dev, "%s: %s parse err = %d\n", __func__,1640 pcm_dev->bin_name, ret);1641 goto out;1642 }1643 ret = pcmdev_profile_ctrl_add(pcm_dev);1644out:1645 if (fw_entry)1646 release_firmware(fw_entry);1647 1648 mutex_unlock(&pcm_dev->codec_lock);1649 return ret;1650}1651 1652 1653static void pcmdevice_comp_remove(struct snd_soc_component *codec)1654{1655 struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec);1656 1657 if (!pcm_dev)1658 return;1659 mutex_lock(&pcm_dev->codec_lock);1660 pcmdevice_config_info_remove(pcm_dev);1661 mutex_unlock(&pcm_dev->codec_lock);1662}1663 1664static const struct snd_soc_dapm_widget pcmdevice_dapm_widgets[] = {1665 SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0),1666 SND_SOC_DAPM_AIF_OUT("ASI1 OUT", "ASI1 Capture",1667 0, SND_SOC_NOPM, 0, 0),1668 SND_SOC_DAPM_OUTPUT("OUT"),1669 SND_SOC_DAPM_INPUT("MIC"),1670};1671 1672static const struct snd_soc_dapm_route pcmdevice_audio_map[] = {1673 {"OUT", NULL, "ASI"},1674 {"ASI1 OUT", NULL, "MIC"},1675};1676 1677static const struct snd_soc_component_driver1678 soc_codec_driver_pcmdevice = {1679 .probe = pcmdevice_comp_probe,1680 .remove = pcmdevice_comp_remove,1681 .dapm_widgets = pcmdevice_dapm_widgets,1682 .num_dapm_widgets = ARRAY_SIZE(pcmdevice_dapm_widgets),1683 .dapm_routes = pcmdevice_audio_map,1684 .num_dapm_routes = ARRAY_SIZE(pcmdevice_audio_map),1685 .suspend_bias_off = 1,1686 .idle_bias_on = 0,1687 .use_pmdown_time = 1,1688 .endianness = 1,1689};1690 1691static int pcmdev_single_byte_wr(struct pcmdevice_priv *pcm_dev,1692 unsigned char *data, int devn, int sublocksize)1693{1694 unsigned short len = get_unaligned_be16(&data[2]);1695 int offset = 2;1696 int i, ret;1697 1698 offset += 2;1699 if (offset + 4 * len > sublocksize) {1700 dev_err(pcm_dev->dev, "%s: dev-%d byt wr out of boundary\n",1701 __func__, devn);1702 return -EINVAL;1703 }1704 1705 for (i = 0; i < len; i++) {1706 ret = pcmdev_dev_write(pcm_dev, devn,1707 PCMDEVICE_REG(data[offset + 1], data[offset + 2]),1708 data[offset + 3]);1709 /* skip this error for next operation or next devices */1710 if (ret < 0)1711 dev_err(pcm_dev->dev, "%s: dev-%d single write err\n",1712 __func__, devn);1713 1714 offset += 4;1715 }1716 1717 return offset;1718}1719 1720static int pcmdev_burst_wr(struct pcmdevice_priv *pcm_dev,1721 unsigned char *data, int devn, int sublocksize)1722{1723 unsigned short len = get_unaligned_be16(&data[2]);1724 int offset = 2;1725 int ret;1726 1727 offset += 2;1728 if (offset + 4 + len > sublocksize) {1729 dev_err(pcm_dev->dev, "%s: dev-%d burst Out of boundary\n",1730 __func__, devn);1731 return -EINVAL;1732 }1733 if (len % 4) {1734 dev_err(pcm_dev->dev, "%s: dev-%d bst-len(%u) not div by 4\n",1735 __func__, devn, len);1736 return -EINVAL;1737 }1738 ret = pcmdev_dev_bulk_write(pcm_dev, devn,1739 PCMDEVICE_REG(data[offset + 1], data[offset + 2]),1740 &(data[offset + 4]), len);1741 /* skip this error for next devices */1742 if (ret < 0)1743 dev_err(pcm_dev->dev, "%s: dev-%d bulk_write err = %d\n",1744 __func__, devn, ret);1745 1746 offset += (len + 4);1747 1748 return offset;1749}1750 1751static int pcmdev_delay(struct pcmdevice_priv *pcm_dev,1752 unsigned char *data, int devn, int sublocksize)1753{1754 unsigned int delay_time = 0;1755 int offset = 2;1756 1757 if (offset + 2 > sublocksize) {1758 dev_err(pcm_dev->dev, "%s: dev-%d delay out of boundary\n",1759 __func__, devn);1760 return -EINVAL;1761 }1762 delay_time = get_unaligned_be16(&data[2]) * 1000;1763 usleep_range(delay_time, delay_time + 50);1764 offset += 2;1765 1766 return offset;1767}1768 1769static int pcmdev_bits_wr(struct pcmdevice_priv *pcm_dev,1770 unsigned char *data, int devn, int sublocksize)1771{1772 int offset = 2;1773 int ret;1774 1775 if (offset + 6 > sublocksize) {1776 dev_err(pcm_dev->dev, "%s: dev-%d bit write out of memory\n",1777 __func__, devn);1778 return -EINVAL;1779 }1780 ret = pcmdev_dev_update_bits(pcm_dev, devn,1781 PCMDEVICE_REG(data[offset + 3], data[offset + 4]),1782 data[offset + 1], data[offset + 5]);1783 /* skip this error for next devices */1784 if (ret < 0)1785 dev_err(pcm_dev->dev, "%s: dev-%d update_bits err = %d\n",1786 __func__, devn, ret);1787 1788 offset += 6;1789 1790 return offset;1791}1792 1793static int pcmdevice_process_block(void *ctxt, unsigned char *data,1794 unsigned char dev_idx, int sublocksize)1795{1796 struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;1797 int devn, dev_end, ret = 0;1798 unsigned char subblk_typ = data[1];1799 1800 if (dev_idx) {1801 devn = dev_idx - 1;1802 dev_end = dev_idx;1803 } else {1804 devn = 0;1805 dev_end = pcm_dev->ndev;1806 }1807 1808 /* loop in case of several devices sharing the same sub-block */1809 for (; devn < dev_end; devn++) {1810 switch (subblk_typ) {1811 case PCMDEVICE_CMD_SING_W:1812 ret = pcmdev_single_byte_wr(pcm_dev, data, devn, sublocksize);1813 break;1814 case PCMDEVICE_CMD_BURST:1815 ret = pcmdev_burst_wr(pcm_dev, data, devn, sublocksize);1816 break;1817 case PCMDEVICE_CMD_DELAY:1818 ret = pcmdev_delay(pcm_dev, data, devn, sublocksize);1819 break;1820 case PCMDEVICE_CMD_FIELD_W:1821 ret = pcmdev_bits_wr(pcm_dev, data, devn, sublocksize);1822 break;1823 default:1824 break;1825 }1826 /*1827 * In case of sub-block error, break the loop for the rest of1828 * devices.1829 */1830 if (ret < 0)1831 break;1832 }1833 1834 return ret;1835}1836 1837static void pcmdevice_select_cfg_blk(void *ctxt, int conf_no,1838 unsigned char block_type)1839{1840 struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;1841 struct pcmdevice_regbin *regbin = &(pcm_dev->regbin);1842 struct pcmdevice_config_info **cfg_info = regbin->cfg_info;1843 struct pcmdevice_block_data **blk_data;1844 int j, k;1845 1846 if (conf_no >= regbin->ncfgs || conf_no < 0 || NULL == cfg_info) {1847 dev_err(pcm_dev->dev, "%s: conf_no should be less than %u\n",1848 __func__, regbin->ncfgs);1849 goto out;1850 }1851 blk_data = cfg_info[conf_no]->blk_data;1852 1853 for (j = 0; j < (int)cfg_info[conf_no]->real_nblocks; j++) {1854 unsigned int length = 0, ret;1855 1856 if (block_type > 5 || block_type < 2) {1857 dev_err(pcm_dev->dev,1858 "%s: block_type should be out of range\n",1859 __func__);1860 goto out;1861 }1862 if (block_type != blk_data[j]->block_type)1863 continue;1864 1865 for (k = 0; k < (int)blk_data[j]->n_subblks; k++) {1866 ret = pcmdevice_process_block(pcm_dev,1867 blk_data[j]->regdata + length,1868 blk_data[j]->dev_idx,1869 blk_data[j]->block_size - length);1870 length += ret;1871 if (blk_data[j]->block_size < length) {1872 dev_err(pcm_dev->dev,1873 "%s: %u %u out of boundary\n",1874 __func__, length,1875 blk_data[j]->block_size);1876 break;1877 }1878 }1879 if (length != blk_data[j]->block_size)1880 dev_err(pcm_dev->dev, "%s: %u %u size is not same\n",1881 __func__, length, blk_data[j]->block_size);1882 }1883 1884out:1885 return;1886}1887 1888static int pcmdevice_mute(struct snd_soc_dai *dai, int mute, int stream)1889{1890 struct snd_soc_component *codec = dai->component;1891 struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec);1892 unsigned char block_type;1893 1894 if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) {1895 dev_err(pcm_dev->dev, "%s: bin file not loaded\n", __func__);1896 return -EINVAL;1897 }1898 1899 if (mute)1900 block_type = PCMDEVICE_BIN_BLK_PRE_SHUTDOWN;1901 else1902 block_type = PCMDEVICE_BIN_BLK_PRE_POWER_UP;1903 1904 mutex_lock(&pcm_dev->codec_lock);1905 pcmdevice_select_cfg_blk(pcm_dev, pcm_dev->cur_conf, block_type);1906 mutex_unlock(&pcm_dev->codec_lock);1907 return 0;1908}1909 1910static int pcmdevice_hw_params(struct snd_pcm_substream *substream,1911 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)1912{1913 struct pcmdevice_priv *pcm_dev = snd_soc_dai_get_drvdata(dai);1914 unsigned int fsrate;1915 unsigned int slot_width;1916 int bclk_rate;1917 int ret = 0;1918 1919 fsrate = params_rate(params);1920 switch (fsrate) {1921 case 48000:1922 break;1923 case 44100:1924 break;1925 default:1926 dev_err(pcm_dev->dev, "%s: incorrect sample rate = %u\n",1927 __func__, fsrate);1928 ret = -EINVAL;1929 goto out;1930 }1931 1932 slot_width = params_width(params);1933 switch (slot_width) {1934 case 16:1935 break;1936 case 20:1937 break;1938 case 24:1939 break;1940 case 32:1941 break;1942 default:1943 dev_err(pcm_dev->dev, "%s: incorrect slot width = %u\n",1944 __func__, slot_width);1945 ret = -EINVAL;1946 goto out;1947 }1948 1949 bclk_rate = snd_soc_params_to_bclk(params);1950 if (bclk_rate < 0) {1951 dev_err(pcm_dev->dev, "%s: incorrect bclk rate = %d\n",1952 __func__, bclk_rate);1953 ret = bclk_rate;1954 }1955 1956out:1957 return ret;1958}1959 1960static const struct snd_soc_dai_ops pcmdevice_dai_ops = {1961 .mute_stream = pcmdevice_mute,1962 .hw_params = pcmdevice_hw_params,1963};1964 1965static struct snd_soc_dai_driver pcmdevice_dai_driver[] = {1966 {1967 .name = "pcmdevice-codec",1968 .capture = {1969 .stream_name = "Capture",1970 .channels_min = 2,1971 .channels_max = PCMDEVICE_MAX_CHANNELS,1972 .rates = PCMDEVICE_RATES,1973 .formats = PCMDEVICE_FORMATS,1974 },1975 .playback = {1976 .stream_name = "Playback",1977 .channels_min = 2,1978 .channels_max = PCMDEVICE_MAX_CHANNELS,1979 .rates = PCMDEVICE_RATES,1980 .formats = PCMDEVICE_FORMATS,1981 },1982 .ops = &pcmdevice_dai_ops,1983 .symmetric_rate = 1,1984 }1985};1986 1987#ifdef CONFIG_OF1988static const struct of_device_id pcmdevice_of_match[] = {1989 { .compatible = "ti,adc3120" },1990 { .compatible = "ti,adc5120" },1991 { .compatible = "ti,adc6120" },1992 { .compatible = "ti,dix4192" },1993 { .compatible = "ti,pcm1690" },1994 { .compatible = "ti,pcm3120" },1995 { .compatible = "ti,pcm3140" },1996 { .compatible = "ti,pcm5120" },1997 { .compatible = "ti,pcm5140" },1998 { .compatible = "ti,pcm6120" },1999 { .compatible = "ti,pcm6140" },2000 { .compatible = "ti,pcm6240" },2001 { .compatible = "ti,pcm6260" },2002 { .compatible = "ti,pcm9211" },2003 { .compatible = "ti,pcmd3140" },2004 { .compatible = "ti,pcmd3180" },2005 { .compatible = "ti,pcmd512x" },2006 { .compatible = "ti,taa5212" },2007 { .compatible = "ti,taa5412" },2008 { .compatible = "ti,tad5212" },2009 { .compatible = "ti,tad5412" },2010 {},2011};2012MODULE_DEVICE_TABLE(of, pcmdevice_of_match);2013#endif2014 2015static const struct regmap_range_cfg pcmdevice_ranges[] = {2016 {2017 .range_min = 0,2018 .range_max = 256 * 128,2019 .selector_reg = PCMDEVICE_PAGE_SELECT,2020 .selector_mask = 0xff,2021 .selector_shift = 0,2022 .window_start = 0,2023 .window_len = 128,2024 },2025};2026 2027static const struct regmap_config pcmdevice_i2c_regmap = {2028 .reg_bits = 8,2029 .val_bits = 8,2030 .cache_type = REGCACHE_MAPLE,2031 .ranges = pcmdevice_ranges,2032 .num_ranges = ARRAY_SIZE(pcmdevice_ranges),2033 .max_register = 256 * 128,2034};2035 2036static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev)2037{2038 if (gpio_is_valid(pcm_dev->irq_info.gpio)) {2039 gpio_free(pcm_dev->irq_info.gpio);2040 free_irq(pcm_dev->irq_info.nmb, pcm_dev);2041 }2042 mutex_destroy(&pcm_dev->codec_lock);2043}2044 2045static char *str_to_upper(char *str)2046{2047 char *orig = str;2048 2049 if (!str)2050 return NULL;2051 2052 while (*str) {2053 *str = toupper(*str);2054 str++;2055 }2056 2057 return orig;2058}2059 2060static int pcmdevice_i2c_probe(struct i2c_client *i2c)2061{2062 const struct i2c_device_id *id = i2c_match_id(pcmdevice_i2c_id, i2c);2063 struct pcmdevice_priv *pcm_dev;2064 struct device_node *np;2065 unsigned int dev_addrs[PCMDEVICE_MAX_I2C_DEVICES];2066 int ret = 0, i = 0, ndev = 0;2067 2068 pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL);2069 if (!pcm_dev)2070 return -ENOMEM;2071 2072 pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0;2073 2074 pcm_dev->dev = &i2c->dev;2075 pcm_dev->client = i2c;2076 2077 if (pcm_dev->chip_id >= MAX_DEVICE)2078 pcm_dev->chip_id = 0;2079 2080 strscpy(pcm_dev->dev_name, pcmdevice_i2c_id[pcm_dev->chip_id].name,2081 sizeof(pcm_dev->dev_name));2082 2083 strscpy(pcm_dev->upper_dev_name,2084 pcmdevice_i2c_id[pcm_dev->chip_id].name,2085 sizeof(pcm_dev->upper_dev_name));2086 2087 str_to_upper(pcm_dev->upper_dev_name);2088 2089 pcm_dev->regmap = devm_regmap_init_i2c(i2c, &pcmdevice_i2c_regmap);2090 if (IS_ERR(pcm_dev->regmap)) {2091 ret = PTR_ERR(pcm_dev->regmap);2092 dev_err(&i2c->dev, "%s: failed to allocate register map: %d\n",2093 __func__, ret);2094 goto out;2095 }2096 2097 i2c_set_clientdata(i2c, pcm_dev);2098 mutex_init(&pcm_dev->codec_lock);2099 np = pcm_dev->dev->of_node;2100 2101 if (IS_ENABLED(CONFIG_OF)) {2102 u64 addr;2103 2104 for (i = 0; i < PCMDEVICE_MAX_I2C_DEVICES; i++) {2105 if (of_property_read_reg(np, i, &addr, NULL))2106 break;2107 dev_addrs[ndev++] = addr;2108 }2109 } else {2110 ndev = 1;2111 dev_addrs[0] = i2c->addr;2112 }2113 pcm_dev->irq_info.gpio = of_irq_get(np, 0);2114 2115 for (i = 0; i < ndev; i++)2116 pcm_dev->addr[i] = dev_addrs[i];2117 2118 pcm_dev->ndev = ndev;2119 2120 pcm_dev->hw_rst = devm_gpiod_get_optional(&i2c->dev,2121 "reset-gpios", GPIOD_OUT_HIGH);2122 /* No reset GPIO, no side-effect */2123 if (IS_ERR(pcm_dev->hw_rst)) {2124 if (pcm_dev->chip_id == PCM9211 || pcm_dev->chip_id == PCM1690)2125 pcm9211_sw_rst(pcm_dev);2126 else2127 pcmdevice_sw_rst(pcm_dev);2128 } else {2129 gpiod_set_value_cansleep(pcm_dev->hw_rst, 0);2130 usleep_range(500, 1000);2131 gpiod_set_value_cansleep(pcm_dev->hw_rst, 1);2132 }2133 2134 if (pcm_dev->chip_id == PCM1690)2135 goto skip_interrupt;2136 if (gpio_is_valid(pcm_dev->irq_info.gpio)) {2137 dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio);2138 2139 ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ");2140 if (!ret) {2141 int gpio = pcm_dev->irq_info.gpio;2142 2143 gpio_direction_input(gpio);2144 pcm_dev->irq_info.nmb = gpio_to_irq(gpio);2145 2146 } else2147 dev_err(pcm_dev->dev, "%s: GPIO %d request error\n",2148 __func__, pcm_dev->irq_info.gpio);2149 } else2150 dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n",2151 pcm_dev->irq_info.gpio);2152 2153skip_interrupt:2154 ret = devm_snd_soc_register_component(&i2c->dev,2155 &soc_codec_driver_pcmdevice, pcmdevice_dai_driver,2156 ARRAY_SIZE(pcmdevice_dai_driver));2157 if (ret < 0)2158 dev_err(&i2c->dev, "probe register comp failed %d\n", ret);2159 2160out:2161 if (ret < 0)2162 pcmdevice_remove(pcm_dev);2163 return ret;2164}2165 2166static void pcmdevice_i2c_remove(struct i2c_client *i2c)2167{2168 struct pcmdevice_priv *pcm_dev = i2c_get_clientdata(i2c);2169 2170 pcmdevice_remove(pcm_dev);2171}2172 2173static struct i2c_driver pcmdevice_i2c_driver = {2174 .driver = {2175 .name = "pcmdevice-codec",2176 .of_match_table = of_match_ptr(pcmdevice_of_match),2177 },2178 .probe = pcmdevice_i2c_probe,2179 .remove = pcmdevice_i2c_remove,2180 .id_table = pcmdevice_i2c_id,2181};2182module_i2c_driver(pcmdevice_i2c_driver);2183 2184MODULE_AUTHOR("Shenghao Ding <shenghao-ding@ti.com>");2185MODULE_DESCRIPTION("ASoC PCM6240 Family Audio ADC/DAC Driver");2186MODULE_LICENSE("GPL");2187