10c0d06caSMauro Carvalho Chehab /* 20c0d06caSMauro Carvalho Chehab * STK1160 driver 30c0d06caSMauro Carvalho Chehab * 40c0d06caSMauro Carvalho Chehab * Copyright (C) 2012 Ezequiel Garcia 50c0d06caSMauro Carvalho Chehab * <elezegarcia--a.t--gmail.com> 60c0d06caSMauro Carvalho Chehab * 7e36e6b5fSMarcel Hasler * Copyright (C) 2016 Marcel Hasler 8e36e6b5fSMarcel Hasler * <mahasler--a.t--gmail.com> 9e36e6b5fSMarcel Hasler * 100c0d06caSMauro Carvalho Chehab * Based on Easycap driver by R.M. Thomas 110c0d06caSMauro Carvalho Chehab * Copyright (C) 2010 R.M. Thomas 120c0d06caSMauro Carvalho Chehab * <rmthomas--a.t--sciolus.org> 130c0d06caSMauro Carvalho Chehab * 140c0d06caSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 150c0d06caSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 160c0d06caSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 170c0d06caSMauro Carvalho Chehab * (at your option) any later version. 180c0d06caSMauro Carvalho Chehab * 190c0d06caSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 200c0d06caSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 210c0d06caSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 220c0d06caSMauro Carvalho Chehab * GNU General Public License for more details. 230c0d06caSMauro Carvalho Chehab * 240c0d06caSMauro Carvalho Chehab */ 250c0d06caSMauro Carvalho Chehab 260c0d06caSMauro Carvalho Chehab #include "stk1160.h" 270c0d06caSMauro Carvalho Chehab #include "stk1160-reg.h" 280c0d06caSMauro Carvalho Chehab 29e36e6b5fSMarcel Hasler static void stk1160_write_ac97(struct stk1160 *dev, u16 reg, u16 value) 300c0d06caSMauro Carvalho Chehab { 310c0d06caSMauro Carvalho Chehab /* Set codec register address */ 320c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); 330c0d06caSMauro Carvalho Chehab 340c0d06caSMauro Carvalho Chehab /* Set codec command */ 350c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff); 360c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8); 370c0d06caSMauro Carvalho Chehab 380c0d06caSMauro Carvalho Chehab /* 390c0d06caSMauro Carvalho Chehab * Set command write bit to initiate write operation. 400c0d06caSMauro Carvalho Chehab * The bit will be cleared when transfer is done. 410c0d06caSMauro Carvalho Chehab */ 420c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c); 430c0d06caSMauro Carvalho Chehab } 440c0d06caSMauro Carvalho Chehab 45e36e6b5fSMarcel Hasler #ifdef DEBUG 46e36e6b5fSMarcel Hasler static u16 stk1160_read_ac97(struct stk1160 *dev, u16 reg) 470c0d06caSMauro Carvalho Chehab { 480c0d06caSMauro Carvalho Chehab u8 vall = 0; 490c0d06caSMauro Carvalho Chehab u8 valh = 0; 500c0d06caSMauro Carvalho Chehab 510c0d06caSMauro Carvalho Chehab /* Set codec register address */ 520c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97_ADDR, reg); 530c0d06caSMauro Carvalho Chehab 540c0d06caSMauro Carvalho Chehab /* 550c0d06caSMauro Carvalho Chehab * Set command read bit to initiate read operation. 560c0d06caSMauro Carvalho Chehab * The bit will be cleared when transfer is done. 570c0d06caSMauro Carvalho Chehab */ 580c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b); 590c0d06caSMauro Carvalho Chehab 600c0d06caSMauro Carvalho Chehab /* Retrieve register value */ 610c0d06caSMauro Carvalho Chehab stk1160_read_reg(dev, STK1160_AC97_CMD, &vall); 620c0d06caSMauro Carvalho Chehab stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh); 630c0d06caSMauro Carvalho Chehab 640c0d06caSMauro Carvalho Chehab return (valh << 8) | vall; 650c0d06caSMauro Carvalho Chehab } 660c0d06caSMauro Carvalho Chehab 67e36e6b5fSMarcel Hasler void stk1160_ac97_dump_regs(struct stk1160 *dev) 680c0d06caSMauro Carvalho Chehab { 69e36e6b5fSMarcel Hasler u16 value; 70e36e6b5fSMarcel Hasler 71e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x12); /* CD volume */ 72e36e6b5fSMarcel Hasler stk1160_dbg("0x12 == 0x%04x", value); 73e36e6b5fSMarcel Hasler 74e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x10); /* Line-in volume */ 75e36e6b5fSMarcel Hasler stk1160_dbg("0x10 == 0x%04x", value); 76e36e6b5fSMarcel Hasler 77e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x0e); /* MIC volume (mono) */ 78e36e6b5fSMarcel Hasler stk1160_dbg("0x0e == 0x%04x", value); 79e36e6b5fSMarcel Hasler 80e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x16); /* Aux volume */ 81e36e6b5fSMarcel Hasler stk1160_dbg("0x16 == 0x%04x", value); 82e36e6b5fSMarcel Hasler 83e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x1a); /* Record select */ 84e36e6b5fSMarcel Hasler stk1160_dbg("0x1a == 0x%04x", value); 85e36e6b5fSMarcel Hasler 86e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x02); /* Master volume */ 87e36e6b5fSMarcel Hasler stk1160_dbg("0x02 == 0x%04x", value); 88e36e6b5fSMarcel Hasler 89e36e6b5fSMarcel Hasler value = stk1160_read_ac97(dev, 0x1c); /* Record gain */ 90e36e6b5fSMarcel Hasler stk1160_dbg("0x1c == 0x%04x", value); 91e36e6b5fSMarcel Hasler } 92e36e6b5fSMarcel Hasler #endif 93e36e6b5fSMarcel Hasler 94e36e6b5fSMarcel Hasler void stk1160_ac97_setup(struct stk1160 *dev) 95e36e6b5fSMarcel Hasler { 960c0d06caSMauro Carvalho Chehab /* Two-step reset AC97 interface and hardware codec */ 970c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94); 98e36e6b5fSMarcel Hasler stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c); 990c0d06caSMauro Carvalho Chehab 1000c0d06caSMauro Carvalho Chehab /* Set 16-bit audio data and choose L&R channel*/ 1010c0d06caSMauro Carvalho Chehab stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01); 102e36e6b5fSMarcel Hasler stk1160_write_reg(dev, STK1160_AC97CTL_1 + 3, 0x00); 1030c0d06caSMauro Carvalho Chehab 104e36e6b5fSMarcel Hasler /* Setup channels */ 105e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x12, 0x8808); /* CD volume */ 106e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x10, 0x0808); /* Line-in volume */ 107e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x0e, 0x0008); /* MIC volume (mono) */ 108e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x16, 0x0808); /* Aux volume */ 109e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x1a, 0x0404); /* Record select */ 110e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x02, 0x0000); /* Master volume */ 111e36e6b5fSMarcel Hasler stk1160_write_ac97(dev, 0x1c, 0x0808); /* Record gain */ 1120c0d06caSMauro Carvalho Chehab 113e36e6b5fSMarcel Hasler #ifdef DEBUG 114e36e6b5fSMarcel Hasler stk1160_ac97_dump_regs(dev); 115e36e6b5fSMarcel Hasler #endif 1160c0d06caSMauro Carvalho Chehab } 117