1 /* 2 * Universal Interface for Intel High Definition Audio Codec 3 * 4 * HD audio interface patch for Realtek ALC codecs 5 * 6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw> 7 * PeiSen Hou <pshou@realtek.com.tw> 8 * Takashi Iwai <tiwai@suse.de> 9 * Jonathan Woithe <jwoithe@just42.net> 10 * 11 * This driver is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This driver is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 * Taken from linux's patch_realtek.c 26 */ 27 28 #ifdef HAVE_KERNEL_OPTION_HEADERS 29 #include "opt_snd.h" 30 #endif 31 32 #include <dev/sound/pcm/sound.h> 33 34 #include <sys/ctype.h> 35 36 #include <dev/sound/pci/hda/hdac.h> 37 #include <dev/sound/pci/hda/hdaa.h> 38 #include <dev/sound/pci/hda/hda_reg.h> 39 #include <dev/sound/pci/hda/hdaa_patches.h> 40 41 void 42 hdaa_patch_direct_acer_c720(struct hdaa_devinfo *devinfo) 43 { 44 struct hdaa_widget *w; 45 device_t dev = devinfo->dev; 46 uint32_t val; 47 48 kprintf("Acer C720 patch\n"); 49 50 /* power down control */ 51 hda_write_coef_idx(dev, 0x20, 0x03, 0x0002); 52 /* FIFO and filter clock */ 53 hda_write_coef_idx(dev, 0x20, 0x05, 0x0700); 54 /* DMIC control */ 55 hda_write_coef_idx(dev, 0x20, 0x07, 0x0200); 56 /* Analog clock */ 57 val = hda_read_coef_idx(dev, 0x20, 0x06); 58 hda_write_coef_idx(dev, 0x20, 0x06, (val & ~0x00f0) | 0x0); 59 60 /* JD */ 61 val = hda_read_coef_idx(dev, 0x20, 0x08); 62 hda_write_coef_idx(dev, 0x20, 0x08, (val & ~0xfffc) | 0x0c2c); 63 /* JD offset1 */ 64 hda_write_coef_idx(dev, 0x20, 0x0a, 0xcccc); 65 /* JD offset2 */ 66 hda_write_coef_idx(dev, 0x20, 0x0b, 0xcccc); 67 /* LD0/1/2/3, DAC/ADC */ 68 hda_write_coef_idx(dev, 0x20, 0x0e, 0x6fc0); 69 /* JD */ 70 val = hda_read_coef_idx(dev, 0x20, 0x0f); 71 hda_write_coef_idx(dev, 0x20, 0x0f, (val & ~0xf800) | 0x1000); 72 73 /* Capless */ 74 val = hda_read_coef_idx(dev, 0x20, 0x10); 75 hda_write_coef_idx(dev, 0x20, 0x10, (val & ~0xfc00) | 0x0c00); 76 /* Class D test 4 */ 77 hda_write_coef_idx(dev, 0x20, 0x3a, 0x0); 78 /* IO power down directly */ 79 val = hda_read_coef_idx(dev, 0x20, 0x0c); 80 hda_write_coef_idx(dev, 0x20, 0x0c, (val & ~0xfe00) | 0x0); 81 /* ANC */ 82 hda_write_coef_idx(dev, 0x20, 0x22, 0xa0c0); 83 /* AGC MUX */ 84 val = hda_read_coef_idx(dev, 0x53, 0x01); 85 hda_write_coef_idx(dev, 0x53, 0x01, (val & ~0x000f) | 0x0008); 86 87 /* DAC simple content protection */ 88 val = hda_read_coef_idx(dev, 0x20, 0x1d); 89 hda_write_coef_idx(dev, 0x20, 0x1d, (val & ~0x00e0) | 0x0); 90 /* ADC simple content protection */ 91 val = hda_read_coef_idx(dev, 0x20, 0x1f); 92 hda_write_coef_idx(dev, 0x20, 0x1f, (val & ~0x00e0) | 0x0); 93 /* DAC ADC Zero Detection */ 94 hda_write_coef_idx(dev, 0x20, 0x21, 0x8804); 95 /* PLL */ 96 hda_write_coef_idx(dev, 0x20, 0x2e, 0x2902); 97 /* capless control 2 */ 98 hda_write_coef_idx(dev, 0x20, 0x33, 0xa080); 99 /* capless control 3 */ 100 hda_write_coef_idx(dev, 0x20, 0x34, 0x3400); 101 /* capless control 4 */ 102 hda_write_coef_idx(dev, 0x20, 0x35, 0x2f3e); 103 /* capless control 5 */ 104 hda_write_coef_idx(dev, 0x20, 0x36, 0x0); 105 /* class D test 2 */ 106 val = hda_read_coef_idx(dev, 0x20, 0x38); 107 hda_write_coef_idx(dev, 0x20, 0x38, (val & ~0x0fff) | 0x0900); 108 109 /* class D test 3 */ 110 hda_write_coef_idx(dev, 0x20, 0x39, 0x110a); 111 /* class D test 5 */ 112 val = hda_read_coef_idx(dev, 0x20, 0x3b); 113 hda_write_coef_idx(dev, 0x20, 0x3b, (val & ~0x00f8) | 0x00d8); 114 /* class D test 6 */ 115 hda_write_coef_idx(dev, 0x20, 0x3c, 0x0014); 116 /* classD OCP */ 117 hda_write_coef_idx(dev, 0x20, 0x3d, 0xc2ba); 118 /* classD pure DC test */ 119 val = hda_read_coef_idx(dev, 0x20, 0x42); 120 hda_write_coef_idx(dev, 0x20, 0x42, (val & ~0x0f80) | 0x0); 121 /* test mode */ 122 hda_write_coef_idx(dev, 0x20, 0x49, 0x0); 123 /* Class D DC enable */ 124 val = hda_read_coef_idx(dev, 0x20, 0x40); 125 hda_write_coef_idx(dev, 0x20, 0x40, (val & ~0xf800) | 0x9800); 126 /* DC offset */ 127 val = hda_read_coef_idx(dev, 0x20, 0x42); 128 hda_write_coef_idx(dev, 0x20, 0x42, (val & ~0xf000) | 0x2000); 129 /* Class D amp control */ 130 hda_write_coef_idx(dev, 0x20, 0x37, 0xfc06); 131 132 /* Index 0x43 direct drive HP AMP LPM Control 1 */ 133 /* Headphone capless set to high power mode */ 134 hda_write_coef_idx(dev, 0x20, 0x43, 0x9004); 135 136 #if 0 137 /* 138 * This has to do with the 'mute internal speaker when 139 * ext headphone out jack is plugged' function. nid 27 140 * comes from the special config bits (XXX currently hardwired) 141 * 142 * XXX doesn't apply to chromebook where we just have to change 143 * the mixer selection for nid 33. 144 */ 145 int dummy; 146 hda_command(dev, HDA_CMD_SET_AMP_GAIN_MUTE(0, 27, 0xb080)); 147 tsleep(&dummy, 0, "hdaslp", hz / 10); 148 hda_command(dev, HDA_CMD_SET_PIN_WIDGET_CTRL(0, 27, 149 HDA_CMD_SET_PIN_WIDGET_CTRL_OUT_ENABLE)); 150 tsleep(&dummy, 0, "hdaslp", hz / 10); 151 #endif 152 153 /* 0x46 combo jack auto switch control 2 */ 154 /* 3k pull-down control for headset jack. */ 155 val = hda_read_coef_idx(dev, 0x20, 0x46); 156 hda_write_coef_idx(dev, 0x20, 0x46, val & ~(3 << 12)); 157 /* headphone capless set to normal mode */ 158 hda_write_coef_idx(dev, 0x20, 0x43, 0x9614); 159 160 #if 0 161 /* 162 * Fixup chromebook (? which chromebook?) 163 */ 164 /* MIC2-VREF control */ 165 /* set to manual mode */ 166 val = hda_read_coef_idx(dev, 0x20, 0x06); 167 hda_write_coef_idx(dev, 0x20, 0x06, val & ~0x000c); 168 /* enable line1 input control by verb */ 169 val = hda_read_coef_idx(dev, 0x20, 0x1a); 170 hda_write_coef_idx(dev, 0x20, 0x1a, val | (1 << 4)); 171 #endif 172 173 /* 174 * 31-30 : port connectivity 175 * 29-21 : reserved 176 * 20 : PCBEEP input 177 * 19-16 : checksum (15:1) 178 * 15-1 : Custom 179 * 0 : Override 180 * 181 * XXX this needs code from linux patch_realtek.c alc_subsystem_id(). 182 * Chromebook: 0x4015812d 183 * bit 30 physical connection present 184 * bit 15 if set we want the 'mute internal speaker when 185 * ext headphone out jack is plugged' function 186 * bit 14:13 reserved 187 * bit 12:11 headphone out 00: PortA, 01: PortE, 02: PortD, 188 * 03: Reserved (for C720 this is 0) 189 * bit 10:8 jack location (for c720 this is 1) 190 * 0, 0x1b, 0x14, 0x21 - nnid 27 is jack? 191 * 192 * bit 5:3 -> 101 (5). ALC_INIT_DEFAULT (default ext amp ctl) 193 * bit 0 override (is set) 194 */ 195 if ((w = hdaa_widget_get(devinfo, 0x1d)) != NULL) { 196 kprintf("WIDGET SPECIAL: %08x\n", w->wclass.pin.config); 197 /* XXX currently in hdaa_patch_direct_acer_c720(devinfo); */ 198 } 199 } 200