1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * CM9825 HD-audio codec 4 */ 5 6 #include <linux/init.h> 7 #include <linux/slab.h> 8 #include <linux/module.h> 9 #include <sound/core.h> 10 #include <sound/hda_codec.h> 11 #include "hda_local.h" 12 #include "hda_auto_parser.h" 13 #include "hda_jack.h" 14 #include "generic.h" 15 16 enum { 17 QUIRK_CM_STD = 0x0, 18 QUIRK_GENE_TWL7_SSID = 0x160dc000 19 }; 20 21 /* CM9825 Offset Definitions */ 22 23 #define CM9825_VERB_SET_HPF_1 0x781 24 #define CM9825_VERB_SET_HPF_2 0x785 25 #define CM9825_VERB_SET_PLL 0x7a0 26 #define CM9825_VERB_SET_NEG 0x7a1 27 #define CM9825_VERB_SET_ADCL 0x7a2 28 #define CM9825_VERB_SET_DACL 0x7a3 29 #define CM9825_VERB_SET_MBIAS 0x7a4 30 #define CM9825_VERB_SET_VNEG 0x7a8 31 #define CM9825_VERB_SET_D2S 0x7a9 32 #define CM9825_VERB_SET_DACTRL 0x7aa 33 #define CM9825_VERB_SET_P3BCP 0x7ab 34 #define CM9825_VERB_SET_PDNEG 0x7ac 35 #define CM9825_VERB_SET_VDO 0x7ad 36 #define CM9825_VERB_SET_CDALR 0x7b0 37 #define CM9825_VERB_SET_MTCBA 0x7b1 38 #define CM9825_VERB_SET_OTP 0x7b2 39 #define CM9825_VERB_SET_OCP 0x7b3 40 #define CM9825_VERB_SET_GAD 0x7b4 41 #define CM9825_VERB_SET_TMOD 0x7b5 42 #define CM9825_VERB_SET_SNR 0x7b6 43 44 struct cmi_spec { 45 struct hda_gen_spec gen; 46 const struct hda_verb *chip_d0_verbs; 47 const struct hda_verb *chip_d3_verbs; 48 const struct hda_verb *chip_hp_present_verbs; 49 const struct hda_verb *chip_hp_remove_verbs; 50 struct hda_codec *codec; 51 struct delayed_work unsol_inputs_work; 52 struct delayed_work unsol_lineout_work; 53 struct delayed_work unsol_hp_work; 54 hda_nid_t jd_cap_hp; 55 hda_nid_t jd_cap_lineout; 56 hda_nid_t jd_cap_inputs[AUTO_CFG_MAX_INS]; 57 int quirk; 58 }; 59 60 static const struct hda_verb cm9825_std_d3_verbs[] = { 61 /* chip sleep verbs */ 62 {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */ 63 {0x43, CM9825_VERB_SET_PLL, 0x01}, /* PLL set */ 64 {0x43, CM9825_VERB_SET_NEG, 0xc2}, /* NEG set */ 65 {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */ 66 {0x43, CM9825_VERB_SET_DACL, 0x02}, /* DACL */ 67 {0x43, CM9825_VERB_SET_VNEG, 0x50}, /* VOL NEG */ 68 {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */ 69 {0x43, CM9825_VERB_SET_PDNEG, 0x04}, /* SEL OSC */ 70 {0x43, CM9825_VERB_SET_CDALR, 0xf6}, /* Class D */ 71 {0x43, CM9825_VERB_SET_OTP, 0xcd}, /* OTP set */ 72 {} 73 }; 74 75 static const struct hda_verb cm9825_std_d0_verbs[] = { 76 /* chip init verbs */ 77 {0x34, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, /* EAPD set */ 78 {0x43, CM9825_VERB_SET_SNR, 0x30}, /* SNR set */ 79 {0x43, CM9825_VERB_SET_PLL, 0x00}, /* PLL set */ 80 {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */ 81 {0x43, CM9825_VERB_SET_DACL, 0x02}, /* DACL */ 82 {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */ 83 {0x43, CM9825_VERB_SET_VNEG, 0x56}, /* VOL NEG */ 84 {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */ 85 {0x43, CM9825_VERB_SET_DACTRL, 0x00}, /* DACTRL set */ 86 {0x43, CM9825_VERB_SET_PDNEG, 0x0c}, /* SEL OSC */ 87 {0x43, CM9825_VERB_SET_VDO, 0x80}, /* VDO set */ 88 {0x43, CM9825_VERB_SET_CDALR, 0xf4}, /* Class D */ 89 {0x43, CM9825_VERB_SET_OTP, 0xcd}, /* OTP set */ 90 {0x43, CM9825_VERB_SET_MTCBA, 0x61}, /* SR set */ 91 {0x43, CM9825_VERB_SET_OCP, 0x33}, /* OTP set */ 92 {0x43, CM9825_VERB_SET_GAD, 0x07}, /* ADC -3db */ 93 {0x43, CM9825_VERB_SET_TMOD, 0x26}, /* Class D clk */ 94 {0x3C, AC_VERB_SET_AMP_GAIN_MUTE | 95 AC_AMP_SET_OUTPUT | AC_AMP_SET_RIGHT, 0x2d}, /* Gain set */ 96 {0x3C, AC_VERB_SET_AMP_GAIN_MUTE | 97 AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT, 0x2d}, /* Gain set */ 98 {0x43, CM9825_VERB_SET_HPF_1, 0x40}, /* HPF set */ 99 {0x43, CM9825_VERB_SET_HPF_2, 0x40}, /* HPF set */ 100 {} 101 }; 102 103 static const struct hda_verb cm9825_hp_present_verbs[] = { 104 {0x42, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00}, /* PIN off */ 105 {0x43, CM9825_VERB_SET_ADCL, 0x88}, /* ADC */ 106 {0x43, CM9825_VERB_SET_DACL, 0xaa}, /* DACL */ 107 {0x43, CM9825_VERB_SET_MBIAS, 0x10}, /* MBIAS */ 108 {0x43, CM9825_VERB_SET_D2S, 0xf2}, /* depop */ 109 {0x43, CM9825_VERB_SET_DACTRL, 0x00}, /* DACTRL set */ 110 {0x43, CM9825_VERB_SET_VDO, 0xc4}, /* VDO set */ 111 {} 112 }; 113 114 static const struct hda_verb cm9825_hp_remove_verbs[] = { 115 {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */ 116 {0x43, CM9825_VERB_SET_DACL, 0x56}, /* DACL */ 117 {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */ 118 {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */ 119 {0x43, CM9825_VERB_SET_DACTRL, 0xe0}, /* DACTRL set */ 120 {0x43, CM9825_VERB_SET_VDO, 0x80}, /* VDO set */ 121 {0x42, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, /* PIN on */ 122 {} 123 }; 124 125 /* 126 * To save power, AD/CLK is turned off. 127 */ 128 static const struct hda_verb cm9825_gene_twl7_d3_verbs[] = { 129 {0x43, CM9825_VERB_SET_D2S, 0x62}, 130 {0x43, CM9825_VERB_SET_PLL, 0x01}, 131 {0x43, CM9825_VERB_SET_NEG, 0xc2}, 132 {0x43, CM9825_VERB_SET_ADCL, 0x00}, 133 {0x43, CM9825_VERB_SET_DACL, 0x02}, 134 {0x43, CM9825_VERB_SET_MBIAS, 0x00}, 135 {0x43, CM9825_VERB_SET_VNEG, 0x50}, 136 {0x43, CM9825_VERB_SET_PDNEG, 0x04}, 137 {0x43, CM9825_VERB_SET_CDALR, 0xf6}, 138 {0x43, CM9825_VERB_SET_OTP, 0xcd}, 139 {} 140 }; 141 142 /* 143 * These settings are required to properly enable the PLL, clock, ADC and 144 * DAC paths, and to select the correct analog input routing. Without 145 * these explicit configurations, the ADC does not start correctly and 146 * recording does not work reliably on this hardware. 147 * 148 * D0 configuration: enable PLL/CLK/ADC/DAC and optimize performance 149 */ 150 static const struct hda_verb cm9825_gene_twl7_d0_verbs[] = { 151 {0x34, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, 152 {0x43, CM9825_VERB_SET_SNR, 0x38}, 153 {0x43, CM9825_VERB_SET_PLL, 0x00}, 154 {0x43, CM9825_VERB_SET_ADCL, 0xcf}, 155 {0x43, CM9825_VERB_SET_DACL, 0xaa}, 156 {0x43, CM9825_VERB_SET_MBIAS, 0x1c}, 157 {0x43, CM9825_VERB_SET_VNEG, 0x56}, 158 {0x43, CM9825_VERB_SET_D2S, 0x62}, 159 {0x43, CM9825_VERB_SET_DACTRL, 0x00}, 160 {0x43, CM9825_VERB_SET_PDNEG, 0x0c}, 161 {0x43, CM9825_VERB_SET_CDALR, 0xf4}, 162 {0x43, CM9825_VERB_SET_OTP, 0xcd}, 163 {0x43, CM9825_VERB_SET_MTCBA, 0x61}, 164 {0x43, CM9825_VERB_SET_OCP, 0x33}, 165 {0x43, CM9825_VERB_SET_GAD, 0x07}, 166 {0x43, CM9825_VERB_SET_TMOD, 0x26}, 167 {0x43, CM9825_VERB_SET_HPF_1, 0x40}, 168 {0x43, CM9825_VERB_SET_HPF_2, 0x40}, 169 {0x40, AC_VERB_SET_CONNECT_SEL, 0x00}, 170 {0x3d, AC_VERB_SET_CONNECT_SEL, 0x01}, 171 {0x46, CM9825_VERB_SET_P3BCP, 0x20}, 172 {} 173 }; 174 175 /* 176 * Enable DAC to start playback. 177 */ 178 static const struct hda_verb cm9825_gene_twl7_playback_start_verbs[] = { 179 {0x43, CM9825_VERB_SET_D2S, 0xf2}, 180 {0x43, CM9825_VERB_SET_VDO, 0xd4}, 181 {0x43, CM9825_VERB_SET_SNR, 0x30}, 182 {} 183 }; 184 185 /* 186 * Disable DAC and enable de-pop noise mechanism. 187 */ 188 static const struct hda_verb cm9825_gene_twl7_playback_stop_verbs[] = { 189 {0x43, CM9825_VERB_SET_VDO, 0xc0}, 190 {0x43, CM9825_VERB_SET_D2S, 0x62}, 191 {0x43, CM9825_VERB_SET_VDO, 0xd0}, 192 {0x43, CM9825_VERB_SET_SNR, 0x38}, 193 {} 194 }; 195 196 static void cm9825_update_jk_plug_status(struct hda_codec *codec, hda_nid_t nid) 197 { 198 struct cmi_spec *spec = codec->spec; 199 bool jack_plugin; 200 struct hda_jack_tbl *jack; 201 202 jack_plugin = snd_hda_jack_detect(spec->codec, nid); 203 jack = snd_hda_jack_tbl_get(spec->codec, nid); 204 if (jack) { 205 jack->block_report = 0; 206 snd_hda_jack_report_sync(spec->codec); 207 } 208 209 codec_dbg(spec->codec, 210 "%s, jack_plugin %d, nid 0x%X, line%d\n", 211 __func__, (int)jack_plugin, nid, __LINE__); 212 } 213 214 static void cm9825_unsol_inputs_delayed(struct work_struct *work) 215 { 216 struct cmi_spec *spec = 217 container_of(to_delayed_work(work), struct cmi_spec, 218 unsol_inputs_work); 219 int i; 220 221 for (i = 0; i < spec->gen.autocfg.num_inputs; i++) { 222 if (!spec->jd_cap_inputs[i]) 223 continue; 224 225 cm9825_update_jk_plug_status(spec->codec, 226 spec->gen.autocfg.inputs[i].pin); 227 } 228 } 229 230 static void cm9825_unsol_lineout_delayed(struct work_struct *work) 231 { 232 struct cmi_spec *spec = 233 container_of(to_delayed_work(work), struct cmi_spec, 234 unsol_lineout_work); 235 236 cm9825_update_jk_plug_status(spec->codec, 237 spec->gen.autocfg.line_out_pins[0]); 238 } 239 240 static void cm9825_unsol_hp_delayed(struct work_struct *work) 241 { 242 struct cmi_spec *spec = 243 container_of(to_delayed_work(work), struct cmi_spec, unsol_hp_work); 244 struct hda_jack_tbl *jack; 245 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; 246 bool hp_jack_plugin = false; 247 int err = 0; 248 249 hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin); 250 251 codec_dbg(spec->codec, "hp_jack_plugin %d, hp_pin 0x%X\n", 252 (int)hp_jack_plugin, hp_pin); 253 254 if (!hp_jack_plugin) { 255 err = 256 snd_hda_codec_write(spec->codec, 0x42, 0, 257 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40); 258 if (err) 259 codec_dbg(spec->codec, "codec_write err %d\n", err); 260 261 snd_hda_sequence_write(spec->codec, spec->chip_hp_remove_verbs); 262 } else { 263 snd_hda_sequence_write(spec->codec, 264 spec->chip_hp_present_verbs); 265 } 266 267 jack = snd_hda_jack_tbl_get(spec->codec, hp_pin); 268 if (jack) { 269 jack->block_report = 0; 270 snd_hda_jack_report_sync(spec->codec); 271 } 272 } 273 274 static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) 275 { 276 struct cmi_spec *spec = codec->spec; 277 struct hda_jack_tbl *tbl; 278 279 /* Delay enabling the HP amp, to let the mic-detection 280 * state machine run. 281 */ 282 283 codec_dbg(spec->codec, "cb->nid 0x%X\n", cb->nid); 284 285 tbl = snd_hda_jack_tbl_get(codec, cb->nid); 286 if (tbl) 287 tbl->block_report = 1; 288 289 if (cb->nid == spec->jd_cap_hp) 290 schedule_delayed_work(&spec->unsol_hp_work, 291 msecs_to_jiffies(200)); 292 else if (cb->nid == spec->jd_cap_lineout) 293 schedule_delayed_work(&spec->unsol_lineout_work, 294 msecs_to_jiffies(200)); 295 296 for (int i = 0; i < spec->gen.autocfg.num_inputs; i++) { 297 if (cb->nid == spec->jd_cap_inputs[i]) 298 schedule_delayed_work(&spec->unsol_inputs_work, 299 msecs_to_jiffies(200)); 300 } 301 } 302 303 static void cm9825_setup_unsol(struct hda_codec *codec) 304 { 305 struct cmi_spec *spec = codec->spec; 306 int i; 307 308 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; 309 310 hda_nid_t lineout_pin = spec->gen.autocfg.line_out_pins[0]; 311 312 if (hp_pin != 0) { 313 if (is_jack_detectable(codec, hp_pin)) { 314 spec->jd_cap_hp = hp_pin; 315 snd_hda_jack_detect_enable_callback(codec, hp_pin, 316 hp_callback); 317 } else 318 spec->jd_cap_hp = 0; 319 } else 320 spec->jd_cap_hp = 0; 321 322 if (lineout_pin != 0) { 323 if (is_jack_detectable(codec, lineout_pin)) { 324 spec->jd_cap_lineout = lineout_pin; 325 snd_hda_jack_detect_enable_callback(codec, lineout_pin, 326 hp_callback); 327 } else 328 spec->jd_cap_lineout = 0; 329 } else 330 spec->jd_cap_lineout = 0; 331 332 codec_dbg(codec, 333 "%s, jd_cap_hp 0x%02X, jd_cap_lineout 0x%02X, line%d\n", 334 __func__, spec->jd_cap_hp, spec->jd_cap_lineout, __LINE__); 335 336 for (i = 0; i < spec->gen.autocfg.num_inputs; i++) { 337 if (spec->gen.autocfg.inputs[i].pin != 0) { 338 if (is_jack_detectable 339 (codec, spec->gen.autocfg.inputs[i].pin)) { 340 spec->jd_cap_inputs[i] = 341 spec->gen.autocfg.inputs[i].pin; 342 snd_hda_jack_detect_enable_callback(codec, 343 spec->gen.autocfg.inputs[i].pin, 344 hp_callback); 345 } else 346 spec->jd_cap_inputs[i] = 0; 347 } else 348 spec->jd_cap_inputs[i] = 0; 349 350 codec_dbg(codec, 351 "%s, input jd_cap_inputs[%d] 0x%02X, line%d\n", 352 __func__, i, spec->jd_cap_inputs[i], __LINE__); 353 } 354 } 355 356 static void cm9825_playback_pcm_hook(struct hda_pcm_stream *hinfo, 357 struct hda_codec *codec, 358 struct snd_pcm_substream *substream, 359 int action) 360 { 361 struct cmi_spec *spec = codec->spec; 362 363 switch (action) { 364 case HDA_GEN_PCM_ACT_PREPARE: 365 snd_hda_sequence_write(spec->codec, 366 cm9825_gene_twl7_playback_start_verbs); 367 break; 368 case HDA_GEN_PCM_ACT_CLEANUP: 369 snd_hda_sequence_write(spec->codec, 370 cm9825_gene_twl7_playback_stop_verbs); 371 break; 372 default: 373 return; 374 } 375 } 376 377 static int cm9825_init(struct hda_codec *codec) 378 { 379 snd_hda_gen_init(codec); 380 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); 381 382 return 0; 383 } 384 385 static void cm9825_remove(struct hda_codec *codec) 386 { 387 struct cmi_spec *spec = codec->spec; 388 int i; 389 390 if (spec->jd_cap_hp) 391 cancel_delayed_work_sync(&spec->unsol_hp_work); 392 393 if (spec->jd_cap_lineout) 394 cancel_delayed_work_sync(&spec->unsol_lineout_work); 395 396 for (i = 0; i < spec->gen.autocfg.num_inputs; i++) { 397 if (spec->jd_cap_inputs[i]) { 398 cancel_delayed_work_sync(&spec->unsol_inputs_work); 399 break; 400 } 401 } 402 403 snd_hda_gen_remove(codec); 404 } 405 406 static int cm9825_suspend(struct hda_codec *codec) 407 { 408 struct cmi_spec *spec = codec->spec; 409 int i; 410 411 if (spec->jd_cap_hp) 412 cancel_delayed_work_sync(&spec->unsol_hp_work); 413 414 if (spec->jd_cap_lineout) 415 cancel_delayed_work_sync(&spec->unsol_lineout_work); 416 417 for (i = 0; i < spec->gen.autocfg.num_inputs; i++) { 418 if (spec->jd_cap_inputs[i]) { 419 cancel_delayed_work_sync(&spec->unsol_inputs_work); 420 break; 421 } 422 } 423 424 snd_hda_sequence_write(codec, spec->chip_d3_verbs); 425 426 return 0; 427 } 428 429 static int cm9825_cm_std_resume(struct hda_codec *codec) 430 { 431 struct cmi_spec *spec = codec->spec; 432 hda_nid_t hp_pin = 0; 433 bool hp_jack_plugin = false; 434 int err; 435 436 err = 437 snd_hda_codec_write(spec->codec, 0x42, 0, 438 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00); 439 if (err) 440 codec_dbg(codec, "codec_write err %d\n", err); 441 442 msleep(150); /* for depop noise */ 443 444 snd_hda_codec_init(codec); 445 446 snd_hda_sequence_write(codec, spec->chip_d0_verbs); 447 448 hp_pin = spec->gen.autocfg.hp_pins[0]; 449 hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin); 450 451 codec_dbg(spec->codec, "hp_jack_plugin %d, hp_pin 0x%X\n", 452 (int)hp_jack_plugin, hp_pin); 453 454 if (!hp_jack_plugin) { 455 err = 456 snd_hda_codec_write(spec->codec, 0x42, 0, 457 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40); 458 459 if (err) 460 codec_dbg(codec, "codec_write err %d\n", err); 461 462 snd_hda_sequence_write(codec, cm9825_hp_remove_verbs); 463 } 464 465 return 0; 466 } 467 468 static int cm9825_resume(struct hda_codec *codec) 469 { 470 struct cmi_spec *spec = codec->spec; 471 472 if (codec->core.subsystem_id == QUIRK_CM_STD) 473 cm9825_cm_std_resume(codec); 474 else if (codec->core.subsystem_id == QUIRK_GENE_TWL7_SSID) { 475 snd_hda_codec_init(codec); 476 snd_hda_sequence_write(codec, spec->chip_d0_verbs); 477 } 478 479 snd_hda_regmap_sync(codec); 480 hda_call_check_power_status(codec, 0x01); 481 482 return 0; 483 } 484 485 static int cm9825_probe(struct hda_codec *codec, const struct hda_device_id *id) 486 { 487 struct cmi_spec *spec; 488 struct auto_pin_cfg *cfg; 489 int err = 0; 490 491 spec = kzalloc_obj(*spec); 492 if (spec == NULL) 493 return -ENOMEM; 494 495 codec_dbg(codec, "chip_name: %s, ssid: 0x%X\n", 496 codec->core.chip_name, codec->core.subsystem_id); 497 498 codec->spec = spec; 499 spec->codec = codec; 500 cfg = &spec->gen.autocfg; 501 snd_hda_gen_spec_init(&spec->gen); 502 spec->chip_d0_verbs = cm9825_std_d0_verbs; 503 spec->chip_d3_verbs = cm9825_std_d3_verbs; 504 spec->chip_hp_present_verbs = cm9825_hp_present_verbs; 505 spec->chip_hp_remove_verbs = cm9825_hp_remove_verbs; 506 507 INIT_DELAYED_WORK(&spec->unsol_hp_work, cm9825_unsol_hp_delayed); 508 INIT_DELAYED_WORK(&spec->unsol_inputs_work, 509 cm9825_unsol_inputs_delayed); 510 INIT_DELAYED_WORK(&spec->unsol_lineout_work, 511 cm9825_unsol_lineout_delayed); 512 513 switch (codec->core.subsystem_id) { 514 case QUIRK_CM_STD: 515 snd_hda_codec_set_name(codec, "CM9825 STD"); 516 spec->chip_d0_verbs = cm9825_std_d0_verbs; 517 spec->chip_d3_verbs = cm9825_std_d3_verbs; 518 spec->chip_hp_present_verbs = cm9825_hp_present_verbs; 519 spec->chip_hp_remove_verbs = cm9825_hp_remove_verbs; 520 break; 521 case QUIRK_GENE_TWL7_SSID: 522 snd_hda_codec_set_name(codec, "CM9825 GENE_TWL7"); 523 spec->chip_d0_verbs = cm9825_gene_twl7_d0_verbs; 524 spec->chip_d3_verbs = cm9825_gene_twl7_d3_verbs; 525 spec->gen.pcm_playback_hook = cm9825_playback_pcm_hook; 526 /* Internal fixed device, Rear, Mic-in, 3.5mm */ 527 snd_hda_codec_set_pincfg(codec, 0x37, 0x24A70100); 528 break; 529 default: 530 err = -ENXIO; 531 break; 532 } 533 534 if (err < 0) 535 goto error; 536 537 snd_hda_sequence_write(codec, spec->chip_d0_verbs); 538 539 err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); 540 if (err < 0) 541 goto error; 542 err = snd_hda_gen_parse_auto_config(codec, cfg); 543 if (err < 0) 544 goto error; 545 546 cm9825_setup_unsol(codec); 547 548 return 0; 549 550 error: 551 cm9825_remove(codec); 552 553 codec_info(codec, "Enter err %d\n", err); 554 555 return err; 556 } 557 558 static const struct hda_codec_ops cm9825_codec_ops = { 559 .probe = cm9825_probe, 560 .remove = cm9825_remove, 561 .build_controls = snd_hda_gen_build_controls, 562 .build_pcms = snd_hda_gen_build_pcms, 563 .init = cm9825_init, 564 .unsol_event = snd_hda_jack_unsol_event, 565 .suspend = cm9825_suspend, 566 .resume = cm9825_resume, 567 .check_power_status = snd_hda_gen_check_power_status, 568 .stream_pm = snd_hda_gen_stream_pm, 569 }; 570 571 /* 572 * driver entries 573 */ 574 static const struct hda_device_id snd_hda_id_cm9825[] = { 575 HDA_CODEC_ID(0x13f69825, "CM9825"), 576 {} /* terminator */ 577 }; 578 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cm9825); 579 580 MODULE_LICENSE("GPL"); 581 MODULE_DESCRIPTION("CM9825 HD-audio codec"); 582 583 static struct hda_codec_driver cm9825_driver = { 584 .id = snd_hda_id_cm9825, 585 .ops = &cm9825_codec_ops, 586 }; 587 588 module_hda_codec_driver(cm9825_driver); 589