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