.. | .. |
---|
67 | 67 | struct regmap *regmap; |
---|
68 | 68 | struct rk808 *rk817; |
---|
69 | 69 | struct clk *mclk; |
---|
| 70 | + struct mutex clk_lock; |
---|
70 | 71 | |
---|
| 72 | + unsigned int clk_capture; |
---|
| 73 | + unsigned int clk_playback; |
---|
71 | 74 | unsigned int stereo_sysclk; |
---|
72 | 75 | unsigned int rate; |
---|
73 | 76 | |
---|
.. | .. |
---|
79 | 82 | bool pdmdata_out_enable; |
---|
80 | 83 | bool use_ext_amplifier; |
---|
81 | 84 | bool adc_for_loopback; |
---|
| 85 | + bool resume_path; |
---|
82 | 86 | |
---|
83 | 87 | bool out_l2spk_r2hp; |
---|
84 | 88 | long int playback_path; |
---|
.. | .. |
---|
506 | 510 | static const char * const rk817_capture_path_mode[] = { |
---|
507 | 511 | "MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"}; |
---|
508 | 512 | |
---|
509 | | -static const char * const rk817_call_path_mode[] = { |
---|
510 | | - "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT"}; /* 0-5 */ |
---|
511 | | - |
---|
512 | | -static const char * const rk817_modem_input_mode[] = {"OFF", "ON"}; |
---|
| 513 | +static const char * const rk817_binary_mode[] = {"OFF", "ON"}; |
---|
513 | 514 | |
---|
514 | 515 | static SOC_ENUM_SINGLE_DECL(rk817_playback_path_type, |
---|
515 | 516 | 0, 0, rk817_playback_path_mode); |
---|
.. | .. |
---|
517 | 518 | static SOC_ENUM_SINGLE_DECL(rk817_capture_path_type, |
---|
518 | 519 | 0, 0, rk817_capture_path_mode); |
---|
519 | 520 | |
---|
520 | | -static SOC_ENUM_SINGLE_DECL(rk817_call_path_type, |
---|
521 | | - 0, 0, rk817_call_path_mode); |
---|
522 | | - |
---|
523 | | -static SOC_ENUM_SINGLE_DECL(rk817_modem_input_type, |
---|
524 | | - 0, 0, rk817_modem_input_mode); |
---|
| 521 | +static SOC_ENUM_SINGLE_DECL(rk817_resume_path_type, |
---|
| 522 | + 0, 0, rk817_binary_mode); |
---|
525 | 523 | |
---|
526 | 524 | static int rk817_playback_path_config(struct snd_soc_component *component, |
---|
527 | 525 | long pre_path, long target_path) |
---|
.. | .. |
---|
533 | 531 | DBG("%s : set playback_path %ld, pre_path %ld\n", |
---|
534 | 532 | __func__, rk817->playback_path, pre_path); |
---|
535 | 533 | |
---|
536 | | - if (rk817->playback_path != OFF) |
---|
537 | | - clk_prepare_enable(rk817->mclk); |
---|
538 | | - else |
---|
539 | | - clk_disable_unprepare(rk817->mclk); |
---|
| 534 | + mutex_lock(&rk817->clk_lock); |
---|
| 535 | + if (rk817->playback_path != OFF) { |
---|
| 536 | + if (rk817->clk_playback == 0) { |
---|
| 537 | + clk_prepare_enable(rk817->mclk); |
---|
| 538 | + rk817->clk_playback++; |
---|
| 539 | + } |
---|
| 540 | + } else { |
---|
| 541 | + if (rk817->clk_playback > 0) { |
---|
| 542 | + clk_disable_unprepare(rk817->mclk); |
---|
| 543 | + rk817->clk_playback--; |
---|
| 544 | + } |
---|
| 545 | + } |
---|
| 546 | + mutex_unlock(&rk817->clk_lock); |
---|
540 | 547 | |
---|
541 | 548 | switch (rk817->playback_path) { |
---|
542 | 549 | case OFF: |
---|
.. | .. |
---|
720 | 727 | DBG("%s : set capture_path %ld, pre_path %ld\n", __func__, |
---|
721 | 728 | rk817->capture_path, pre_path); |
---|
722 | 729 | |
---|
723 | | - if (rk817->capture_path != MIC_OFF) |
---|
724 | | - clk_prepare_enable(rk817->mclk); |
---|
725 | | - else |
---|
726 | | - clk_disable_unprepare(rk817->mclk); |
---|
| 730 | + mutex_lock(&rk817->clk_lock); |
---|
| 731 | + if (rk817->capture_path != MIC_OFF) { |
---|
| 732 | + if (rk817->clk_capture == 0) { |
---|
| 733 | + clk_prepare_enable(rk817->mclk); |
---|
| 734 | + rk817->clk_capture++; |
---|
| 735 | + } |
---|
| 736 | + } else { |
---|
| 737 | + if (rk817->clk_capture > 0) { |
---|
| 738 | + clk_disable_unprepare(rk817->mclk); |
---|
| 739 | + rk817->clk_capture--; |
---|
| 740 | + } |
---|
| 741 | + } |
---|
| 742 | + mutex_unlock(&rk817->clk_lock); |
---|
727 | 743 | |
---|
728 | 744 | switch (rk817->capture_path) { |
---|
729 | 745 | case MIC_OFF: |
---|
.. | .. |
---|
842 | 858 | ucontrol->value.integer.value[0]); |
---|
843 | 859 | } |
---|
844 | 860 | |
---|
| 861 | +static int rk817_resume_path_get(struct snd_kcontrol *kcontrol, |
---|
| 862 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 863 | +{ |
---|
| 864 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
| 865 | + struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); |
---|
| 866 | + |
---|
| 867 | + DBG("%s : resume_path %ld\n", __func__, rk817->resume_path); |
---|
| 868 | + |
---|
| 869 | + ucontrol->value.integer.value[0] = rk817->resume_path; |
---|
| 870 | + |
---|
| 871 | + return 0; |
---|
| 872 | +} |
---|
| 873 | + |
---|
| 874 | +static int rk817_resume_path_put(struct snd_kcontrol *kcontrol, |
---|
| 875 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 876 | +{ |
---|
| 877 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
| 878 | + struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); |
---|
| 879 | + |
---|
| 880 | + rk817->resume_path = ucontrol->value.integer.value[0]; |
---|
| 881 | + |
---|
| 882 | + return 0; |
---|
| 883 | +} |
---|
| 884 | + |
---|
845 | 885 | static struct snd_kcontrol_new rk817_snd_path_controls[] = { |
---|
846 | 886 | SOC_ENUM_EXT("Playback Path", rk817_playback_path_type, |
---|
847 | 887 | rk817_playback_path_get, rk817_playback_path_put), |
---|
848 | 888 | |
---|
849 | 889 | SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type, |
---|
850 | 890 | rk817_capture_path_get, rk817_capture_path_put), |
---|
| 891 | + |
---|
| 892 | + SOC_ENUM_EXT("Resume Path", rk817_resume_path_type, |
---|
| 893 | + rk817_resume_path_get, rk817_resume_path_put), |
---|
851 | 894 | }; |
---|
852 | 895 | |
---|
853 | 896 | static int rk817_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
---|
.. | .. |
---|
892 | 935 | struct snd_pcm_hw_params *params, |
---|
893 | 936 | struct snd_soc_dai *dai) |
---|
894 | 937 | { |
---|
895 | | - struct snd_soc_pcm_runtime *rtd = substream->private_data; |
---|
896 | | - struct snd_soc_component *component = rtd->codec_dai->component; |
---|
| 938 | + struct snd_soc_component *component = dai->component; |
---|
897 | 939 | struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); |
---|
898 | 940 | unsigned int rate = params_rate(params); |
---|
899 | 941 | unsigned char apll_cfg3_val; |
---|
.. | .. |
---|
946 | 988 | * is before playback/capture_path_put, therefore, we need to configure |
---|
947 | 989 | * APLL_CFG3/DTOP_DIGEN_CLKE/DDAC_SR_LMT0 for different sample rates. |
---|
948 | 990 | */ |
---|
949 | | - snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, apll_cfg3_val); |
---|
950 | | - /* The 0x00 contains ADC_DIG_CLK_DIS and DAC_DIG_CLK_DIS */ |
---|
951 | | - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, |
---|
952 | | - dtop_digen_clke, 0x00); |
---|
953 | | - snd_soc_component_update_bits(component, RK817_CODEC_DDAC_SR_LMT0, |
---|
954 | | - DACSRT_MASK, dtop_digen_sr_lmt0); |
---|
955 | | - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, |
---|
956 | | - dtop_digen_clke, dtop_digen_clke); |
---|
| 991 | + if (!((substream->stream == SNDRV_PCM_STREAM_CAPTURE) && rk817->pdmdata_out_enable)) { |
---|
| 992 | + snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, apll_cfg3_val); |
---|
| 993 | + /* The 0x00 contains ADC_DIG_CLK_DIS and DAC_DIG_CLK_DIS */ |
---|
| 994 | + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, |
---|
| 995 | + dtop_digen_clke, 0x00); |
---|
| 996 | + snd_soc_component_update_bits(component, RK817_CODEC_DDAC_SR_LMT0, |
---|
| 997 | + DACSRT_MASK, dtop_digen_sr_lmt0); |
---|
| 998 | + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, |
---|
| 999 | + dtop_digen_clke, dtop_digen_clke); |
---|
| 1000 | + snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, |
---|
| 1001 | + PLL_PW_DOWN, PLL_PW_DOWN); |
---|
| 1002 | + usleep_range(50, 60); |
---|
| 1003 | + snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, |
---|
| 1004 | + PLL_PW_DOWN, PLL_PW_UP); |
---|
| 1005 | + usleep_range(500, 600); |
---|
| 1006 | + } |
---|
957 | 1007 | |
---|
958 | 1008 | switch (params_format(params)) { |
---|
959 | 1009 | case SNDRV_PCM_FORMAT_S16_LE: |
---|
.. | .. |
---|
1144 | 1194 | |
---|
1145 | 1195 | static int rk817_resume(struct snd_soc_component *component) |
---|
1146 | 1196 | { |
---|
| 1197 | + struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component); |
---|
| 1198 | + |
---|
| 1199 | + if (rk817->resume_path) { |
---|
| 1200 | + if (rk817->capture_path != MIC_OFF) |
---|
| 1201 | + rk817_capture_path_config(component, OFF, rk817->capture_path); |
---|
| 1202 | + if (rk817->playback_path != OFF) |
---|
| 1203 | + rk817_playback_path_config(component, OFF, rk817->playback_path); |
---|
| 1204 | + } |
---|
| 1205 | + |
---|
1147 | 1206 | return 0; |
---|
1148 | 1207 | } |
---|
1149 | 1208 | |
---|
.. | .. |
---|
1173 | 1232 | clk_prepare_enable(rk817->mclk); |
---|
1174 | 1233 | rk817_reset(component); |
---|
1175 | 1234 | clk_disable_unprepare(rk817->mclk); |
---|
| 1235 | + mutex_init(&rk817->clk_lock); |
---|
| 1236 | + rk817->clk_capture = 0; |
---|
| 1237 | + rk817->clk_playback = 0; |
---|
1176 | 1238 | |
---|
1177 | 1239 | snd_soc_add_component_controls(component, rk817_snd_path_controls, |
---|
1178 | 1240 | ARRAY_SIZE(rk817_snd_path_controls)); |
---|
.. | .. |
---|
1193 | 1255 | |
---|
1194 | 1256 | rk817_codec_power_down(component, RK817_CODEC_ALL); |
---|
1195 | 1257 | snd_soc_component_exit_regmap(component); |
---|
| 1258 | + mutex_destroy(&rk817->clk_lock); |
---|
1196 | 1259 | mdelay(10); |
---|
1197 | 1260 | |
---|
1198 | 1261 | } |
---|