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

ASoC: codecs: wcd-clsh: add new version support

From WCD937X Class H controller has changed significantly, so add support
to this new version for WCD937X and WCD938X Codecs.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20210609090943.7896-3-srinivas.kandagatla@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Srinivas Kandagatla and committed by
Mark Brown
19c5d1f6 10ee3e07

+354 -10
+338 -10
sound/soc/codecs/wcd-clsh-v2.c
··· 88 88 #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA 0x50 89 89 #define WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_30MA 0x30 90 90 91 + #define WCD9XXX_BASE_ADDRESS 0x3000 92 + #define WCD9XXX_ANA_RX_SUPPLIES (WCD9XXX_BASE_ADDRESS+0x008) 93 + #define WCD9XXX_ANA_HPH (WCD9XXX_BASE_ADDRESS+0x009) 94 + #define WCD9XXX_CLASSH_MODE_2 (WCD9XXX_BASE_ADDRESS+0x098) 95 + #define WCD9XXX_CLASSH_MODE_3 (WCD9XXX_BASE_ADDRESS+0x099) 96 + #define WCD9XXX_FLYBACK_VNEG_CTRL_1 (WCD9XXX_BASE_ADDRESS+0x0A5) 97 + #define WCD9XXX_FLYBACK_VNEG_CTRL_4 (WCD9XXX_BASE_ADDRESS+0x0A8) 98 + #define WCD9XXX_FLYBACK_VNEGDAC_CTRL_2 (WCD9XXX_BASE_ADDRESS+0x0AF) 99 + #define WCD9XXX_RX_BIAS_HPH_LOWPOWER (WCD9XXX_BASE_ADDRESS+0x0BF) 100 + #define WCD9XXX_V3_RX_BIAS_FLYB_BUFF (WCD9XXX_BASE_ADDRESS+0x0C7) 101 + #define WCD9XXX_HPH_PA_CTL1 (WCD9XXX_BASE_ADDRESS+0x0D1) 102 + #define WCD9XXX_HPH_NEW_INT_PA_MISC2 (WCD9XXX_BASE_ADDRESS+0x138) 103 + 91 104 #define CLSH_REQ_ENABLE true 92 105 #define CLSH_REQ_DISABLE false 93 106 #define WCD_USLEEP_RANGE 50 ··· 150 137 WCD9XXX_A_ANA_RX_VPOS_PWR_LVL_DEFAULT); 151 138 } 152 139 140 + static void wcd_clsh_v3_set_buck_mode(struct snd_soc_component *component, 141 + int mode) 142 + { 143 + if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI || 144 + mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI) 145 + snd_soc_component_update_bits(component, 146 + WCD9XXX_ANA_RX_SUPPLIES, 147 + 0x08, 0x08); /* set to HIFI */ 148 + else 149 + snd_soc_component_update_bits(component, 150 + WCD9XXX_ANA_RX_SUPPLIES, 151 + 0x08, 0x00); /* set to default */ 152 + } 153 + 153 154 static inline void wcd_clsh_set_flyback_mode(struct snd_soc_component *comp, 154 155 int mode) 155 156 { ··· 195 168 * as per HW requirement 196 169 */ 197 170 usleep_range(500, 500 + WCD_USLEEP_RANGE); 171 + } 172 + 173 + static void wcd_clsh_v3_buck_ctrl(struct snd_soc_component *component, 174 + struct wcd_clsh_ctrl *ctrl, 175 + int mode, 176 + bool enable) 177 + { 178 + /* enable/disable buck */ 179 + if ((enable && (++ctrl->buck_users == 1)) || 180 + (!enable && (--ctrl->buck_users == 0))) { 181 + snd_soc_component_update_bits(component, 182 + WCD9XXX_ANA_RX_SUPPLIES, 183 + (1 << 7), (enable << 7)); 184 + /* 185 + * 500us sleep is required after buck enable/disable 186 + * as per HW requirement 187 + */ 188 + usleep_range(500, 510); 189 + if (mode == CLS_H_LOHIFI || mode == CLS_H_ULP || 190 + mode == CLS_H_HIFI || mode == CLS_H_LP) 191 + snd_soc_component_update_bits(component, 192 + WCD9XXX_CLASSH_MODE_3, 193 + 0x02, 0x00); 194 + 195 + snd_soc_component_update_bits(component, 196 + WCD9XXX_CLASSH_MODE_2, 197 + 0xFF, 0x3A); 198 + /* 500usec delay is needed as per HW requirement */ 199 + usleep_range(500, 500 + WCD_USLEEP_RANGE); 200 + } 198 201 } 199 202 200 203 static void wcd_clsh_flyback_ctrl(struct wcd_clsh_ctrl *ctrl, ··· 276 219 val); 277 220 } 278 221 279 - static void wcd_clsh_set_hph_mode(struct snd_soc_component *comp, 280 - int mode) 222 + static void wcd_clsh_v2_set_hph_mode(struct snd_soc_component *comp, int mode) 281 223 { 282 224 int val = 0, gain = 0, res_val; 283 225 int ipeak = WCD9XXX_CLASSH_CTRL_CCL_1_DELTA_IPEAK_50MA; ··· 320 264 ipeak); 321 265 } 322 266 267 + static void wcd_clsh_v3_set_hph_mode(struct snd_soc_component *component, 268 + int mode) 269 + { 270 + u8 val; 271 + 272 + switch (mode) { 273 + case CLS_H_NORMAL: 274 + val = 0x00; 275 + break; 276 + case CLS_AB: 277 + case CLS_H_ULP: 278 + val = 0x0C; 279 + break; 280 + case CLS_AB_HIFI: 281 + case CLS_H_HIFI: 282 + val = 0x08; 283 + break; 284 + case CLS_H_LP: 285 + case CLS_H_LOHIFI: 286 + case CLS_AB_LP: 287 + case CLS_AB_LOHIFI: 288 + val = 0x04; 289 + break; 290 + default: 291 + dev_err(component->dev, "%s:Invalid mode %d\n", __func__, mode); 292 + return; 293 + } 294 + 295 + snd_soc_component_update_bits(component, WCD9XXX_ANA_HPH, 0x0C, val); 296 + } 297 + 298 + void wcd_clsh_set_hph_mode(struct wcd_clsh_ctrl *ctrl, int mode) 299 + { 300 + struct snd_soc_component *comp = ctrl->comp; 301 + 302 + if (ctrl->codec_version >= WCD937X) 303 + wcd_clsh_v3_set_hph_mode(comp, mode); 304 + else 305 + wcd_clsh_v2_set_hph_mode(comp, mode); 306 + 307 + } 308 + 323 309 static void wcd_clsh_set_flyback_current(struct snd_soc_component *comp, 324 310 int mode) 325 311 { ··· 385 287 snd_soc_component_update_bits(comp, WCD9XXX_A_ANA_RX_SUPPLIES, 386 288 WCD9XXX_A_ANA_RX_REGULATOR_MODE_MASK, 387 289 WCD9XXX_A_ANA_RX_REGULATOR_MODE_CLS_H); 290 + } 291 + 292 + static void wcd_clsh_v3_set_buck_regulator_mode(struct snd_soc_component *component, 293 + int mode) 294 + { 295 + snd_soc_component_update_bits(component, WCD9XXX_ANA_RX_SUPPLIES, 296 + 0x02, 0x00); 297 + } 298 + 299 + static void wcd_clsh_v3_set_flyback_mode(struct snd_soc_component *component, 300 + int mode) 301 + { 302 + if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI || 303 + mode == CLS_AB_HIFI || mode == CLS_AB_LOHIFI) { 304 + snd_soc_component_update_bits(component, 305 + WCD9XXX_ANA_RX_SUPPLIES, 306 + 0x04, 0x04); 307 + snd_soc_component_update_bits(component, 308 + WCD9XXX_FLYBACK_VNEG_CTRL_4, 309 + 0xF0, 0x80); 310 + } else { 311 + snd_soc_component_update_bits(component, 312 + WCD9XXX_ANA_RX_SUPPLIES, 313 + 0x04, 0x00); /* set to Default */ 314 + snd_soc_component_update_bits(component, 315 + WCD9XXX_FLYBACK_VNEG_CTRL_4, 316 + 0xF0, 0x70); 317 + } 318 + } 319 + 320 + static void wcd_clsh_v3_force_iq_ctl(struct snd_soc_component *component, 321 + int mode, bool enable) 322 + { 323 + if (enable) { 324 + snd_soc_component_update_bits(component, 325 + WCD9XXX_FLYBACK_VNEGDAC_CTRL_2, 326 + 0xE0, 0xA0); 327 + /* 100usec delay is needed as per HW requirement */ 328 + usleep_range(100, 110); 329 + snd_soc_component_update_bits(component, 330 + WCD9XXX_CLASSH_MODE_3, 331 + 0x02, 0x02); 332 + snd_soc_component_update_bits(component, 333 + WCD9XXX_CLASSH_MODE_2, 334 + 0xFF, 0x1C); 335 + if (mode == CLS_H_LOHIFI || mode == CLS_AB_LOHIFI) { 336 + snd_soc_component_update_bits(component, 337 + WCD9XXX_HPH_NEW_INT_PA_MISC2, 338 + 0x20, 0x20); 339 + snd_soc_component_update_bits(component, 340 + WCD9XXX_RX_BIAS_HPH_LOWPOWER, 341 + 0xF0, 0xC0); 342 + snd_soc_component_update_bits(component, 343 + WCD9XXX_HPH_PA_CTL1, 344 + 0x0E, 0x02); 345 + } 346 + } else { 347 + snd_soc_component_update_bits(component, 348 + WCD9XXX_HPH_NEW_INT_PA_MISC2, 349 + 0x20, 0x00); 350 + snd_soc_component_update_bits(component, 351 + WCD9XXX_RX_BIAS_HPH_LOWPOWER, 352 + 0xF0, 0x80); 353 + snd_soc_component_update_bits(component, 354 + WCD9XXX_HPH_PA_CTL1, 355 + 0x0E, 0x06); 356 + } 357 + } 358 + 359 + static void wcd_clsh_v3_flyback_ctrl(struct snd_soc_component *component, 360 + struct wcd_clsh_ctrl *ctrl, 361 + int mode, 362 + bool enable) 363 + { 364 + /* enable/disable flyback */ 365 + if ((enable && (++ctrl->flyback_users == 1)) || 366 + (!enable && (--ctrl->flyback_users == 0))) { 367 + snd_soc_component_update_bits(component, 368 + WCD9XXX_FLYBACK_VNEG_CTRL_1, 369 + 0xE0, 0xE0); 370 + snd_soc_component_update_bits(component, 371 + WCD9XXX_ANA_RX_SUPPLIES, 372 + (1 << 6), (enable << 6)); 373 + /* 374 + * 100us sleep is required after flyback enable/disable 375 + * as per HW requirement 376 + */ 377 + usleep_range(100, 110); 378 + snd_soc_component_update_bits(component, 379 + WCD9XXX_FLYBACK_VNEGDAC_CTRL_2, 380 + 0xE0, 0xE0); 381 + /* 500usec delay is needed as per HW requirement */ 382 + usleep_range(500, 500 + WCD_USLEEP_RANGE); 383 + } 384 + } 385 + 386 + static void wcd_clsh_v3_set_flyback_current(struct snd_soc_component *component, 387 + int mode) 388 + { 389 + snd_soc_component_update_bits(component, WCD9XXX_V3_RX_BIAS_FLYB_BUFF, 390 + 0x0F, 0x0A); 391 + snd_soc_component_update_bits(component, WCD9XXX_V3_RX_BIAS_FLYB_BUFF, 392 + 0xF0, 0xA0); 393 + /* Sleep needed to avoid click and pop as per HW requirement */ 394 + usleep_range(100, 110); 395 + } 396 + 397 + static void wcd_clsh_v3_state_aux(struct wcd_clsh_ctrl *ctrl, int req_state, 398 + bool is_enable, int mode) 399 + { 400 + struct snd_soc_component *component = ctrl->comp; 401 + 402 + if (is_enable) { 403 + wcd_clsh_v3_set_buck_mode(component, mode); 404 + wcd_clsh_v3_set_flyback_mode(component, mode); 405 + wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true); 406 + wcd_clsh_v3_set_flyback_current(component, mode); 407 + wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true); 408 + } else { 409 + wcd_clsh_v3_buck_ctrl(component, ctrl, mode, false); 410 + wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, false); 411 + wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL); 412 + wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL); 413 + } 388 414 } 389 415 390 416 static void wcd_clsh_state_lo(struct wcd_clsh_ctrl *ctrl, int req_state, ··· 535 313 wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); 536 314 wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); 537 315 wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); 316 + } 317 + } 318 + 319 + static void wcd_clsh_v3_state_hph_r(struct wcd_clsh_ctrl *ctrl, int req_state, 320 + bool is_enable, int mode) 321 + { 322 + struct snd_soc_component *component = ctrl->comp; 323 + 324 + if (mode == CLS_H_NORMAL) { 325 + dev_dbg(component->dev, "%s: Normal mode not applicable for hph_r\n", 326 + __func__); 327 + return; 328 + } 329 + 330 + if (is_enable) { 331 + wcd_clsh_v3_set_buck_regulator_mode(component, mode); 332 + wcd_clsh_v3_set_flyback_mode(component, mode); 333 + wcd_clsh_v3_force_iq_ctl(component, mode, true); 334 + wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true); 335 + wcd_clsh_v3_set_flyback_current(component, mode); 336 + wcd_clsh_v3_set_buck_mode(component, mode); 337 + wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true); 338 + wcd_clsh_v3_set_hph_mode(component, mode); 339 + } else { 340 + wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL); 341 + 342 + /* buck and flyback set to default mode and disable */ 343 + wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false); 344 + wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false); 345 + wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false); 346 + wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL); 347 + wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL); 538 348 } 539 349 } 540 350 ··· 607 353 wcd_clsh_set_flyback_current(comp, mode); 608 354 wcd_clsh_set_buck_mode(comp, mode); 609 355 wcd_clsh_buck_ctrl(ctrl, mode, true); 610 - wcd_clsh_set_hph_mode(comp, mode); 356 + wcd_clsh_v2_set_hph_mode(comp, mode); 611 357 wcd_clsh_set_gain_path(ctrl, mode); 612 358 } else { 613 - wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); 359 + wcd_clsh_v2_set_hph_mode(comp, CLS_H_NORMAL); 614 360 615 361 if (mode != CLS_AB) { 616 362 snd_soc_component_update_bits(comp, ··· 625 371 wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); 626 372 wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); 627 373 wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); 374 + } 375 + } 376 + 377 + static void wcd_clsh_v3_state_hph_l(struct wcd_clsh_ctrl *ctrl, int req_state, 378 + bool is_enable, int mode) 379 + { 380 + struct snd_soc_component *component = ctrl->comp; 381 + 382 + if (mode == CLS_H_NORMAL) { 383 + dev_dbg(component->dev, "%s: Normal mode not applicable for hph_l\n", 384 + __func__); 385 + return; 386 + } 387 + 388 + if (is_enable) { 389 + wcd_clsh_v3_set_buck_regulator_mode(component, mode); 390 + wcd_clsh_v3_set_flyback_mode(component, mode); 391 + wcd_clsh_v3_force_iq_ctl(component, mode, true); 392 + wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true); 393 + wcd_clsh_v3_set_flyback_current(component, mode); 394 + wcd_clsh_v3_set_buck_mode(component, mode); 395 + wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true); 396 + wcd_clsh_v3_set_hph_mode(component, mode); 397 + } else { 398 + wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL); 399 + 400 + /* set buck and flyback to Default Mode */ 401 + wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false); 402 + wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false); 403 + wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false); 404 + wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL); 405 + wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL); 628 406 } 629 407 } 630 408 ··· 697 411 wcd_clsh_set_flyback_current(comp, mode); 698 412 wcd_clsh_set_buck_mode(comp, mode); 699 413 wcd_clsh_buck_ctrl(ctrl, mode, true); 700 - wcd_clsh_set_hph_mode(comp, mode); 414 + wcd_clsh_v2_set_hph_mode(comp, mode); 701 415 wcd_clsh_set_gain_path(ctrl, mode); 702 416 } else { 703 - wcd_clsh_set_hph_mode(comp, CLS_H_NORMAL); 417 + wcd_clsh_v2_set_hph_mode(comp, CLS_H_NORMAL); 704 418 705 419 if (mode != CLS_AB) { 706 420 snd_soc_component_update_bits(comp, ··· 715 429 wcd_clsh_set_flyback_mode(comp, CLS_H_NORMAL); 716 430 wcd_clsh_set_buck_mode(comp, CLS_H_NORMAL); 717 431 wcd_clsh_set_buck_regulator_mode(comp, CLS_H_NORMAL); 432 + } 433 + } 434 + 435 + static void wcd_clsh_v3_state_ear(struct wcd_clsh_ctrl *ctrl, int req_state, 436 + bool is_enable, int mode) 437 + { 438 + struct snd_soc_component *component = ctrl->comp; 439 + 440 + if (is_enable) { 441 + wcd_clsh_v3_set_buck_regulator_mode(component, mode); 442 + wcd_clsh_v3_set_flyback_mode(component, mode); 443 + wcd_clsh_v3_force_iq_ctl(component, mode, true); 444 + wcd_clsh_v3_flyback_ctrl(component, ctrl, mode, true); 445 + wcd_clsh_v3_set_flyback_current(component, mode); 446 + wcd_clsh_v3_set_buck_mode(component, mode); 447 + wcd_clsh_v3_buck_ctrl(component, ctrl, mode, true); 448 + wcd_clsh_v3_set_hph_mode(component, mode); 449 + } else { 450 + wcd_clsh_v3_set_hph_mode(component, CLS_H_NORMAL); 451 + 452 + /* set buck and flyback to Default Mode */ 453 + wcd_clsh_v3_flyback_ctrl(component, ctrl, CLS_H_NORMAL, false); 454 + wcd_clsh_v3_buck_ctrl(component, ctrl, CLS_H_NORMAL, false); 455 + wcd_clsh_v3_force_iq_ctl(component, CLS_H_NORMAL, false); 456 + wcd_clsh_v3_set_flyback_mode(component, CLS_H_NORMAL); 457 + wcd_clsh_v3_set_buck_mode(component, CLS_H_NORMAL); 718 458 } 719 459 } 720 460 ··· 784 472 { 785 473 switch (req_state) { 786 474 case WCD_CLSH_STATE_EAR: 787 - wcd_clsh_state_ear(ctrl, req_state, is_enable, mode); 475 + if (ctrl->codec_version >= WCD937X) 476 + wcd_clsh_v3_state_ear(ctrl, req_state, is_enable, mode); 477 + else 478 + wcd_clsh_state_ear(ctrl, req_state, is_enable, mode); 788 479 break; 789 480 case WCD_CLSH_STATE_HPHL: 790 - wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode); 481 + if (ctrl->codec_version >= WCD937X) 482 + wcd_clsh_v3_state_hph_l(ctrl, req_state, is_enable, mode); 483 + else 484 + wcd_clsh_state_hph_l(ctrl, req_state, is_enable, mode); 791 485 break; 792 486 case WCD_CLSH_STATE_HPHR: 793 - wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode); 487 + if (ctrl->codec_version >= WCD937X) 488 + wcd_clsh_v3_state_hph_r(ctrl, req_state, is_enable, mode); 489 + else 490 + wcd_clsh_state_hph_r(ctrl, req_state, is_enable, mode); 794 491 break; 795 492 case WCD_CLSH_STATE_LO: 796 - wcd_clsh_state_lo(ctrl, req_state, is_enable, mode); 493 + if (ctrl->codec_version < WCD937X) 494 + wcd_clsh_state_lo(ctrl, req_state, is_enable, mode); 495 + break; 496 + case WCD_CLSH_STATE_AUX: 497 + if (ctrl->codec_version >= WCD937X) 498 + wcd_clsh_v3_state_aux(ctrl, req_state, is_enable, mode); 797 499 break; 798 500 default: 799 501 break; ··· 830 504 case WCD_CLSH_STATE_HPHL: 831 505 case WCD_CLSH_STATE_HPHR: 832 506 case WCD_CLSH_STATE_LO: 507 + case WCD_CLSH_STATE_AUX: 833 508 return true; 834 509 default: 835 510 return false; ··· 892 565 893 566 ctrl->state = WCD_CLSH_STATE_IDLE; 894 567 ctrl->comp = comp; 568 + ctrl->codec_version = version; 895 569 896 570 return ctrl; 897 571 }
+16
sound/soc/codecs/wcd-clsh-v2.h
··· 22 22 #define WCD_CLSH_STATE_HPHL BIT(1) 23 23 #define WCD_CLSH_STATE_HPHR BIT(2) 24 24 #define WCD_CLSH_STATE_LO BIT(3) 25 + #define WCD_CLSH_STATE_AUX BIT(4) 25 26 #define WCD_CLSH_STATE_MAX 4 27 + #define WCD_CLSH_V3_STATE_MAX 5 26 28 #define NUM_CLSH_STATES_V2 BIT(WCD_CLSH_STATE_MAX) 29 + #define NUM_CLSH_STATES_V3 BIT(WCD_CLSH_V3_STATE_MAX) 27 30 28 31 enum wcd_clsh_mode { 29 32 CLS_H_NORMAL = 0, /* Class-H Default */ ··· 34 31 CLS_H_LP, /* Class-H Low Power */ 35 32 CLS_AB, /* Class-AB */ 36 33 CLS_H_LOHIFI, /* LoHIFI */ 34 + CLS_H_ULP, /* Ultra Low power */ 35 + CLS_AB_HIFI, /* Class-AB */ 36 + CLS_AB_LP, /* Class-AB Low Power */ 37 + CLS_AB_LOHIFI, /* Class-AB Low HIFI */ 37 38 CLS_NONE, /* None of the above modes */ 38 39 }; 39 40 41 + enum wcd_codec_version { 42 + WCD9335 = 0, 43 + WCD934X = 1, 44 + /* New CLSH after this */ 45 + WCD937X = 2, 46 + WCD938X = 3, 47 + }; 40 48 struct wcd_clsh_ctrl; 41 49 42 50 extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc( ··· 59 45 enum wcd_clsh_event clsh_event, 60 46 int nstate, 61 47 enum wcd_clsh_mode mode); 48 + extern void wcd_clsh_set_hph_mode(struct wcd_clsh_ctrl *ctrl, 49 + int mode); 62 50 63 51 #endif /* _WCD_CLSH_V2_H_ */