1*0f1e8306STakashi Iwai // SPDX-License-Identifier: GPL-2.0-or-later 2*0f1e8306STakashi Iwai /* 3*0f1e8306STakashi Iwai * CM9825 HD-audio codec 4*0f1e8306STakashi Iwai */ 5*0f1e8306STakashi Iwai 6*0f1e8306STakashi Iwai #include <linux/init.h> 7*0f1e8306STakashi Iwai #include <linux/slab.h> 8*0f1e8306STakashi Iwai #include <linux/module.h> 9*0f1e8306STakashi Iwai #include <sound/core.h> 10*0f1e8306STakashi Iwai #include <sound/hda_codec.h> 11*0f1e8306STakashi Iwai #include "hda_local.h" 12*0f1e8306STakashi Iwai #include "hda_auto_parser.h" 13*0f1e8306STakashi Iwai #include "hda_jack.h" 14*0f1e8306STakashi Iwai #include "generic.h" 15*0f1e8306STakashi Iwai 16*0f1e8306STakashi Iwai /* CM9825 Offset Definitions */ 17*0f1e8306STakashi Iwai 18*0f1e8306STakashi Iwai #define CM9825_VERB_SET_HPF_1 0x781 19*0f1e8306STakashi Iwai #define CM9825_VERB_SET_HPF_2 0x785 20*0f1e8306STakashi Iwai #define CM9825_VERB_SET_PLL 0x7a0 21*0f1e8306STakashi Iwai #define CM9825_VERB_SET_NEG 0x7a1 22*0f1e8306STakashi Iwai #define CM9825_VERB_SET_ADCL 0x7a2 23*0f1e8306STakashi Iwai #define CM9825_VERB_SET_DACL 0x7a3 24*0f1e8306STakashi Iwai #define CM9825_VERB_SET_MBIAS 0x7a4 25*0f1e8306STakashi Iwai #define CM9825_VERB_SET_VNEG 0x7a8 26*0f1e8306STakashi Iwai #define CM9825_VERB_SET_D2S 0x7a9 27*0f1e8306STakashi Iwai #define CM9825_VERB_SET_DACTRL 0x7aa 28*0f1e8306STakashi Iwai #define CM9825_VERB_SET_PDNEG 0x7ac 29*0f1e8306STakashi Iwai #define CM9825_VERB_SET_VDO 0x7ad 30*0f1e8306STakashi Iwai #define CM9825_VERB_SET_CDALR 0x7b0 31*0f1e8306STakashi Iwai #define CM9825_VERB_SET_MTCBA 0x7b1 32*0f1e8306STakashi Iwai #define CM9825_VERB_SET_OTP 0x7b2 33*0f1e8306STakashi Iwai #define CM9825_VERB_SET_OCP 0x7b3 34*0f1e8306STakashi Iwai #define CM9825_VERB_SET_GAD 0x7b4 35*0f1e8306STakashi Iwai #define CM9825_VERB_SET_TMOD 0x7b5 36*0f1e8306STakashi Iwai #define CM9825_VERB_SET_SNR 0x7b6 37*0f1e8306STakashi Iwai 38*0f1e8306STakashi Iwai struct cmi_spec { 39*0f1e8306STakashi Iwai struct hda_gen_spec gen; 40*0f1e8306STakashi Iwai const struct hda_verb *chip_d0_verbs; 41*0f1e8306STakashi Iwai const struct hda_verb *chip_d3_verbs; 42*0f1e8306STakashi Iwai const struct hda_verb *chip_hp_present_verbs; 43*0f1e8306STakashi Iwai const struct hda_verb *chip_hp_remove_verbs; 44*0f1e8306STakashi Iwai struct hda_codec *codec; 45*0f1e8306STakashi Iwai struct delayed_work unsol_hp_work; 46*0f1e8306STakashi Iwai int quirk; 47*0f1e8306STakashi Iwai }; 48*0f1e8306STakashi Iwai 49*0f1e8306STakashi Iwai static const struct hda_verb cm9825_std_d3_verbs[] = { 50*0f1e8306STakashi Iwai /* chip sleep verbs */ 51*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */ 52*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_PLL, 0x01}, /* PLL set */ 53*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_NEG, 0xc2}, /* NEG set */ 54*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */ 55*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACL, 0x02}, /* DACL */ 56*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_VNEG, 0x50}, /* VOL NEG */ 57*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */ 58*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_PDNEG, 0x04}, /* SEL OSC */ 59*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_CDALR, 0xf6}, /* Class D */ 60*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_OTP, 0xcd}, /* OTP set */ 61*0f1e8306STakashi Iwai {} 62*0f1e8306STakashi Iwai }; 63*0f1e8306STakashi Iwai 64*0f1e8306STakashi Iwai static const struct hda_verb cm9825_std_d0_verbs[] = { 65*0f1e8306STakashi Iwai /* chip init verbs */ 66*0f1e8306STakashi Iwai {0x34, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, /* EAPD set */ 67*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_SNR, 0x30}, /* SNR set */ 68*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_PLL, 0x00}, /* PLL set */ 69*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */ 70*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACL, 0x02}, /* DACL */ 71*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */ 72*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_VNEG, 0x56}, /* VOL NEG */ 73*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */ 74*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACTRL, 0x00}, /* DACTRL set */ 75*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_PDNEG, 0x0c}, /* SEL OSC */ 76*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_VDO, 0x80}, /* VDO set */ 77*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_CDALR, 0xf4}, /* Class D */ 78*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_OTP, 0xcd}, /* OTP set */ 79*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_MTCBA, 0x61}, /* SR set */ 80*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_OCP, 0x33}, /* OTP set */ 81*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_GAD, 0x07}, /* ADC -3db */ 82*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_TMOD, 0x26}, /* Class D clk */ 83*0f1e8306STakashi Iwai {0x3C, AC_VERB_SET_AMP_GAIN_MUTE | 84*0f1e8306STakashi Iwai AC_AMP_SET_OUTPUT | AC_AMP_SET_RIGHT, 0x2d}, /* Gain set */ 85*0f1e8306STakashi Iwai {0x3C, AC_VERB_SET_AMP_GAIN_MUTE | 86*0f1e8306STakashi Iwai AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT, 0x2d}, /* Gain set */ 87*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_HPF_1, 0x40}, /* HPF set */ 88*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_HPF_2, 0x40}, /* HPF set */ 89*0f1e8306STakashi Iwai {} 90*0f1e8306STakashi Iwai }; 91*0f1e8306STakashi Iwai 92*0f1e8306STakashi Iwai static const struct hda_verb cm9825_hp_present_verbs[] = { 93*0f1e8306STakashi Iwai {0x42, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00}, /* PIN off */ 94*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_ADCL, 0x88}, /* ADC */ 95*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACL, 0xaa}, /* DACL */ 96*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_MBIAS, 0x10}, /* MBIAS */ 97*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_D2S, 0xf2}, /* depop */ 98*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACTRL, 0x00}, /* DACTRL set */ 99*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_VDO, 0xc4}, /* VDO set */ 100*0f1e8306STakashi Iwai {} 101*0f1e8306STakashi Iwai }; 102*0f1e8306STakashi Iwai 103*0f1e8306STakashi Iwai static const struct hda_verb cm9825_hp_remove_verbs[] = { 104*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_ADCL, 0x00}, /* ADC */ 105*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACL, 0x56}, /* DACL */ 106*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_MBIAS, 0x00}, /* MBIAS */ 107*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_D2S, 0x62}, /* depop */ 108*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_DACTRL, 0xe0}, /* DACTRL set */ 109*0f1e8306STakashi Iwai {0x43, CM9825_VERB_SET_VDO, 0x80}, /* VDO set */ 110*0f1e8306STakashi Iwai {0x42, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, /* PIN on */ 111*0f1e8306STakashi Iwai {} 112*0f1e8306STakashi Iwai }; 113*0f1e8306STakashi Iwai 114*0f1e8306STakashi Iwai static void cm9825_unsol_hp_delayed(struct work_struct *work) 115*0f1e8306STakashi Iwai { 116*0f1e8306STakashi Iwai struct cmi_spec *spec = 117*0f1e8306STakashi Iwai container_of(to_delayed_work(work), struct cmi_spec, unsol_hp_work); 118*0f1e8306STakashi Iwai struct hda_jack_tbl *jack; 119*0f1e8306STakashi Iwai hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; 120*0f1e8306STakashi Iwai bool hp_jack_plugin = false; 121*0f1e8306STakashi Iwai int err = 0; 122*0f1e8306STakashi Iwai 123*0f1e8306STakashi Iwai hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin); 124*0f1e8306STakashi Iwai 125*0f1e8306STakashi Iwai codec_dbg(spec->codec, "hp_jack_plugin %d, hp_pin 0x%X\n", 126*0f1e8306STakashi Iwai (int)hp_jack_plugin, hp_pin); 127*0f1e8306STakashi Iwai 128*0f1e8306STakashi Iwai if (!hp_jack_plugin) { 129*0f1e8306STakashi Iwai err = 130*0f1e8306STakashi Iwai snd_hda_codec_write(spec->codec, 0x42, 0, 131*0f1e8306STakashi Iwai AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40); 132*0f1e8306STakashi Iwai if (err) 133*0f1e8306STakashi Iwai codec_dbg(spec->codec, "codec_write err %d\n", err); 134*0f1e8306STakashi Iwai 135*0f1e8306STakashi Iwai snd_hda_sequence_write(spec->codec, spec->chip_hp_remove_verbs); 136*0f1e8306STakashi Iwai } else { 137*0f1e8306STakashi Iwai snd_hda_sequence_write(spec->codec, 138*0f1e8306STakashi Iwai spec->chip_hp_present_verbs); 139*0f1e8306STakashi Iwai } 140*0f1e8306STakashi Iwai 141*0f1e8306STakashi Iwai jack = snd_hda_jack_tbl_get(spec->codec, hp_pin); 142*0f1e8306STakashi Iwai if (jack) { 143*0f1e8306STakashi Iwai jack->block_report = 0; 144*0f1e8306STakashi Iwai snd_hda_jack_report_sync(spec->codec); 145*0f1e8306STakashi Iwai } 146*0f1e8306STakashi Iwai } 147*0f1e8306STakashi Iwai 148*0f1e8306STakashi Iwai static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) 149*0f1e8306STakashi Iwai { 150*0f1e8306STakashi Iwai struct cmi_spec *spec = codec->spec; 151*0f1e8306STakashi Iwai struct hda_jack_tbl *tbl; 152*0f1e8306STakashi Iwai 153*0f1e8306STakashi Iwai /* Delay enabling the HP amp, to let the mic-detection 154*0f1e8306STakashi Iwai * state machine run. 155*0f1e8306STakashi Iwai */ 156*0f1e8306STakashi Iwai 157*0f1e8306STakashi Iwai codec_dbg(spec->codec, "cb->nid 0x%X\n", cb->nid); 158*0f1e8306STakashi Iwai 159*0f1e8306STakashi Iwai tbl = snd_hda_jack_tbl_get(codec, cb->nid); 160*0f1e8306STakashi Iwai if (tbl) 161*0f1e8306STakashi Iwai tbl->block_report = 1; 162*0f1e8306STakashi Iwai schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(200)); 163*0f1e8306STakashi Iwai } 164*0f1e8306STakashi Iwai 165*0f1e8306STakashi Iwai static void cm9825_setup_unsol(struct hda_codec *codec) 166*0f1e8306STakashi Iwai { 167*0f1e8306STakashi Iwai struct cmi_spec *spec = codec->spec; 168*0f1e8306STakashi Iwai 169*0f1e8306STakashi Iwai hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; 170*0f1e8306STakashi Iwai 171*0f1e8306STakashi Iwai snd_hda_jack_detect_enable_callback(codec, hp_pin, hp_callback); 172*0f1e8306STakashi Iwai } 173*0f1e8306STakashi Iwai 174*0f1e8306STakashi Iwai static int cm9825_init(struct hda_codec *codec) 175*0f1e8306STakashi Iwai { 176*0f1e8306STakashi Iwai snd_hda_gen_init(codec); 177*0f1e8306STakashi Iwai snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); 178*0f1e8306STakashi Iwai 179*0f1e8306STakashi Iwai return 0; 180*0f1e8306STakashi Iwai } 181*0f1e8306STakashi Iwai 182*0f1e8306STakashi Iwai static void cm9825_remove(struct hda_codec *codec) 183*0f1e8306STakashi Iwai { 184*0f1e8306STakashi Iwai struct cmi_spec *spec = codec->spec; 185*0f1e8306STakashi Iwai 186*0f1e8306STakashi Iwai cancel_delayed_work_sync(&spec->unsol_hp_work); 187*0f1e8306STakashi Iwai snd_hda_gen_remove(codec); 188*0f1e8306STakashi Iwai } 189*0f1e8306STakashi Iwai 190*0f1e8306STakashi Iwai static int cm9825_suspend(struct hda_codec *codec) 191*0f1e8306STakashi Iwai { 192*0f1e8306STakashi Iwai struct cmi_spec *spec = codec->spec; 193*0f1e8306STakashi Iwai 194*0f1e8306STakashi Iwai cancel_delayed_work_sync(&spec->unsol_hp_work); 195*0f1e8306STakashi Iwai 196*0f1e8306STakashi Iwai snd_hda_sequence_write(codec, spec->chip_d3_verbs); 197*0f1e8306STakashi Iwai 198*0f1e8306STakashi Iwai return 0; 199*0f1e8306STakashi Iwai } 200*0f1e8306STakashi Iwai 201*0f1e8306STakashi Iwai static int cm9825_resume(struct hda_codec *codec) 202*0f1e8306STakashi Iwai { 203*0f1e8306STakashi Iwai struct cmi_spec *spec = codec->spec; 204*0f1e8306STakashi Iwai hda_nid_t hp_pin = 0; 205*0f1e8306STakashi Iwai bool hp_jack_plugin = false; 206*0f1e8306STakashi Iwai int err; 207*0f1e8306STakashi Iwai 208*0f1e8306STakashi Iwai err = 209*0f1e8306STakashi Iwai snd_hda_codec_write(spec->codec, 0x42, 0, 210*0f1e8306STakashi Iwai AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00); 211*0f1e8306STakashi Iwai if (err) 212*0f1e8306STakashi Iwai codec_dbg(codec, "codec_write err %d\n", err); 213*0f1e8306STakashi Iwai 214*0f1e8306STakashi Iwai msleep(150); /* for depop noise */ 215*0f1e8306STakashi Iwai 216*0f1e8306STakashi Iwai snd_hda_codec_init(codec); 217*0f1e8306STakashi Iwai 218*0f1e8306STakashi Iwai hp_pin = spec->gen.autocfg.hp_pins[0]; 219*0f1e8306STakashi Iwai hp_jack_plugin = snd_hda_jack_detect(spec->codec, hp_pin); 220*0f1e8306STakashi Iwai 221*0f1e8306STakashi Iwai codec_dbg(spec->codec, "hp_jack_plugin %d, hp_pin 0x%X\n", 222*0f1e8306STakashi Iwai (int)hp_jack_plugin, hp_pin); 223*0f1e8306STakashi Iwai 224*0f1e8306STakashi Iwai if (!hp_jack_plugin) { 225*0f1e8306STakashi Iwai err = 226*0f1e8306STakashi Iwai snd_hda_codec_write(spec->codec, 0x42, 0, 227*0f1e8306STakashi Iwai AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40); 228*0f1e8306STakashi Iwai 229*0f1e8306STakashi Iwai if (err) 230*0f1e8306STakashi Iwai codec_dbg(codec, "codec_write err %d\n", err); 231*0f1e8306STakashi Iwai 232*0f1e8306STakashi Iwai snd_hda_sequence_write(codec, cm9825_hp_remove_verbs); 233*0f1e8306STakashi Iwai } 234*0f1e8306STakashi Iwai 235*0f1e8306STakashi Iwai snd_hda_regmap_sync(codec); 236*0f1e8306STakashi Iwai hda_call_check_power_status(codec, 0x01); 237*0f1e8306STakashi Iwai 238*0f1e8306STakashi Iwai return 0; 239*0f1e8306STakashi Iwai } 240*0f1e8306STakashi Iwai 241*0f1e8306STakashi Iwai static int cm9825_probe(struct hda_codec *codec, const struct hda_device_id *id) 242*0f1e8306STakashi Iwai { 243*0f1e8306STakashi Iwai struct cmi_spec *spec; 244*0f1e8306STakashi Iwai struct auto_pin_cfg *cfg; 245*0f1e8306STakashi Iwai int err; 246*0f1e8306STakashi Iwai 247*0f1e8306STakashi Iwai spec = kzalloc(sizeof(*spec), GFP_KERNEL); 248*0f1e8306STakashi Iwai if (spec == NULL) 249*0f1e8306STakashi Iwai return -ENOMEM; 250*0f1e8306STakashi Iwai 251*0f1e8306STakashi Iwai INIT_DELAYED_WORK(&spec->unsol_hp_work, cm9825_unsol_hp_delayed); 252*0f1e8306STakashi Iwai codec->spec = spec; 253*0f1e8306STakashi Iwai spec->codec = codec; 254*0f1e8306STakashi Iwai cfg = &spec->gen.autocfg; 255*0f1e8306STakashi Iwai snd_hda_gen_spec_init(&spec->gen); 256*0f1e8306STakashi Iwai spec->chip_d0_verbs = cm9825_std_d0_verbs; 257*0f1e8306STakashi Iwai spec->chip_d3_verbs = cm9825_std_d3_verbs; 258*0f1e8306STakashi Iwai spec->chip_hp_present_verbs = cm9825_hp_present_verbs; 259*0f1e8306STakashi Iwai spec->chip_hp_remove_verbs = cm9825_hp_remove_verbs; 260*0f1e8306STakashi Iwai 261*0f1e8306STakashi Iwai snd_hda_sequence_write(codec, spec->chip_d0_verbs); 262*0f1e8306STakashi Iwai 263*0f1e8306STakashi Iwai err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0); 264*0f1e8306STakashi Iwai if (err < 0) 265*0f1e8306STakashi Iwai goto error; 266*0f1e8306STakashi Iwai err = snd_hda_gen_parse_auto_config(codec, cfg); 267*0f1e8306STakashi Iwai if (err < 0) 268*0f1e8306STakashi Iwai goto error; 269*0f1e8306STakashi Iwai 270*0f1e8306STakashi Iwai cm9825_setup_unsol(codec); 271*0f1e8306STakashi Iwai 272*0f1e8306STakashi Iwai return 0; 273*0f1e8306STakashi Iwai 274*0f1e8306STakashi Iwai error: 275*0f1e8306STakashi Iwai cm9825_remove(codec); 276*0f1e8306STakashi Iwai 277*0f1e8306STakashi Iwai codec_info(codec, "Enter err %d\n", err); 278*0f1e8306STakashi Iwai 279*0f1e8306STakashi Iwai return err; 280*0f1e8306STakashi Iwai } 281*0f1e8306STakashi Iwai 282*0f1e8306STakashi Iwai static const struct hda_codec_ops cm9825_codec_ops = { 283*0f1e8306STakashi Iwai .probe = cm9825_probe, 284*0f1e8306STakashi Iwai .remove = cm9825_remove, 285*0f1e8306STakashi Iwai .build_controls = snd_hda_gen_build_controls, 286*0f1e8306STakashi Iwai .build_pcms = snd_hda_gen_build_pcms, 287*0f1e8306STakashi Iwai .init = cm9825_init, 288*0f1e8306STakashi Iwai .unsol_event = snd_hda_jack_unsol_event, 289*0f1e8306STakashi Iwai .suspend = cm9825_suspend, 290*0f1e8306STakashi Iwai .resume = cm9825_resume, 291*0f1e8306STakashi Iwai .check_power_status = snd_hda_gen_check_power_status, 292*0f1e8306STakashi Iwai .stream_pm = snd_hda_gen_stream_pm, 293*0f1e8306STakashi Iwai }; 294*0f1e8306STakashi Iwai 295*0f1e8306STakashi Iwai /* 296*0f1e8306STakashi Iwai * driver entries 297*0f1e8306STakashi Iwai */ 298*0f1e8306STakashi Iwai static const struct hda_device_id snd_hda_id_cm9825[] = { 299*0f1e8306STakashi Iwai HDA_CODEC_ID(0x13f69825, "CM9825"), 300*0f1e8306STakashi Iwai {} /* terminator */ 301*0f1e8306STakashi Iwai }; 302*0f1e8306STakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_cm9825); 303*0f1e8306STakashi Iwai 304*0f1e8306STakashi Iwai MODULE_LICENSE("GPL"); 305*0f1e8306STakashi Iwai MODULE_DESCRIPTION("CM9825 HD-audio codec"); 306*0f1e8306STakashi Iwai 307*0f1e8306STakashi Iwai static struct hda_codec_driver cm9825_driver = { 308*0f1e8306STakashi Iwai .id = snd_hda_id_cm9825, 309*0f1e8306STakashi Iwai .ops = &cm9825_codec_ops, 310*0f1e8306STakashi Iwai }; 311*0f1e8306STakashi Iwai 312*0f1e8306STakashi Iwai module_hda_codec_driver(cm9825_driver); 313