1*8cc72361SWai Yew CHAY /** 2*8cc72361SWai Yew CHAY * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 3*8cc72361SWai Yew CHAY * 4*8cc72361SWai Yew CHAY * This source file is released under GPL v2 license (no other versions). 5*8cc72361SWai Yew CHAY * See the COPYING file included in the main directory of this source 6*8cc72361SWai Yew CHAY * distribution for the license terms and conditions. 7*8cc72361SWai Yew CHAY * 8*8cc72361SWai Yew CHAY * @File cthw20k1.c 9*8cc72361SWai Yew CHAY * 10*8cc72361SWai Yew CHAY * @Brief 11*8cc72361SWai Yew CHAY * This file contains the implementation of hardware access methord for 20k1. 12*8cc72361SWai Yew CHAY * 13*8cc72361SWai Yew CHAY * @Author Liu Chun 14*8cc72361SWai Yew CHAY * @Date Jun 24 2008 15*8cc72361SWai Yew CHAY * 16*8cc72361SWai Yew CHAY */ 17*8cc72361SWai Yew CHAY 18*8cc72361SWai Yew CHAY #include "cthw20k1.h" 19*8cc72361SWai Yew CHAY #include "ct20k1reg.h" 20*8cc72361SWai Yew CHAY #include <linux/types.h> 21*8cc72361SWai Yew CHAY #include <linux/slab.h> 22*8cc72361SWai Yew CHAY #include <linux/pci.h> 23*8cc72361SWai Yew CHAY #include <linux/io.h> 24*8cc72361SWai Yew CHAY #include <linux/string.h> 25*8cc72361SWai Yew CHAY #include <linux/spinlock.h> 26*8cc72361SWai Yew CHAY #include <linux/kernel.h> 27*8cc72361SWai Yew CHAY #include <linux/interrupt.h> 28*8cc72361SWai Yew CHAY 29*8cc72361SWai Yew CHAY #define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bits */ 30*8cc72361SWai Yew CHAY 31*8cc72361SWai Yew CHAY struct hw20k1 { 32*8cc72361SWai Yew CHAY struct hw hw; 33*8cc72361SWai Yew CHAY spinlock_t reg_20k1_lock; 34*8cc72361SWai Yew CHAY spinlock_t reg_pci_lock; 35*8cc72361SWai Yew CHAY }; 36*8cc72361SWai Yew CHAY 37*8cc72361SWai Yew CHAY static u32 hw_read_20kx(struct hw *hw, u32 reg); 38*8cc72361SWai Yew CHAY static void hw_write_20kx(struct hw *hw, u32 reg, u32 data); 39*8cc72361SWai Yew CHAY static u32 hw_read_pci(struct hw *hw, u32 reg); 40*8cc72361SWai Yew CHAY static void hw_write_pci(struct hw *hw, u32 reg, u32 data); 41*8cc72361SWai Yew CHAY 42*8cc72361SWai Yew CHAY /* 43*8cc72361SWai Yew CHAY * Type definition block. 44*8cc72361SWai Yew CHAY * The layout of control structures can be directly applied on 20k2 chip. 45*8cc72361SWai Yew CHAY */ 46*8cc72361SWai Yew CHAY 47*8cc72361SWai Yew CHAY /* 48*8cc72361SWai Yew CHAY * SRC control block definitions. 49*8cc72361SWai Yew CHAY */ 50*8cc72361SWai Yew CHAY 51*8cc72361SWai Yew CHAY /* SRC resource control block */ 52*8cc72361SWai Yew CHAY #define SRCCTL_STATE 0x00000007 53*8cc72361SWai Yew CHAY #define SRCCTL_BM 0x00000008 54*8cc72361SWai Yew CHAY #define SRCCTL_RSR 0x00000030 55*8cc72361SWai Yew CHAY #define SRCCTL_SF 0x000001C0 56*8cc72361SWai Yew CHAY #define SRCCTL_WR 0x00000200 57*8cc72361SWai Yew CHAY #define SRCCTL_PM 0x00000400 58*8cc72361SWai Yew CHAY #define SRCCTL_ROM 0x00001800 59*8cc72361SWai Yew CHAY #define SRCCTL_VO 0x00002000 60*8cc72361SWai Yew CHAY #define SRCCTL_ST 0x00004000 61*8cc72361SWai Yew CHAY #define SRCCTL_IE 0x00008000 62*8cc72361SWai Yew CHAY #define SRCCTL_ILSZ 0x000F0000 63*8cc72361SWai Yew CHAY #define SRCCTL_BP 0x00100000 64*8cc72361SWai Yew CHAY 65*8cc72361SWai Yew CHAY #define SRCCCR_CISZ 0x000007FF 66*8cc72361SWai Yew CHAY #define SRCCCR_CWA 0x001FF800 67*8cc72361SWai Yew CHAY #define SRCCCR_D 0x00200000 68*8cc72361SWai Yew CHAY #define SRCCCR_RS 0x01C00000 69*8cc72361SWai Yew CHAY #define SRCCCR_NAL 0x3E000000 70*8cc72361SWai Yew CHAY #define SRCCCR_RA 0xC0000000 71*8cc72361SWai Yew CHAY 72*8cc72361SWai Yew CHAY #define SRCCA_CA 0x03FFFFFF 73*8cc72361SWai Yew CHAY #define SRCCA_RS 0x1C000000 74*8cc72361SWai Yew CHAY #define SRCCA_NAL 0xE0000000 75*8cc72361SWai Yew CHAY 76*8cc72361SWai Yew CHAY #define SRCSA_SA 0x03FFFFFF 77*8cc72361SWai Yew CHAY 78*8cc72361SWai Yew CHAY #define SRCLA_LA 0x03FFFFFF 79*8cc72361SWai Yew CHAY 80*8cc72361SWai Yew CHAY /* Mixer Parameter Ring ram Low and Hight register. 81*8cc72361SWai Yew CHAY * Fixed-point value in 8.24 format for parameter channel */ 82*8cc72361SWai Yew CHAY #define MPRLH_PITCH 0xFFFFFFFF 83*8cc72361SWai Yew CHAY 84*8cc72361SWai Yew CHAY /* SRC resource register dirty flags */ 85*8cc72361SWai Yew CHAY union src_dirty { 86*8cc72361SWai Yew CHAY struct { 87*8cc72361SWai Yew CHAY u16 ctl:1; 88*8cc72361SWai Yew CHAY u16 ccr:1; 89*8cc72361SWai Yew CHAY u16 sa:1; 90*8cc72361SWai Yew CHAY u16 la:1; 91*8cc72361SWai Yew CHAY u16 ca:1; 92*8cc72361SWai Yew CHAY u16 mpr:1; 93*8cc72361SWai Yew CHAY u16 czbfs:1; /* Clear Z-Buffers */ 94*8cc72361SWai Yew CHAY u16 rsv:9; 95*8cc72361SWai Yew CHAY } bf; 96*8cc72361SWai Yew CHAY u16 data; 97*8cc72361SWai Yew CHAY }; 98*8cc72361SWai Yew CHAY 99*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk { 100*8cc72361SWai Yew CHAY unsigned int ctl; 101*8cc72361SWai Yew CHAY unsigned int ccr; 102*8cc72361SWai Yew CHAY unsigned int ca; 103*8cc72361SWai Yew CHAY unsigned int sa; 104*8cc72361SWai Yew CHAY unsigned int la; 105*8cc72361SWai Yew CHAY unsigned int mpr; 106*8cc72361SWai Yew CHAY union src_dirty dirty; 107*8cc72361SWai Yew CHAY }; 108*8cc72361SWai Yew CHAY 109*8cc72361SWai Yew CHAY /* SRC manager control block */ 110*8cc72361SWai Yew CHAY union src_mgr_dirty { 111*8cc72361SWai Yew CHAY struct { 112*8cc72361SWai Yew CHAY u16 enb0:1; 113*8cc72361SWai Yew CHAY u16 enb1:1; 114*8cc72361SWai Yew CHAY u16 enb2:1; 115*8cc72361SWai Yew CHAY u16 enb3:1; 116*8cc72361SWai Yew CHAY u16 enb4:1; 117*8cc72361SWai Yew CHAY u16 enb5:1; 118*8cc72361SWai Yew CHAY u16 enb6:1; 119*8cc72361SWai Yew CHAY u16 enb7:1; 120*8cc72361SWai Yew CHAY u16 enbsa:1; 121*8cc72361SWai Yew CHAY u16 rsv:7; 122*8cc72361SWai Yew CHAY } bf; 123*8cc72361SWai Yew CHAY u16 data; 124*8cc72361SWai Yew CHAY }; 125*8cc72361SWai Yew CHAY 126*8cc72361SWai Yew CHAY struct src_mgr_ctrl_blk { 127*8cc72361SWai Yew CHAY unsigned int enbsa; 128*8cc72361SWai Yew CHAY unsigned int enb[8]; 129*8cc72361SWai Yew CHAY union src_mgr_dirty dirty; 130*8cc72361SWai Yew CHAY }; 131*8cc72361SWai Yew CHAY 132*8cc72361SWai Yew CHAY /* SRCIMP manager control block */ 133*8cc72361SWai Yew CHAY #define SRCAIM_ARC 0x00000FFF 134*8cc72361SWai Yew CHAY #define SRCAIM_NXT 0x00FF0000 135*8cc72361SWai Yew CHAY #define SRCAIM_SRC 0xFF000000 136*8cc72361SWai Yew CHAY 137*8cc72361SWai Yew CHAY struct srcimap { 138*8cc72361SWai Yew CHAY unsigned int srcaim; 139*8cc72361SWai Yew CHAY unsigned int idx; 140*8cc72361SWai Yew CHAY }; 141*8cc72361SWai Yew CHAY 142*8cc72361SWai Yew CHAY /* SRCIMP manager register dirty flags */ 143*8cc72361SWai Yew CHAY union srcimp_mgr_dirty { 144*8cc72361SWai Yew CHAY struct { 145*8cc72361SWai Yew CHAY u16 srcimap:1; 146*8cc72361SWai Yew CHAY u16 rsv:15; 147*8cc72361SWai Yew CHAY } bf; 148*8cc72361SWai Yew CHAY u16 data; 149*8cc72361SWai Yew CHAY }; 150*8cc72361SWai Yew CHAY 151*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk { 152*8cc72361SWai Yew CHAY struct srcimap srcimap; 153*8cc72361SWai Yew CHAY union srcimp_mgr_dirty dirty; 154*8cc72361SWai Yew CHAY }; 155*8cc72361SWai Yew CHAY 156*8cc72361SWai Yew CHAY /* 157*8cc72361SWai Yew CHAY * Function implementation block. 158*8cc72361SWai Yew CHAY */ 159*8cc72361SWai Yew CHAY 160*8cc72361SWai Yew CHAY static int src_get_rsc_ctrl_blk(void **rblk) 161*8cc72361SWai Yew CHAY { 162*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *blk; 163*8cc72361SWai Yew CHAY 164*8cc72361SWai Yew CHAY *rblk = NULL; 165*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 166*8cc72361SWai Yew CHAY if (NULL == blk) 167*8cc72361SWai Yew CHAY return -ENOMEM; 168*8cc72361SWai Yew CHAY 169*8cc72361SWai Yew CHAY *rblk = blk; 170*8cc72361SWai Yew CHAY 171*8cc72361SWai Yew CHAY return 0; 172*8cc72361SWai Yew CHAY } 173*8cc72361SWai Yew CHAY 174*8cc72361SWai Yew CHAY static int src_put_rsc_ctrl_blk(void *blk) 175*8cc72361SWai Yew CHAY { 176*8cc72361SWai Yew CHAY kfree((struct src_rsc_ctrl_blk *)blk); 177*8cc72361SWai Yew CHAY 178*8cc72361SWai Yew CHAY return 0; 179*8cc72361SWai Yew CHAY } 180*8cc72361SWai Yew CHAY 181*8cc72361SWai Yew CHAY static int src_set_state(void *blk, unsigned int state) 182*8cc72361SWai Yew CHAY { 183*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 184*8cc72361SWai Yew CHAY 185*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_STATE, state); 186*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 187*8cc72361SWai Yew CHAY return 0; 188*8cc72361SWai Yew CHAY } 189*8cc72361SWai Yew CHAY 190*8cc72361SWai Yew CHAY static int src_set_bm(void *blk, unsigned int bm) 191*8cc72361SWai Yew CHAY { 192*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 193*8cc72361SWai Yew CHAY 194*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_BM, bm); 195*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 196*8cc72361SWai Yew CHAY return 0; 197*8cc72361SWai Yew CHAY } 198*8cc72361SWai Yew CHAY 199*8cc72361SWai Yew CHAY static int src_set_rsr(void *blk, unsigned int rsr) 200*8cc72361SWai Yew CHAY { 201*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 202*8cc72361SWai Yew CHAY 203*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_RSR, rsr); 204*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 205*8cc72361SWai Yew CHAY return 0; 206*8cc72361SWai Yew CHAY } 207*8cc72361SWai Yew CHAY 208*8cc72361SWai Yew CHAY static int src_set_sf(void *blk, unsigned int sf) 209*8cc72361SWai Yew CHAY { 210*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 211*8cc72361SWai Yew CHAY 212*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_SF, sf); 213*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 214*8cc72361SWai Yew CHAY return 0; 215*8cc72361SWai Yew CHAY } 216*8cc72361SWai Yew CHAY 217*8cc72361SWai Yew CHAY static int src_set_wr(void *blk, unsigned int wr) 218*8cc72361SWai Yew CHAY { 219*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 220*8cc72361SWai Yew CHAY 221*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_WR, wr); 222*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 223*8cc72361SWai Yew CHAY return 0; 224*8cc72361SWai Yew CHAY } 225*8cc72361SWai Yew CHAY 226*8cc72361SWai Yew CHAY static int src_set_pm(void *blk, unsigned int pm) 227*8cc72361SWai Yew CHAY { 228*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 229*8cc72361SWai Yew CHAY 230*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_PM, pm); 231*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 232*8cc72361SWai Yew CHAY return 0; 233*8cc72361SWai Yew CHAY } 234*8cc72361SWai Yew CHAY 235*8cc72361SWai Yew CHAY static int src_set_rom(void *blk, unsigned int rom) 236*8cc72361SWai Yew CHAY { 237*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 238*8cc72361SWai Yew CHAY 239*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ROM, rom); 240*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 241*8cc72361SWai Yew CHAY return 0; 242*8cc72361SWai Yew CHAY } 243*8cc72361SWai Yew CHAY 244*8cc72361SWai Yew CHAY static int src_set_vo(void *blk, unsigned int vo) 245*8cc72361SWai Yew CHAY { 246*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 247*8cc72361SWai Yew CHAY 248*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_VO, vo); 249*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 250*8cc72361SWai Yew CHAY return 0; 251*8cc72361SWai Yew CHAY } 252*8cc72361SWai Yew CHAY 253*8cc72361SWai Yew CHAY static int src_set_st(void *blk, unsigned int st) 254*8cc72361SWai Yew CHAY { 255*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 256*8cc72361SWai Yew CHAY 257*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ST, st); 258*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 259*8cc72361SWai Yew CHAY return 0; 260*8cc72361SWai Yew CHAY } 261*8cc72361SWai Yew CHAY 262*8cc72361SWai Yew CHAY static int src_set_ie(void *blk, unsigned int ie) 263*8cc72361SWai Yew CHAY { 264*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 265*8cc72361SWai Yew CHAY 266*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_IE, ie); 267*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 268*8cc72361SWai Yew CHAY return 0; 269*8cc72361SWai Yew CHAY } 270*8cc72361SWai Yew CHAY 271*8cc72361SWai Yew CHAY static int src_set_ilsz(void *blk, unsigned int ilsz) 272*8cc72361SWai Yew CHAY { 273*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 274*8cc72361SWai Yew CHAY 275*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz); 276*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 277*8cc72361SWai Yew CHAY return 0; 278*8cc72361SWai Yew CHAY } 279*8cc72361SWai Yew CHAY 280*8cc72361SWai Yew CHAY static int src_set_bp(void *blk, unsigned int bp) 281*8cc72361SWai Yew CHAY { 282*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 283*8cc72361SWai Yew CHAY 284*8cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_BP, bp); 285*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 286*8cc72361SWai Yew CHAY return 0; 287*8cc72361SWai Yew CHAY } 288*8cc72361SWai Yew CHAY 289*8cc72361SWai Yew CHAY static int src_set_cisz(void *blk, unsigned int cisz) 290*8cc72361SWai Yew CHAY { 291*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 292*8cc72361SWai Yew CHAY 293*8cc72361SWai Yew CHAY set_field(&ctl->ccr, SRCCCR_CISZ, cisz); 294*8cc72361SWai Yew CHAY ctl->dirty.bf.ccr = 1; 295*8cc72361SWai Yew CHAY return 0; 296*8cc72361SWai Yew CHAY } 297*8cc72361SWai Yew CHAY 298*8cc72361SWai Yew CHAY static int src_set_ca(void *blk, unsigned int ca) 299*8cc72361SWai Yew CHAY { 300*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 301*8cc72361SWai Yew CHAY 302*8cc72361SWai Yew CHAY set_field(&ctl->ca, SRCCA_CA, ca); 303*8cc72361SWai Yew CHAY ctl->dirty.bf.ca = 1; 304*8cc72361SWai Yew CHAY return 0; 305*8cc72361SWai Yew CHAY } 306*8cc72361SWai Yew CHAY 307*8cc72361SWai Yew CHAY static int src_set_sa(void *blk, unsigned int sa) 308*8cc72361SWai Yew CHAY { 309*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 310*8cc72361SWai Yew CHAY 311*8cc72361SWai Yew CHAY set_field(&ctl->sa, SRCSA_SA, sa); 312*8cc72361SWai Yew CHAY ctl->dirty.bf.sa = 1; 313*8cc72361SWai Yew CHAY return 0; 314*8cc72361SWai Yew CHAY } 315*8cc72361SWai Yew CHAY 316*8cc72361SWai Yew CHAY static int src_set_la(void *blk, unsigned int la) 317*8cc72361SWai Yew CHAY { 318*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 319*8cc72361SWai Yew CHAY 320*8cc72361SWai Yew CHAY set_field(&ctl->la, SRCLA_LA, la); 321*8cc72361SWai Yew CHAY ctl->dirty.bf.la = 1; 322*8cc72361SWai Yew CHAY return 0; 323*8cc72361SWai Yew CHAY } 324*8cc72361SWai Yew CHAY 325*8cc72361SWai Yew CHAY static int src_set_pitch(void *blk, unsigned int pitch) 326*8cc72361SWai Yew CHAY { 327*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 328*8cc72361SWai Yew CHAY 329*8cc72361SWai Yew CHAY set_field(&ctl->mpr, MPRLH_PITCH, pitch); 330*8cc72361SWai Yew CHAY ctl->dirty.bf.mpr = 1; 331*8cc72361SWai Yew CHAY return 0; 332*8cc72361SWai Yew CHAY } 333*8cc72361SWai Yew CHAY 334*8cc72361SWai Yew CHAY static int src_set_clear_zbufs(void *blk, unsigned int clear) 335*8cc72361SWai Yew CHAY { 336*8cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0); 337*8cc72361SWai Yew CHAY return 0; 338*8cc72361SWai Yew CHAY } 339*8cc72361SWai Yew CHAY 340*8cc72361SWai Yew CHAY static int src_set_dirty(void *blk, unsigned int flags) 341*8cc72361SWai Yew CHAY { 342*8cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 343*8cc72361SWai Yew CHAY return 0; 344*8cc72361SWai Yew CHAY } 345*8cc72361SWai Yew CHAY 346*8cc72361SWai Yew CHAY static int src_set_dirty_all(void *blk) 347*8cc72361SWai Yew CHAY { 348*8cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 349*8cc72361SWai Yew CHAY return 0; 350*8cc72361SWai Yew CHAY } 351*8cc72361SWai Yew CHAY 352*8cc72361SWai Yew CHAY #define AR_SLOT_SIZE 4096 353*8cc72361SWai Yew CHAY #define AR_SLOT_BLOCK_SIZE 16 354*8cc72361SWai Yew CHAY #define AR_PTS_PITCH 6 355*8cc72361SWai Yew CHAY #define AR_PARAM_SRC_OFFSET 0x60 356*8cc72361SWai Yew CHAY 357*8cc72361SWai Yew CHAY static unsigned int src_param_pitch_mixer(unsigned int src_idx) 358*8cc72361SWai Yew CHAY { 359*8cc72361SWai Yew CHAY return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE 360*8cc72361SWai Yew CHAY - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE; 361*8cc72361SWai Yew CHAY 362*8cc72361SWai Yew CHAY } 363*8cc72361SWai Yew CHAY 364*8cc72361SWai Yew CHAY static int src_commit_write(struct hw *hw, unsigned int idx, void *blk) 365*8cc72361SWai Yew CHAY { 366*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 367*8cc72361SWai Yew CHAY int i = 0; 368*8cc72361SWai Yew CHAY 369*8cc72361SWai Yew CHAY if (ctl->dirty.bf.czbfs) { 370*8cc72361SWai Yew CHAY /* Clear Z-Buffer registers */ 371*8cc72361SWai Yew CHAY for (i = 0; i < 8; i++) 372*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCUPZ+idx*0x100+i*0x4, 0); 373*8cc72361SWai Yew CHAY 374*8cc72361SWai Yew CHAY for (i = 0; i < 4; i++) 375*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCDN0Z+idx*0x100+i*0x4, 0); 376*8cc72361SWai Yew CHAY 377*8cc72361SWai Yew CHAY for (i = 0; i < 8; i++) 378*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCDN1Z+idx*0x100+i*0x4, 0); 379*8cc72361SWai Yew CHAY 380*8cc72361SWai Yew CHAY ctl->dirty.bf.czbfs = 0; 381*8cc72361SWai Yew CHAY } 382*8cc72361SWai Yew CHAY if (ctl->dirty.bf.mpr) { 383*8cc72361SWai Yew CHAY /* Take the parameter mixer resource in the same group as that 384*8cc72361SWai Yew CHAY * the idx src is in for simplicity. Unlike src, all conjugate 385*8cc72361SWai Yew CHAY * parameter mixer resources must be programmed for 386*8cc72361SWai Yew CHAY * corresponding conjugate src resources. */ 387*8cc72361SWai Yew CHAY unsigned int pm_idx = src_param_pitch_mixer(idx); 388*8cc72361SWai Yew CHAY hw_write_20kx(hw, PRING_LO_HI+4*pm_idx, ctl->mpr); 389*8cc72361SWai Yew CHAY hw_write_20kx(hw, PMOPLO+8*pm_idx, 0x3); 390*8cc72361SWai Yew CHAY hw_write_20kx(hw, PMOPHI+8*pm_idx, 0x0); 391*8cc72361SWai Yew CHAY ctl->dirty.bf.mpr = 0; 392*8cc72361SWai Yew CHAY } 393*8cc72361SWai Yew CHAY if (ctl->dirty.bf.sa) { 394*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCSA+idx*0x100, ctl->sa); 395*8cc72361SWai Yew CHAY ctl->dirty.bf.sa = 0; 396*8cc72361SWai Yew CHAY } 397*8cc72361SWai Yew CHAY if (ctl->dirty.bf.la) { 398*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCLA+idx*0x100, ctl->la); 399*8cc72361SWai Yew CHAY ctl->dirty.bf.la = 0; 400*8cc72361SWai Yew CHAY } 401*8cc72361SWai Yew CHAY if (ctl->dirty.bf.ca) { 402*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCA+idx*0x100, ctl->ca); 403*8cc72361SWai Yew CHAY ctl->dirty.bf.ca = 0; 404*8cc72361SWai Yew CHAY } 405*8cc72361SWai Yew CHAY 406*8cc72361SWai Yew CHAY /* Write srccf register */ 407*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCF+idx*0x100, 0x0); 408*8cc72361SWai Yew CHAY 409*8cc72361SWai Yew CHAY if (ctl->dirty.bf.ccr) { 410*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCCR+idx*0x100, ctl->ccr); 411*8cc72361SWai Yew CHAY ctl->dirty.bf.ccr = 0; 412*8cc72361SWai Yew CHAY } 413*8cc72361SWai Yew CHAY if (ctl->dirty.bf.ctl) { 414*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCTL+idx*0x100, ctl->ctl); 415*8cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 0; 416*8cc72361SWai Yew CHAY } 417*8cc72361SWai Yew CHAY 418*8cc72361SWai Yew CHAY return 0; 419*8cc72361SWai Yew CHAY } 420*8cc72361SWai Yew CHAY 421*8cc72361SWai Yew CHAY static int src_get_ca(struct hw *hw, unsigned int idx, void *blk) 422*8cc72361SWai Yew CHAY { 423*8cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 424*8cc72361SWai Yew CHAY 425*8cc72361SWai Yew CHAY ctl->ca = hw_read_20kx(hw, SRCCA+idx*0x100); 426*8cc72361SWai Yew CHAY ctl->dirty.bf.ca = 0; 427*8cc72361SWai Yew CHAY 428*8cc72361SWai Yew CHAY return get_field(ctl->ca, SRCCA_CA); 429*8cc72361SWai Yew CHAY } 430*8cc72361SWai Yew CHAY 431*8cc72361SWai Yew CHAY static unsigned int src_get_dirty(void *blk) 432*8cc72361SWai Yew CHAY { 433*8cc72361SWai Yew CHAY return ((struct src_rsc_ctrl_blk *)blk)->dirty.data; 434*8cc72361SWai Yew CHAY } 435*8cc72361SWai Yew CHAY 436*8cc72361SWai Yew CHAY static unsigned int src_dirty_conj_mask(void) 437*8cc72361SWai Yew CHAY { 438*8cc72361SWai Yew CHAY return 0x20; 439*8cc72361SWai Yew CHAY } 440*8cc72361SWai Yew CHAY 441*8cc72361SWai Yew CHAY static int src_mgr_enbs_src(void *blk, unsigned int idx) 442*8cc72361SWai Yew CHAY { 443*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enbsa = ~(0x0); 444*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1; 445*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 446*8cc72361SWai Yew CHAY return 0; 447*8cc72361SWai Yew CHAY } 448*8cc72361SWai Yew CHAY 449*8cc72361SWai Yew CHAY static int src_mgr_enb_src(void *blk, unsigned int idx) 450*8cc72361SWai Yew CHAY { 451*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 452*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 453*8cc72361SWai Yew CHAY return 0; 454*8cc72361SWai Yew CHAY } 455*8cc72361SWai Yew CHAY 456*8cc72361SWai Yew CHAY static int src_mgr_dsb_src(void *blk, unsigned int idx) 457*8cc72361SWai Yew CHAY { 458*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32)); 459*8cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 460*8cc72361SWai Yew CHAY return 0; 461*8cc72361SWai Yew CHAY } 462*8cc72361SWai Yew CHAY 463*8cc72361SWai Yew CHAY static int src_mgr_commit_write(struct hw *hw, void *blk) 464*8cc72361SWai Yew CHAY { 465*8cc72361SWai Yew CHAY struct src_mgr_ctrl_blk *ctl = blk; 466*8cc72361SWai Yew CHAY int i = 0; 467*8cc72361SWai Yew CHAY unsigned int ret = 0; 468*8cc72361SWai Yew CHAY 469*8cc72361SWai Yew CHAY if (ctl->dirty.bf.enbsa) { 470*8cc72361SWai Yew CHAY do { 471*8cc72361SWai Yew CHAY ret = hw_read_20kx(hw, SRCENBSTAT); 472*8cc72361SWai Yew CHAY } while (ret & 0x1); 473*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCENBS, ctl->enbsa); 474*8cc72361SWai Yew CHAY ctl->dirty.bf.enbsa = 0; 475*8cc72361SWai Yew CHAY } 476*8cc72361SWai Yew CHAY for (i = 0; i < 8; i++) { 477*8cc72361SWai Yew CHAY if ((ctl->dirty.data & (0x1 << i))) { 478*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCENB+(i*0x100), ctl->enb[i]); 479*8cc72361SWai Yew CHAY ctl->dirty.data &= ~(0x1 << i); 480*8cc72361SWai Yew CHAY } 481*8cc72361SWai Yew CHAY } 482*8cc72361SWai Yew CHAY 483*8cc72361SWai Yew CHAY return 0; 484*8cc72361SWai Yew CHAY } 485*8cc72361SWai Yew CHAY 486*8cc72361SWai Yew CHAY static int src_mgr_get_ctrl_blk(void **rblk) 487*8cc72361SWai Yew CHAY { 488*8cc72361SWai Yew CHAY struct src_mgr_ctrl_blk *blk; 489*8cc72361SWai Yew CHAY 490*8cc72361SWai Yew CHAY *rblk = NULL; 491*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 492*8cc72361SWai Yew CHAY if (NULL == blk) 493*8cc72361SWai Yew CHAY return -ENOMEM; 494*8cc72361SWai Yew CHAY 495*8cc72361SWai Yew CHAY *rblk = blk; 496*8cc72361SWai Yew CHAY 497*8cc72361SWai Yew CHAY return 0; 498*8cc72361SWai Yew CHAY } 499*8cc72361SWai Yew CHAY 500*8cc72361SWai Yew CHAY static int src_mgr_put_ctrl_blk(void *blk) 501*8cc72361SWai Yew CHAY { 502*8cc72361SWai Yew CHAY kfree((struct src_mgr_ctrl_blk *)blk); 503*8cc72361SWai Yew CHAY 504*8cc72361SWai Yew CHAY return 0; 505*8cc72361SWai Yew CHAY } 506*8cc72361SWai Yew CHAY 507*8cc72361SWai Yew CHAY static int srcimp_mgr_get_ctrl_blk(void **rblk) 508*8cc72361SWai Yew CHAY { 509*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *blk; 510*8cc72361SWai Yew CHAY 511*8cc72361SWai Yew CHAY *rblk = NULL; 512*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 513*8cc72361SWai Yew CHAY if (NULL == blk) 514*8cc72361SWai Yew CHAY return -ENOMEM; 515*8cc72361SWai Yew CHAY 516*8cc72361SWai Yew CHAY *rblk = blk; 517*8cc72361SWai Yew CHAY 518*8cc72361SWai Yew CHAY return 0; 519*8cc72361SWai Yew CHAY } 520*8cc72361SWai Yew CHAY 521*8cc72361SWai Yew CHAY static int srcimp_mgr_put_ctrl_blk(void *blk) 522*8cc72361SWai Yew CHAY { 523*8cc72361SWai Yew CHAY kfree((struct srcimp_mgr_ctrl_blk *)blk); 524*8cc72361SWai Yew CHAY 525*8cc72361SWai Yew CHAY return 0; 526*8cc72361SWai Yew CHAY } 527*8cc72361SWai Yew CHAY 528*8cc72361SWai Yew CHAY static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot) 529*8cc72361SWai Yew CHAY { 530*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 531*8cc72361SWai Yew CHAY 532*8cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot); 533*8cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 534*8cc72361SWai Yew CHAY return 0; 535*8cc72361SWai Yew CHAY } 536*8cc72361SWai Yew CHAY 537*8cc72361SWai Yew CHAY static int srcimp_mgr_set_imapuser(void *blk, unsigned int user) 538*8cc72361SWai Yew CHAY { 539*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 540*8cc72361SWai Yew CHAY 541*8cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user); 542*8cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 543*8cc72361SWai Yew CHAY return 0; 544*8cc72361SWai Yew CHAY } 545*8cc72361SWai Yew CHAY 546*8cc72361SWai Yew CHAY static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next) 547*8cc72361SWai Yew CHAY { 548*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 549*8cc72361SWai Yew CHAY 550*8cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next); 551*8cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 552*8cc72361SWai Yew CHAY return 0; 553*8cc72361SWai Yew CHAY } 554*8cc72361SWai Yew CHAY 555*8cc72361SWai Yew CHAY static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr) 556*8cc72361SWai Yew CHAY { 557*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 558*8cc72361SWai Yew CHAY 559*8cc72361SWai Yew CHAY ctl->srcimap.idx = addr; 560*8cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 561*8cc72361SWai Yew CHAY return 0; 562*8cc72361SWai Yew CHAY } 563*8cc72361SWai Yew CHAY 564*8cc72361SWai Yew CHAY static int srcimp_mgr_commit_write(struct hw *hw, void *blk) 565*8cc72361SWai Yew CHAY { 566*8cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 567*8cc72361SWai Yew CHAY 568*8cc72361SWai Yew CHAY if (ctl->dirty.bf.srcimap) { 569*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCIMAP+ctl->srcimap.idx*0x100, 570*8cc72361SWai Yew CHAY ctl->srcimap.srcaim); 571*8cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 0; 572*8cc72361SWai Yew CHAY } 573*8cc72361SWai Yew CHAY 574*8cc72361SWai Yew CHAY return 0; 575*8cc72361SWai Yew CHAY } 576*8cc72361SWai Yew CHAY 577*8cc72361SWai Yew CHAY /* 578*8cc72361SWai Yew CHAY * AMIXER control block definitions. 579*8cc72361SWai Yew CHAY */ 580*8cc72361SWai Yew CHAY 581*8cc72361SWai Yew CHAY #define AMOPLO_M 0x00000003 582*8cc72361SWai Yew CHAY #define AMOPLO_X 0x0003FFF0 583*8cc72361SWai Yew CHAY #define AMOPLO_Y 0xFFFC0000 584*8cc72361SWai Yew CHAY 585*8cc72361SWai Yew CHAY #define AMOPHI_SADR 0x000000FF 586*8cc72361SWai Yew CHAY #define AMOPHI_SE 0x80000000 587*8cc72361SWai Yew CHAY 588*8cc72361SWai Yew CHAY /* AMIXER resource register dirty flags */ 589*8cc72361SWai Yew CHAY union amixer_dirty { 590*8cc72361SWai Yew CHAY struct { 591*8cc72361SWai Yew CHAY u16 amoplo:1; 592*8cc72361SWai Yew CHAY u16 amophi:1; 593*8cc72361SWai Yew CHAY u16 rsv:14; 594*8cc72361SWai Yew CHAY } bf; 595*8cc72361SWai Yew CHAY u16 data; 596*8cc72361SWai Yew CHAY }; 597*8cc72361SWai Yew CHAY 598*8cc72361SWai Yew CHAY /* AMIXER resource control block */ 599*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk { 600*8cc72361SWai Yew CHAY unsigned int amoplo; 601*8cc72361SWai Yew CHAY unsigned int amophi; 602*8cc72361SWai Yew CHAY union amixer_dirty dirty; 603*8cc72361SWai Yew CHAY }; 604*8cc72361SWai Yew CHAY 605*8cc72361SWai Yew CHAY static int amixer_set_mode(void *blk, unsigned int mode) 606*8cc72361SWai Yew CHAY { 607*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 608*8cc72361SWai Yew CHAY 609*8cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_M, mode); 610*8cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 611*8cc72361SWai Yew CHAY return 0; 612*8cc72361SWai Yew CHAY } 613*8cc72361SWai Yew CHAY 614*8cc72361SWai Yew CHAY static int amixer_set_iv(void *blk, unsigned int iv) 615*8cc72361SWai Yew CHAY { 616*8cc72361SWai Yew CHAY /* 20k1 amixer does not have this field */ 617*8cc72361SWai Yew CHAY return 0; 618*8cc72361SWai Yew CHAY } 619*8cc72361SWai Yew CHAY 620*8cc72361SWai Yew CHAY static int amixer_set_x(void *blk, unsigned int x) 621*8cc72361SWai Yew CHAY { 622*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 623*8cc72361SWai Yew CHAY 624*8cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_X, x); 625*8cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 626*8cc72361SWai Yew CHAY return 0; 627*8cc72361SWai Yew CHAY } 628*8cc72361SWai Yew CHAY 629*8cc72361SWai Yew CHAY static int amixer_set_y(void *blk, unsigned int y) 630*8cc72361SWai Yew CHAY { 631*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 632*8cc72361SWai Yew CHAY 633*8cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_Y, y); 634*8cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 635*8cc72361SWai Yew CHAY return 0; 636*8cc72361SWai Yew CHAY } 637*8cc72361SWai Yew CHAY 638*8cc72361SWai Yew CHAY static int amixer_set_sadr(void *blk, unsigned int sadr) 639*8cc72361SWai Yew CHAY { 640*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 641*8cc72361SWai Yew CHAY 642*8cc72361SWai Yew CHAY set_field(&ctl->amophi, AMOPHI_SADR, sadr); 643*8cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 1; 644*8cc72361SWai Yew CHAY return 0; 645*8cc72361SWai Yew CHAY } 646*8cc72361SWai Yew CHAY 647*8cc72361SWai Yew CHAY static int amixer_set_se(void *blk, unsigned int se) 648*8cc72361SWai Yew CHAY { 649*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 650*8cc72361SWai Yew CHAY 651*8cc72361SWai Yew CHAY set_field(&ctl->amophi, AMOPHI_SE, se); 652*8cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 1; 653*8cc72361SWai Yew CHAY return 0; 654*8cc72361SWai Yew CHAY } 655*8cc72361SWai Yew CHAY 656*8cc72361SWai Yew CHAY static int amixer_set_dirty(void *blk, unsigned int flags) 657*8cc72361SWai Yew CHAY { 658*8cc72361SWai Yew CHAY ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 659*8cc72361SWai Yew CHAY return 0; 660*8cc72361SWai Yew CHAY } 661*8cc72361SWai Yew CHAY 662*8cc72361SWai Yew CHAY static int amixer_set_dirty_all(void *blk) 663*8cc72361SWai Yew CHAY { 664*8cc72361SWai Yew CHAY ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 665*8cc72361SWai Yew CHAY return 0; 666*8cc72361SWai Yew CHAY } 667*8cc72361SWai Yew CHAY 668*8cc72361SWai Yew CHAY static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) 669*8cc72361SWai Yew CHAY { 670*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 671*8cc72361SWai Yew CHAY 672*8cc72361SWai Yew CHAY if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { 673*8cc72361SWai Yew CHAY hw_write_20kx(hw, AMOPLO+idx*8, ctl->amoplo); 674*8cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 0; 675*8cc72361SWai Yew CHAY hw_write_20kx(hw, AMOPHI+idx*8, ctl->amophi); 676*8cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 0; 677*8cc72361SWai Yew CHAY } 678*8cc72361SWai Yew CHAY 679*8cc72361SWai Yew CHAY return 0; 680*8cc72361SWai Yew CHAY } 681*8cc72361SWai Yew CHAY 682*8cc72361SWai Yew CHAY static int amixer_get_y(void *blk) 683*8cc72361SWai Yew CHAY { 684*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 685*8cc72361SWai Yew CHAY 686*8cc72361SWai Yew CHAY return get_field(ctl->amoplo, AMOPLO_Y); 687*8cc72361SWai Yew CHAY } 688*8cc72361SWai Yew CHAY 689*8cc72361SWai Yew CHAY static unsigned int amixer_get_dirty(void *blk) 690*8cc72361SWai Yew CHAY { 691*8cc72361SWai Yew CHAY return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; 692*8cc72361SWai Yew CHAY } 693*8cc72361SWai Yew CHAY 694*8cc72361SWai Yew CHAY static int amixer_rsc_get_ctrl_blk(void **rblk) 695*8cc72361SWai Yew CHAY { 696*8cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *blk; 697*8cc72361SWai Yew CHAY 698*8cc72361SWai Yew CHAY *rblk = NULL; 699*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 700*8cc72361SWai Yew CHAY if (NULL == blk) 701*8cc72361SWai Yew CHAY return -ENOMEM; 702*8cc72361SWai Yew CHAY 703*8cc72361SWai Yew CHAY *rblk = blk; 704*8cc72361SWai Yew CHAY 705*8cc72361SWai Yew CHAY return 0; 706*8cc72361SWai Yew CHAY } 707*8cc72361SWai Yew CHAY 708*8cc72361SWai Yew CHAY static int amixer_rsc_put_ctrl_blk(void *blk) 709*8cc72361SWai Yew CHAY { 710*8cc72361SWai Yew CHAY kfree((struct amixer_rsc_ctrl_blk *)blk); 711*8cc72361SWai Yew CHAY 712*8cc72361SWai Yew CHAY return 0; 713*8cc72361SWai Yew CHAY } 714*8cc72361SWai Yew CHAY 715*8cc72361SWai Yew CHAY static int amixer_mgr_get_ctrl_blk(void **rblk) 716*8cc72361SWai Yew CHAY { 717*8cc72361SWai Yew CHAY /*amixer_mgr_ctrl_blk_t *blk;*/ 718*8cc72361SWai Yew CHAY 719*8cc72361SWai Yew CHAY *rblk = NULL; 720*8cc72361SWai Yew CHAY /*blk = kzalloc(sizeof(*blk), GFP_KERNEL); 721*8cc72361SWai Yew CHAY if (NULL == blk) 722*8cc72361SWai Yew CHAY return -ENOMEM; 723*8cc72361SWai Yew CHAY 724*8cc72361SWai Yew CHAY *rblk = blk;*/ 725*8cc72361SWai Yew CHAY 726*8cc72361SWai Yew CHAY return 0; 727*8cc72361SWai Yew CHAY } 728*8cc72361SWai Yew CHAY 729*8cc72361SWai Yew CHAY static int amixer_mgr_put_ctrl_blk(void *blk) 730*8cc72361SWai Yew CHAY { 731*8cc72361SWai Yew CHAY /*kfree((amixer_mgr_ctrl_blk_t *)blk);*/ 732*8cc72361SWai Yew CHAY 733*8cc72361SWai Yew CHAY return 0; 734*8cc72361SWai Yew CHAY } 735*8cc72361SWai Yew CHAY 736*8cc72361SWai Yew CHAY /* 737*8cc72361SWai Yew CHAY * DAIO control block definitions. 738*8cc72361SWai Yew CHAY */ 739*8cc72361SWai Yew CHAY 740*8cc72361SWai Yew CHAY /* Receiver Sample Rate Tracker Control register */ 741*8cc72361SWai Yew CHAY #define SRTCTL_SRCR 0x000000FF 742*8cc72361SWai Yew CHAY #define SRTCTL_SRCL 0x0000FF00 743*8cc72361SWai Yew CHAY #define SRTCTL_RSR 0x00030000 744*8cc72361SWai Yew CHAY #define SRTCTL_DRAT 0x000C0000 745*8cc72361SWai Yew CHAY #define SRTCTL_RLE 0x10000000 746*8cc72361SWai Yew CHAY #define SRTCTL_RLP 0x20000000 747*8cc72361SWai Yew CHAY #define SRTCTL_EC 0x40000000 748*8cc72361SWai Yew CHAY #define SRTCTL_ET 0x80000000 749*8cc72361SWai Yew CHAY 750*8cc72361SWai Yew CHAY /* DAIO Receiver register dirty flags */ 751*8cc72361SWai Yew CHAY union dai_dirty { 752*8cc72361SWai Yew CHAY struct { 753*8cc72361SWai Yew CHAY u16 srtctl:1; 754*8cc72361SWai Yew CHAY u16 rsv:15; 755*8cc72361SWai Yew CHAY } bf; 756*8cc72361SWai Yew CHAY u16 data; 757*8cc72361SWai Yew CHAY }; 758*8cc72361SWai Yew CHAY 759*8cc72361SWai Yew CHAY /* DAIO Receiver control block */ 760*8cc72361SWai Yew CHAY struct dai_ctrl_blk { 761*8cc72361SWai Yew CHAY unsigned int srtctl; 762*8cc72361SWai Yew CHAY union dai_dirty dirty; 763*8cc72361SWai Yew CHAY }; 764*8cc72361SWai Yew CHAY 765*8cc72361SWai Yew CHAY /* S/PDIF Transmitter register dirty flags */ 766*8cc72361SWai Yew CHAY union dao_dirty { 767*8cc72361SWai Yew CHAY struct { 768*8cc72361SWai Yew CHAY u16 spos:1; 769*8cc72361SWai Yew CHAY u16 rsv:15; 770*8cc72361SWai Yew CHAY } bf; 771*8cc72361SWai Yew CHAY u16 data; 772*8cc72361SWai Yew CHAY }; 773*8cc72361SWai Yew CHAY 774*8cc72361SWai Yew CHAY /* S/PDIF Transmitter control block */ 775*8cc72361SWai Yew CHAY struct dao_ctrl_blk { 776*8cc72361SWai Yew CHAY unsigned int spos; /* S/PDIF Output Channel Status Register */ 777*8cc72361SWai Yew CHAY union dao_dirty dirty; 778*8cc72361SWai Yew CHAY }; 779*8cc72361SWai Yew CHAY 780*8cc72361SWai Yew CHAY /* Audio Input Mapper RAM */ 781*8cc72361SWai Yew CHAY #define AIM_ARC 0x00000FFF 782*8cc72361SWai Yew CHAY #define AIM_NXT 0x007F0000 783*8cc72361SWai Yew CHAY 784*8cc72361SWai Yew CHAY struct daoimap { 785*8cc72361SWai Yew CHAY unsigned int aim; 786*8cc72361SWai Yew CHAY unsigned int idx; 787*8cc72361SWai Yew CHAY }; 788*8cc72361SWai Yew CHAY 789*8cc72361SWai Yew CHAY /* I2S Transmitter/Receiver Control register */ 790*8cc72361SWai Yew CHAY #define I2SCTL_EA 0x00000004 791*8cc72361SWai Yew CHAY #define I2SCTL_EI 0x00000010 792*8cc72361SWai Yew CHAY 793*8cc72361SWai Yew CHAY /* S/PDIF Transmitter Control register */ 794*8cc72361SWai Yew CHAY #define SPOCTL_OE 0x00000001 795*8cc72361SWai Yew CHAY #define SPOCTL_OS 0x0000000E 796*8cc72361SWai Yew CHAY #define SPOCTL_RIV 0x00000010 797*8cc72361SWai Yew CHAY #define SPOCTL_LIV 0x00000020 798*8cc72361SWai Yew CHAY #define SPOCTL_SR 0x000000C0 799*8cc72361SWai Yew CHAY 800*8cc72361SWai Yew CHAY /* S/PDIF Receiver Control register */ 801*8cc72361SWai Yew CHAY #define SPICTL_EN 0x00000001 802*8cc72361SWai Yew CHAY #define SPICTL_I24 0x00000002 803*8cc72361SWai Yew CHAY #define SPICTL_IB 0x00000004 804*8cc72361SWai Yew CHAY #define SPICTL_SM 0x00000008 805*8cc72361SWai Yew CHAY #define SPICTL_VM 0x00000010 806*8cc72361SWai Yew CHAY 807*8cc72361SWai Yew CHAY /* DAIO manager register dirty flags */ 808*8cc72361SWai Yew CHAY union daio_mgr_dirty { 809*8cc72361SWai Yew CHAY struct { 810*8cc72361SWai Yew CHAY u32 i2soctl:4; 811*8cc72361SWai Yew CHAY u32 i2sictl:4; 812*8cc72361SWai Yew CHAY u32 spoctl:4; 813*8cc72361SWai Yew CHAY u32 spictl:4; 814*8cc72361SWai Yew CHAY u32 daoimap:1; 815*8cc72361SWai Yew CHAY u32 rsv:15; 816*8cc72361SWai Yew CHAY } bf; 817*8cc72361SWai Yew CHAY u32 data; 818*8cc72361SWai Yew CHAY }; 819*8cc72361SWai Yew CHAY 820*8cc72361SWai Yew CHAY /* DAIO manager control block */ 821*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk { 822*8cc72361SWai Yew CHAY unsigned int i2sctl; 823*8cc72361SWai Yew CHAY unsigned int spoctl; 824*8cc72361SWai Yew CHAY unsigned int spictl; 825*8cc72361SWai Yew CHAY struct daoimap daoimap; 826*8cc72361SWai Yew CHAY union daio_mgr_dirty dirty; 827*8cc72361SWai Yew CHAY }; 828*8cc72361SWai Yew CHAY 829*8cc72361SWai Yew CHAY static int dai_srt_set_srcr(void *blk, unsigned int src) 830*8cc72361SWai Yew CHAY { 831*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 832*8cc72361SWai Yew CHAY 833*8cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_SRCR, src); 834*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 835*8cc72361SWai Yew CHAY return 0; 836*8cc72361SWai Yew CHAY } 837*8cc72361SWai Yew CHAY 838*8cc72361SWai Yew CHAY static int dai_srt_set_srcl(void *blk, unsigned int src) 839*8cc72361SWai Yew CHAY { 840*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 841*8cc72361SWai Yew CHAY 842*8cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_SRCL, src); 843*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 844*8cc72361SWai Yew CHAY return 0; 845*8cc72361SWai Yew CHAY } 846*8cc72361SWai Yew CHAY 847*8cc72361SWai Yew CHAY static int dai_srt_set_rsr(void *blk, unsigned int rsr) 848*8cc72361SWai Yew CHAY { 849*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 850*8cc72361SWai Yew CHAY 851*8cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_RSR, rsr); 852*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 853*8cc72361SWai Yew CHAY return 0; 854*8cc72361SWai Yew CHAY } 855*8cc72361SWai Yew CHAY 856*8cc72361SWai Yew CHAY static int dai_srt_set_drat(void *blk, unsigned int drat) 857*8cc72361SWai Yew CHAY { 858*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 859*8cc72361SWai Yew CHAY 860*8cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_DRAT, drat); 861*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 862*8cc72361SWai Yew CHAY return 0; 863*8cc72361SWai Yew CHAY } 864*8cc72361SWai Yew CHAY 865*8cc72361SWai Yew CHAY static int dai_srt_set_ec(void *blk, unsigned int ec) 866*8cc72361SWai Yew CHAY { 867*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 868*8cc72361SWai Yew CHAY 869*8cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_EC, ec ? 1 : 0); 870*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 871*8cc72361SWai Yew CHAY return 0; 872*8cc72361SWai Yew CHAY } 873*8cc72361SWai Yew CHAY 874*8cc72361SWai Yew CHAY static int dai_srt_set_et(void *blk, unsigned int et) 875*8cc72361SWai Yew CHAY { 876*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 877*8cc72361SWai Yew CHAY 878*8cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_ET, et ? 1 : 0); 879*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 880*8cc72361SWai Yew CHAY return 0; 881*8cc72361SWai Yew CHAY } 882*8cc72361SWai Yew CHAY 883*8cc72361SWai Yew CHAY static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) 884*8cc72361SWai Yew CHAY { 885*8cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 886*8cc72361SWai Yew CHAY 887*8cc72361SWai Yew CHAY if (ctl->dirty.bf.srtctl) { 888*8cc72361SWai Yew CHAY if (idx < 4) { 889*8cc72361SWai Yew CHAY /* S/PDIF SRTs */ 890*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRTSCTL+0x4*idx, ctl->srtctl); 891*8cc72361SWai Yew CHAY } else { 892*8cc72361SWai Yew CHAY /* I2S SRT */ 893*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRTICTL, ctl->srtctl); 894*8cc72361SWai Yew CHAY } 895*8cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 0; 896*8cc72361SWai Yew CHAY } 897*8cc72361SWai Yew CHAY 898*8cc72361SWai Yew CHAY return 0; 899*8cc72361SWai Yew CHAY } 900*8cc72361SWai Yew CHAY 901*8cc72361SWai Yew CHAY static int dai_get_ctrl_blk(void **rblk) 902*8cc72361SWai Yew CHAY { 903*8cc72361SWai Yew CHAY struct dai_ctrl_blk *blk; 904*8cc72361SWai Yew CHAY 905*8cc72361SWai Yew CHAY *rblk = NULL; 906*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 907*8cc72361SWai Yew CHAY if (NULL == blk) 908*8cc72361SWai Yew CHAY return -ENOMEM; 909*8cc72361SWai Yew CHAY 910*8cc72361SWai Yew CHAY *rblk = blk; 911*8cc72361SWai Yew CHAY 912*8cc72361SWai Yew CHAY return 0; 913*8cc72361SWai Yew CHAY } 914*8cc72361SWai Yew CHAY 915*8cc72361SWai Yew CHAY static int dai_put_ctrl_blk(void *blk) 916*8cc72361SWai Yew CHAY { 917*8cc72361SWai Yew CHAY kfree((struct dai_ctrl_blk *)blk); 918*8cc72361SWai Yew CHAY 919*8cc72361SWai Yew CHAY return 0; 920*8cc72361SWai Yew CHAY } 921*8cc72361SWai Yew CHAY 922*8cc72361SWai Yew CHAY static int dao_set_spos(void *blk, unsigned int spos) 923*8cc72361SWai Yew CHAY { 924*8cc72361SWai Yew CHAY ((struct dao_ctrl_blk *)blk)->spos = spos; 925*8cc72361SWai Yew CHAY ((struct dao_ctrl_blk *)blk)->dirty.bf.spos = 1; 926*8cc72361SWai Yew CHAY return 0; 927*8cc72361SWai Yew CHAY } 928*8cc72361SWai Yew CHAY 929*8cc72361SWai Yew CHAY static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) 930*8cc72361SWai Yew CHAY { 931*8cc72361SWai Yew CHAY struct dao_ctrl_blk *ctl = blk; 932*8cc72361SWai Yew CHAY 933*8cc72361SWai Yew CHAY if (ctl->dirty.bf.spos) { 934*8cc72361SWai Yew CHAY if (idx < 4) { 935*8cc72361SWai Yew CHAY /* S/PDIF SPOSx */ 936*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPOS+0x4*idx, ctl->spos); 937*8cc72361SWai Yew CHAY } 938*8cc72361SWai Yew CHAY ctl->dirty.bf.spos = 0; 939*8cc72361SWai Yew CHAY } 940*8cc72361SWai Yew CHAY 941*8cc72361SWai Yew CHAY return 0; 942*8cc72361SWai Yew CHAY } 943*8cc72361SWai Yew CHAY 944*8cc72361SWai Yew CHAY static int dao_get_spos(void *blk, unsigned int *spos) 945*8cc72361SWai Yew CHAY { 946*8cc72361SWai Yew CHAY *spos = ((struct dao_ctrl_blk *)blk)->spos; 947*8cc72361SWai Yew CHAY return 0; 948*8cc72361SWai Yew CHAY } 949*8cc72361SWai Yew CHAY 950*8cc72361SWai Yew CHAY static int dao_get_ctrl_blk(void **rblk) 951*8cc72361SWai Yew CHAY { 952*8cc72361SWai Yew CHAY struct dao_ctrl_blk *blk; 953*8cc72361SWai Yew CHAY 954*8cc72361SWai Yew CHAY *rblk = NULL; 955*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 956*8cc72361SWai Yew CHAY if (NULL == blk) 957*8cc72361SWai Yew CHAY return -ENOMEM; 958*8cc72361SWai Yew CHAY 959*8cc72361SWai Yew CHAY *rblk = blk; 960*8cc72361SWai Yew CHAY 961*8cc72361SWai Yew CHAY return 0; 962*8cc72361SWai Yew CHAY } 963*8cc72361SWai Yew CHAY 964*8cc72361SWai Yew CHAY static int dao_put_ctrl_blk(void *blk) 965*8cc72361SWai Yew CHAY { 966*8cc72361SWai Yew CHAY kfree((struct dao_ctrl_blk *)blk); 967*8cc72361SWai Yew CHAY 968*8cc72361SWai Yew CHAY return 0; 969*8cc72361SWai Yew CHAY } 970*8cc72361SWai Yew CHAY 971*8cc72361SWai Yew CHAY static int daio_mgr_enb_dai(void *blk, unsigned int idx) 972*8cc72361SWai Yew CHAY { 973*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 974*8cc72361SWai Yew CHAY 975*8cc72361SWai Yew CHAY if (idx < 4) { 976*8cc72361SWai Yew CHAY /* S/PDIF input */ 977*8cc72361SWai Yew CHAY set_field(&ctl->spictl, SPICTL_EN << (idx*8), 1); 978*8cc72361SWai Yew CHAY ctl->dirty.bf.spictl |= (0x1 << idx); 979*8cc72361SWai Yew CHAY } else { 980*8cc72361SWai Yew CHAY /* I2S input */ 981*8cc72361SWai Yew CHAY idx %= 4; 982*8cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 1); 983*8cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl |= (0x1 << idx); 984*8cc72361SWai Yew CHAY } 985*8cc72361SWai Yew CHAY return 0; 986*8cc72361SWai Yew CHAY } 987*8cc72361SWai Yew CHAY 988*8cc72361SWai Yew CHAY static int daio_mgr_dsb_dai(void *blk, unsigned int idx) 989*8cc72361SWai Yew CHAY { 990*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 991*8cc72361SWai Yew CHAY 992*8cc72361SWai Yew CHAY if (idx < 4) { 993*8cc72361SWai Yew CHAY /* S/PDIF input */ 994*8cc72361SWai Yew CHAY set_field(&ctl->spictl, SPICTL_EN << (idx*8), 0); 995*8cc72361SWai Yew CHAY ctl->dirty.bf.spictl |= (0x1 << idx); 996*8cc72361SWai Yew CHAY } else { 997*8cc72361SWai Yew CHAY /* I2S input */ 998*8cc72361SWai Yew CHAY idx %= 4; 999*8cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 0); 1000*8cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl |= (0x1 << idx); 1001*8cc72361SWai Yew CHAY } 1002*8cc72361SWai Yew CHAY return 0; 1003*8cc72361SWai Yew CHAY } 1004*8cc72361SWai Yew CHAY 1005*8cc72361SWai Yew CHAY static int daio_mgr_enb_dao(void *blk, unsigned int idx) 1006*8cc72361SWai Yew CHAY { 1007*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1008*8cc72361SWai Yew CHAY 1009*8cc72361SWai Yew CHAY if (idx < 4) { 1010*8cc72361SWai Yew CHAY /* S/PDIF output */ 1011*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 1); 1012*8cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 1013*8cc72361SWai Yew CHAY } else { 1014*8cc72361SWai Yew CHAY /* I2S output */ 1015*8cc72361SWai Yew CHAY idx %= 4; 1016*8cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 1); 1017*8cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl |= (0x1 << idx); 1018*8cc72361SWai Yew CHAY } 1019*8cc72361SWai Yew CHAY return 0; 1020*8cc72361SWai Yew CHAY } 1021*8cc72361SWai Yew CHAY 1022*8cc72361SWai Yew CHAY static int daio_mgr_dsb_dao(void *blk, unsigned int idx) 1023*8cc72361SWai Yew CHAY { 1024*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1025*8cc72361SWai Yew CHAY 1026*8cc72361SWai Yew CHAY if (idx < 4) { 1027*8cc72361SWai Yew CHAY /* S/PDIF output */ 1028*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 0); 1029*8cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 1030*8cc72361SWai Yew CHAY } else { 1031*8cc72361SWai Yew CHAY /* I2S output */ 1032*8cc72361SWai Yew CHAY idx %= 4; 1033*8cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 0); 1034*8cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl |= (0x1 << idx); 1035*8cc72361SWai Yew CHAY } 1036*8cc72361SWai Yew CHAY return 0; 1037*8cc72361SWai Yew CHAY } 1038*8cc72361SWai Yew CHAY 1039*8cc72361SWai Yew CHAY static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) 1040*8cc72361SWai Yew CHAY { 1041*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1042*8cc72361SWai Yew CHAY 1043*8cc72361SWai Yew CHAY if (idx < 4) { 1044*8cc72361SWai Yew CHAY /* S/PDIF output */ 1045*8cc72361SWai Yew CHAY switch ((conf & 0x7)) { 1046*8cc72361SWai Yew CHAY case 0: 1047*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 3); 1048*8cc72361SWai Yew CHAY break; /* CDIF */ 1049*8cc72361SWai Yew CHAY case 1: 1050*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 0); 1051*8cc72361SWai Yew CHAY break; 1052*8cc72361SWai Yew CHAY case 2: 1053*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 1); 1054*8cc72361SWai Yew CHAY break; 1055*8cc72361SWai Yew CHAY case 4: 1056*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 2); 1057*8cc72361SWai Yew CHAY break; 1058*8cc72361SWai Yew CHAY default: 1059*8cc72361SWai Yew CHAY break; 1060*8cc72361SWai Yew CHAY } 1061*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_LIV << (idx*8), 1062*8cc72361SWai Yew CHAY (conf >> 4) & 0x1); /* Non-audio */ 1063*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_RIV << (idx*8), 1064*8cc72361SWai Yew CHAY (conf >> 4) & 0x1); /* Non-audio */ 1065*8cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OS << (idx*8), 1066*8cc72361SWai Yew CHAY ((conf >> 3) & 0x1) ? 2 : 2); /* Raw */ 1067*8cc72361SWai Yew CHAY 1068*8cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 1069*8cc72361SWai Yew CHAY } else { 1070*8cc72361SWai Yew CHAY /* I2S output */ 1071*8cc72361SWai Yew CHAY /*idx %= 4; */ 1072*8cc72361SWai Yew CHAY } 1073*8cc72361SWai Yew CHAY return 0; 1074*8cc72361SWai Yew CHAY } 1075*8cc72361SWai Yew CHAY 1076*8cc72361SWai Yew CHAY static int daio_mgr_set_imaparc(void *blk, unsigned int slot) 1077*8cc72361SWai Yew CHAY { 1078*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1079*8cc72361SWai Yew CHAY 1080*8cc72361SWai Yew CHAY set_field(&ctl->daoimap.aim, AIM_ARC, slot); 1081*8cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 1082*8cc72361SWai Yew CHAY return 0; 1083*8cc72361SWai Yew CHAY } 1084*8cc72361SWai Yew CHAY 1085*8cc72361SWai Yew CHAY static int daio_mgr_set_imapnxt(void *blk, unsigned int next) 1086*8cc72361SWai Yew CHAY { 1087*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1088*8cc72361SWai Yew CHAY 1089*8cc72361SWai Yew CHAY set_field(&ctl->daoimap.aim, AIM_NXT, next); 1090*8cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 1091*8cc72361SWai Yew CHAY return 0; 1092*8cc72361SWai Yew CHAY } 1093*8cc72361SWai Yew CHAY 1094*8cc72361SWai Yew CHAY static int daio_mgr_set_imapaddr(void *blk, unsigned int addr) 1095*8cc72361SWai Yew CHAY { 1096*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1097*8cc72361SWai Yew CHAY 1098*8cc72361SWai Yew CHAY ctl->daoimap.idx = addr; 1099*8cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 1100*8cc72361SWai Yew CHAY return 0; 1101*8cc72361SWai Yew CHAY } 1102*8cc72361SWai Yew CHAY 1103*8cc72361SWai Yew CHAY static int daio_mgr_commit_write(struct hw *hw, void *blk) 1104*8cc72361SWai Yew CHAY { 1105*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1106*8cc72361SWai Yew CHAY int i = 0; 1107*8cc72361SWai Yew CHAY 1108*8cc72361SWai Yew CHAY if (ctl->dirty.bf.i2sictl || ctl->dirty.bf.i2soctl) { 1109*8cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 1110*8cc72361SWai Yew CHAY if ((ctl->dirty.bf.i2sictl & (0x1 << i))) 1111*8cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl &= ~(0x1 << i); 1112*8cc72361SWai Yew CHAY 1113*8cc72361SWai Yew CHAY if ((ctl->dirty.bf.i2soctl & (0x1 << i))) 1114*8cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl &= ~(0x1 << i); 1115*8cc72361SWai Yew CHAY } 1116*8cc72361SWai Yew CHAY hw_write_20kx(hw, I2SCTL, ctl->i2sctl); 1117*8cc72361SWai Yew CHAY mdelay(1); 1118*8cc72361SWai Yew CHAY } 1119*8cc72361SWai Yew CHAY if (ctl->dirty.bf.spoctl) { 1120*8cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 1121*8cc72361SWai Yew CHAY if ((ctl->dirty.bf.spoctl & (0x1 << i))) 1122*8cc72361SWai Yew CHAY ctl->dirty.bf.spoctl &= ~(0x1 << i); 1123*8cc72361SWai Yew CHAY } 1124*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, ctl->spoctl); 1125*8cc72361SWai Yew CHAY mdelay(1); 1126*8cc72361SWai Yew CHAY } 1127*8cc72361SWai Yew CHAY if (ctl->dirty.bf.spictl) { 1128*8cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 1129*8cc72361SWai Yew CHAY if ((ctl->dirty.bf.spictl & (0x1 << i))) 1130*8cc72361SWai Yew CHAY ctl->dirty.bf.spictl &= ~(0x1 << i); 1131*8cc72361SWai Yew CHAY } 1132*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, ctl->spictl); 1133*8cc72361SWai Yew CHAY mdelay(1); 1134*8cc72361SWai Yew CHAY } 1135*8cc72361SWai Yew CHAY if (ctl->dirty.bf.daoimap) { 1136*8cc72361SWai Yew CHAY hw_write_20kx(hw, DAOIMAP+ctl->daoimap.idx*4, 1137*8cc72361SWai Yew CHAY ctl->daoimap.aim); 1138*8cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 0; 1139*8cc72361SWai Yew CHAY } 1140*8cc72361SWai Yew CHAY 1141*8cc72361SWai Yew CHAY return 0; 1142*8cc72361SWai Yew CHAY } 1143*8cc72361SWai Yew CHAY 1144*8cc72361SWai Yew CHAY static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) 1145*8cc72361SWai Yew CHAY { 1146*8cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *blk; 1147*8cc72361SWai Yew CHAY 1148*8cc72361SWai Yew CHAY *rblk = NULL; 1149*8cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 1150*8cc72361SWai Yew CHAY if (NULL == blk) 1151*8cc72361SWai Yew CHAY return -ENOMEM; 1152*8cc72361SWai Yew CHAY 1153*8cc72361SWai Yew CHAY blk->i2sctl = hw_read_20kx(hw, I2SCTL); 1154*8cc72361SWai Yew CHAY blk->spoctl = hw_read_20kx(hw, SPOCTL); 1155*8cc72361SWai Yew CHAY blk->spictl = hw_read_20kx(hw, SPICTL); 1156*8cc72361SWai Yew CHAY 1157*8cc72361SWai Yew CHAY *rblk = blk; 1158*8cc72361SWai Yew CHAY 1159*8cc72361SWai Yew CHAY return 0; 1160*8cc72361SWai Yew CHAY } 1161*8cc72361SWai Yew CHAY 1162*8cc72361SWai Yew CHAY static int daio_mgr_put_ctrl_blk(void *blk) 1163*8cc72361SWai Yew CHAY { 1164*8cc72361SWai Yew CHAY kfree((struct daio_mgr_ctrl_blk *)blk); 1165*8cc72361SWai Yew CHAY 1166*8cc72361SWai Yew CHAY return 0; 1167*8cc72361SWai Yew CHAY } 1168*8cc72361SWai Yew CHAY 1169*8cc72361SWai Yew CHAY /* Card hardware initialization block */ 1170*8cc72361SWai Yew CHAY struct dac_conf { 1171*8cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 1172*8cc72361SWai Yew CHAY }; 1173*8cc72361SWai Yew CHAY 1174*8cc72361SWai Yew CHAY struct adc_conf { 1175*8cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 1176*8cc72361SWai Yew CHAY unsigned char input; /* the input source of ADC */ 1177*8cc72361SWai Yew CHAY unsigned char mic20db; /* boost mic by 20db if input is microphone */ 1178*8cc72361SWai Yew CHAY }; 1179*8cc72361SWai Yew CHAY 1180*8cc72361SWai Yew CHAY struct daio_conf { 1181*8cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 1182*8cc72361SWai Yew CHAY }; 1183*8cc72361SWai Yew CHAY 1184*8cc72361SWai Yew CHAY struct trn_conf { 1185*8cc72361SWai Yew CHAY unsigned long vm_pgt_phys; 1186*8cc72361SWai Yew CHAY }; 1187*8cc72361SWai Yew CHAY 1188*8cc72361SWai Yew CHAY static int hw_daio_init(struct hw *hw, const struct daio_conf *info) 1189*8cc72361SWai Yew CHAY { 1190*8cc72361SWai Yew CHAY u32 i2sorg = 0; 1191*8cc72361SWai Yew CHAY u32 spdorg = 0; 1192*8cc72361SWai Yew CHAY 1193*8cc72361SWai Yew CHAY /* Read I2S CTL. Keep original value. */ 1194*8cc72361SWai Yew CHAY /*i2sorg = hw_read_20kx(hw, I2SCTL);*/ 1195*8cc72361SWai Yew CHAY i2sorg = 0x94040404; /* enable all audio out and I2S-D input */ 1196*8cc72361SWai Yew CHAY /* Program I2S with proper master sample rate and enable 1197*8cc72361SWai Yew CHAY * the correct I2S channel. */ 1198*8cc72361SWai Yew CHAY i2sorg &= 0xfffffffc; 1199*8cc72361SWai Yew CHAY 1200*8cc72361SWai Yew CHAY /* Enable S/PDIF-out-A in fixed 24-bit data 1201*8cc72361SWai Yew CHAY * format and default to 48kHz. */ 1202*8cc72361SWai Yew CHAY /* Disable all before doing any changes. */ 1203*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, 0x0); 1204*8cc72361SWai Yew CHAY spdorg = 0x05; 1205*8cc72361SWai Yew CHAY 1206*8cc72361SWai Yew CHAY switch (info->msr) { 1207*8cc72361SWai Yew CHAY case 1: 1208*8cc72361SWai Yew CHAY i2sorg |= 1; 1209*8cc72361SWai Yew CHAY spdorg |= (0x0 << 6); 1210*8cc72361SWai Yew CHAY break; 1211*8cc72361SWai Yew CHAY case 2: 1212*8cc72361SWai Yew CHAY i2sorg |= 2; 1213*8cc72361SWai Yew CHAY spdorg |= (0x1 << 6); 1214*8cc72361SWai Yew CHAY break; 1215*8cc72361SWai Yew CHAY case 4: 1216*8cc72361SWai Yew CHAY i2sorg |= 3; 1217*8cc72361SWai Yew CHAY spdorg |= (0x2 << 6); 1218*8cc72361SWai Yew CHAY break; 1219*8cc72361SWai Yew CHAY default: 1220*8cc72361SWai Yew CHAY i2sorg |= 1; 1221*8cc72361SWai Yew CHAY break; 1222*8cc72361SWai Yew CHAY } 1223*8cc72361SWai Yew CHAY 1224*8cc72361SWai Yew CHAY hw_write_20kx(hw, I2SCTL, i2sorg); 1225*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, spdorg); 1226*8cc72361SWai Yew CHAY 1227*8cc72361SWai Yew CHAY /* Enable S/PDIF-in-A in fixed 24-bit data format. */ 1228*8cc72361SWai Yew CHAY /* Disable all before doing any changes. */ 1229*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, 0x0); 1230*8cc72361SWai Yew CHAY mdelay(1); 1231*8cc72361SWai Yew CHAY spdorg = 0x0a0a0a0a; 1232*8cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, spdorg); 1233*8cc72361SWai Yew CHAY mdelay(1); 1234*8cc72361SWai Yew CHAY 1235*8cc72361SWai Yew CHAY return 0; 1236*8cc72361SWai Yew CHAY } 1237*8cc72361SWai Yew CHAY 1238*8cc72361SWai Yew CHAY /* TRANSPORT operations */ 1239*8cc72361SWai Yew CHAY static int hw_trn_init(struct hw *hw, const struct trn_conf *info) 1240*8cc72361SWai Yew CHAY { 1241*8cc72361SWai Yew CHAY u32 trnctl = 0; 1242*8cc72361SWai Yew CHAY unsigned long ptp_phys_low = 0, ptp_phys_high = 0; 1243*8cc72361SWai Yew CHAY 1244*8cc72361SWai Yew CHAY /* Set up device page table */ 1245*8cc72361SWai Yew CHAY if ((~0UL) == info->vm_pgt_phys) { 1246*8cc72361SWai Yew CHAY printk(KERN_ERR "Wrong device page table page address!\n"); 1247*8cc72361SWai Yew CHAY return -1; 1248*8cc72361SWai Yew CHAY } 1249*8cc72361SWai Yew CHAY 1250*8cc72361SWai Yew CHAY trnctl = 0x13; /* 32-bit, 4k-size page */ 1251*8cc72361SWai Yew CHAY #if BITS_PER_LONG == 64 1252*8cc72361SWai Yew CHAY ptp_phys_low = info->vm_pgt_phys & ((1UL<<32)-1); 1253*8cc72361SWai Yew CHAY ptp_phys_high = (info->vm_pgt_phys>>32) & ((1UL<<32)-1); 1254*8cc72361SWai Yew CHAY trnctl |= (1<<2); 1255*8cc72361SWai Yew CHAY #elif BITS_PER_LONG == 32 1256*8cc72361SWai Yew CHAY ptp_phys_low = info->vm_pgt_phys & (~0UL); 1257*8cc72361SWai Yew CHAY ptp_phys_high = 0; 1258*8cc72361SWai Yew CHAY #else 1259*8cc72361SWai Yew CHAY # error "Unknown BITS_PER_LONG!" 1260*8cc72361SWai Yew CHAY #endif 1261*8cc72361SWai Yew CHAY #if PAGE_SIZE == 8192 1262*8cc72361SWai Yew CHAY trnctl |= (1<<5); 1263*8cc72361SWai Yew CHAY #endif 1264*8cc72361SWai Yew CHAY hw_write_20kx(hw, PTPALX, ptp_phys_low); 1265*8cc72361SWai Yew CHAY hw_write_20kx(hw, PTPAHX, ptp_phys_high); 1266*8cc72361SWai Yew CHAY hw_write_20kx(hw, TRNCTL, trnctl); 1267*8cc72361SWai Yew CHAY hw_write_20kx(hw, TRNIS, 0x200c01); /* realy needed? */ 1268*8cc72361SWai Yew CHAY 1269*8cc72361SWai Yew CHAY return 0; 1270*8cc72361SWai Yew CHAY } 1271*8cc72361SWai Yew CHAY 1272*8cc72361SWai Yew CHAY /* Card initialization */ 1273*8cc72361SWai Yew CHAY #define GCTL_EAC 0x00000001 1274*8cc72361SWai Yew CHAY #define GCTL_EAI 0x00000002 1275*8cc72361SWai Yew CHAY #define GCTL_BEP 0x00000004 1276*8cc72361SWai Yew CHAY #define GCTL_BES 0x00000008 1277*8cc72361SWai Yew CHAY #define GCTL_DSP 0x00000010 1278*8cc72361SWai Yew CHAY #define GCTL_DBP 0x00000020 1279*8cc72361SWai Yew CHAY #define GCTL_ABP 0x00000040 1280*8cc72361SWai Yew CHAY #define GCTL_TBP 0x00000080 1281*8cc72361SWai Yew CHAY #define GCTL_SBP 0x00000100 1282*8cc72361SWai Yew CHAY #define GCTL_FBP 0x00000200 1283*8cc72361SWai Yew CHAY #define GCTL_XA 0x00000400 1284*8cc72361SWai Yew CHAY #define GCTL_ET 0x00000800 1285*8cc72361SWai Yew CHAY #define GCTL_PR 0x00001000 1286*8cc72361SWai Yew CHAY #define GCTL_MRL 0x00002000 1287*8cc72361SWai Yew CHAY #define GCTL_SDE 0x00004000 1288*8cc72361SWai Yew CHAY #define GCTL_SDI 0x00008000 1289*8cc72361SWai Yew CHAY #define GCTL_SM 0x00010000 1290*8cc72361SWai Yew CHAY #define GCTL_SR 0x00020000 1291*8cc72361SWai Yew CHAY #define GCTL_SD 0x00040000 1292*8cc72361SWai Yew CHAY #define GCTL_SE 0x00080000 1293*8cc72361SWai Yew CHAY #define GCTL_AID 0x00100000 1294*8cc72361SWai Yew CHAY 1295*8cc72361SWai Yew CHAY static int hw_pll_init(struct hw *hw, unsigned int rsr) 1296*8cc72361SWai Yew CHAY { 1297*8cc72361SWai Yew CHAY unsigned int pllctl; 1298*8cc72361SWai Yew CHAY int i = 0; 1299*8cc72361SWai Yew CHAY 1300*8cc72361SWai Yew CHAY pllctl = (48000 == rsr) ? 0x1480a001 : 0x1480a731; 1301*8cc72361SWai Yew CHAY for (i = 0; i < 3; i++) { 1302*8cc72361SWai Yew CHAY if (hw_read_20kx(hw, PLLCTL) == pllctl) 1303*8cc72361SWai Yew CHAY break; 1304*8cc72361SWai Yew CHAY 1305*8cc72361SWai Yew CHAY hw_write_20kx(hw, PLLCTL, pllctl); 1306*8cc72361SWai Yew CHAY mdelay(40); 1307*8cc72361SWai Yew CHAY } 1308*8cc72361SWai Yew CHAY if (i >= 3) { 1309*8cc72361SWai Yew CHAY printk(KERN_ALERT "PLL initialization failed!!!\n"); 1310*8cc72361SWai Yew CHAY return -EBUSY; 1311*8cc72361SWai Yew CHAY } 1312*8cc72361SWai Yew CHAY 1313*8cc72361SWai Yew CHAY return 0; 1314*8cc72361SWai Yew CHAY } 1315*8cc72361SWai Yew CHAY 1316*8cc72361SWai Yew CHAY static int hw_auto_init(struct hw *hw) 1317*8cc72361SWai Yew CHAY { 1318*8cc72361SWai Yew CHAY unsigned int gctl; 1319*8cc72361SWai Yew CHAY int i; 1320*8cc72361SWai Yew CHAY 1321*8cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 1322*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAI, 0); 1323*8cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 1324*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAI, 1); 1325*8cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 1326*8cc72361SWai Yew CHAY mdelay(10); 1327*8cc72361SWai Yew CHAY for (i = 0; i < 400000; i++) { 1328*8cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 1329*8cc72361SWai Yew CHAY if (get_field(gctl, GCTL_AID)) 1330*8cc72361SWai Yew CHAY break; 1331*8cc72361SWai Yew CHAY } 1332*8cc72361SWai Yew CHAY if (!get_field(gctl, GCTL_AID)) { 1333*8cc72361SWai Yew CHAY printk(KERN_ALERT "Card Auto-init failed!!!\n"); 1334*8cc72361SWai Yew CHAY return -EBUSY; 1335*8cc72361SWai Yew CHAY } 1336*8cc72361SWai Yew CHAY 1337*8cc72361SWai Yew CHAY return 0; 1338*8cc72361SWai Yew CHAY } 1339*8cc72361SWai Yew CHAY 1340*8cc72361SWai Yew CHAY static int i2c_unlock(struct hw *hw) 1341*8cc72361SWai Yew CHAY { 1342*8cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 1343*8cc72361SWai Yew CHAY return 0; 1344*8cc72361SWai Yew CHAY 1345*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x8c); 1346*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x0e); 1347*8cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 1348*8cc72361SWai Yew CHAY return 0; 1349*8cc72361SWai Yew CHAY 1350*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0xee); 1351*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0xaa); 1352*8cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 1353*8cc72361SWai Yew CHAY return 0; 1354*8cc72361SWai Yew CHAY 1355*8cc72361SWai Yew CHAY return -1; 1356*8cc72361SWai Yew CHAY } 1357*8cc72361SWai Yew CHAY 1358*8cc72361SWai Yew CHAY static void i2c_lock(struct hw *hw) 1359*8cc72361SWai Yew CHAY { 1360*8cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 1361*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x00); 1362*8cc72361SWai Yew CHAY } 1363*8cc72361SWai Yew CHAY 1364*8cc72361SWai Yew CHAY static void i2c_write(struct hw *hw, u32 device, u32 addr, u32 data) 1365*8cc72361SWai Yew CHAY { 1366*8cc72361SWai Yew CHAY unsigned int ret = 0; 1367*8cc72361SWai Yew CHAY 1368*8cc72361SWai Yew CHAY do { 1369*8cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 1370*8cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 1371*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xE0, device); 1372*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xE4, (data << 8) | (addr & 0xff)); 1373*8cc72361SWai Yew CHAY } 1374*8cc72361SWai Yew CHAY 1375*8cc72361SWai Yew CHAY /* DAC operations */ 1376*8cc72361SWai Yew CHAY 1377*8cc72361SWai Yew CHAY static int hw_reset_dac(struct hw *hw) 1378*8cc72361SWai Yew CHAY { 1379*8cc72361SWai Yew CHAY u32 i = 0; 1380*8cc72361SWai Yew CHAY u16 gpioorg = 0; 1381*8cc72361SWai Yew CHAY unsigned int ret = 0; 1382*8cc72361SWai Yew CHAY 1383*8cc72361SWai Yew CHAY if (i2c_unlock(hw)) 1384*8cc72361SWai Yew CHAY return -1; 1385*8cc72361SWai Yew CHAY 1386*8cc72361SWai Yew CHAY do { 1387*8cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 1388*8cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 1389*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 1390*8cc72361SWai Yew CHAY 1391*8cc72361SWai Yew CHAY /* To be effective, need to reset the DAC twice. */ 1392*8cc72361SWai Yew CHAY for (i = 0; i < 2; i++) { 1393*8cc72361SWai Yew CHAY /* set gpio */ 1394*8cc72361SWai Yew CHAY mdelay(100); 1395*8cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 1396*8cc72361SWai Yew CHAY gpioorg &= 0xfffd; 1397*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 1398*8cc72361SWai Yew CHAY mdelay(1); 1399*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg | 0x2); 1400*8cc72361SWai Yew CHAY } 1401*8cc72361SWai Yew CHAY 1402*8cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x01, 0x80); 1403*8cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x02, 0x10); 1404*8cc72361SWai Yew CHAY 1405*8cc72361SWai Yew CHAY i2c_lock(hw); 1406*8cc72361SWai Yew CHAY 1407*8cc72361SWai Yew CHAY return 0; 1408*8cc72361SWai Yew CHAY } 1409*8cc72361SWai Yew CHAY 1410*8cc72361SWai Yew CHAY static int hw_dac_init(struct hw *hw, const struct dac_conf *info) 1411*8cc72361SWai Yew CHAY { 1412*8cc72361SWai Yew CHAY u32 data = 0; 1413*8cc72361SWai Yew CHAY u16 gpioorg = 0; 1414*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1415*8cc72361SWai Yew CHAY unsigned int ret = 0; 1416*8cc72361SWai Yew CHAY 1417*8cc72361SWai Yew CHAY pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id); 1418*8cc72361SWai Yew CHAY if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) { 1419*8cc72361SWai Yew CHAY /* SB055x, unmute outputs */ 1420*8cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 1421*8cc72361SWai Yew CHAY gpioorg &= 0xffbf; /* set GPIO6 to low */ 1422*8cc72361SWai Yew CHAY gpioorg |= 2; /* set GPIO1 to high */ 1423*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 1424*8cc72361SWai Yew CHAY return 0; 1425*8cc72361SWai Yew CHAY } 1426*8cc72361SWai Yew CHAY 1427*8cc72361SWai Yew CHAY /* mute outputs */ 1428*8cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 1429*8cc72361SWai Yew CHAY gpioorg &= 0xffbf; 1430*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 1431*8cc72361SWai Yew CHAY 1432*8cc72361SWai Yew CHAY hw_reset_dac(hw); 1433*8cc72361SWai Yew CHAY 1434*8cc72361SWai Yew CHAY if (i2c_unlock(hw)) 1435*8cc72361SWai Yew CHAY return -1; 1436*8cc72361SWai Yew CHAY 1437*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 1438*8cc72361SWai Yew CHAY do { 1439*8cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 1440*8cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 1441*8cc72361SWai Yew CHAY 1442*8cc72361SWai Yew CHAY switch (info->msr) { 1443*8cc72361SWai Yew CHAY case 1: 1444*8cc72361SWai Yew CHAY data = 0x24; 1445*8cc72361SWai Yew CHAY break; 1446*8cc72361SWai Yew CHAY case 2: 1447*8cc72361SWai Yew CHAY data = 0x25; 1448*8cc72361SWai Yew CHAY break; 1449*8cc72361SWai Yew CHAY case 4: 1450*8cc72361SWai Yew CHAY data = 0x26; 1451*8cc72361SWai Yew CHAY break; 1452*8cc72361SWai Yew CHAY default: 1453*8cc72361SWai Yew CHAY data = 0x24; 1454*8cc72361SWai Yew CHAY break; 1455*8cc72361SWai Yew CHAY } 1456*8cc72361SWai Yew CHAY 1457*8cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x06, data); 1458*8cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x09, data); 1459*8cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x0c, data); 1460*8cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x0f, data); 1461*8cc72361SWai Yew CHAY 1462*8cc72361SWai Yew CHAY i2c_lock(hw); 1463*8cc72361SWai Yew CHAY 1464*8cc72361SWai Yew CHAY /* unmute outputs */ 1465*8cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 1466*8cc72361SWai Yew CHAY gpioorg = gpioorg | 0x40; 1467*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 1468*8cc72361SWai Yew CHAY 1469*8cc72361SWai Yew CHAY return 0; 1470*8cc72361SWai Yew CHAY } 1471*8cc72361SWai Yew CHAY 1472*8cc72361SWai Yew CHAY /* ADC operations */ 1473*8cc72361SWai Yew CHAY 1474*8cc72361SWai Yew CHAY static int is_adc_input_selected_SB055x(struct hw *hw, enum ADCSRC type) 1475*8cc72361SWai Yew CHAY { 1476*8cc72361SWai Yew CHAY u32 data = 0; 1477*8cc72361SWai Yew CHAY return data; 1478*8cc72361SWai Yew CHAY } 1479*8cc72361SWai Yew CHAY 1480*8cc72361SWai Yew CHAY static int is_adc_input_selected_SBx(struct hw *hw, enum ADCSRC type) 1481*8cc72361SWai Yew CHAY { 1482*8cc72361SWai Yew CHAY u32 data = 0; 1483*8cc72361SWai Yew CHAY 1484*8cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 1485*8cc72361SWai Yew CHAY switch (type) { 1486*8cc72361SWai Yew CHAY case ADC_MICIN: 1487*8cc72361SWai Yew CHAY data = ((data & (0x1<<7)) && (data & (0x1<<8))); 1488*8cc72361SWai Yew CHAY break; 1489*8cc72361SWai Yew CHAY case ADC_LINEIN: 1490*8cc72361SWai Yew CHAY data = (!(data & (0x1<<7)) && (data & (0x1<<8))); 1491*8cc72361SWai Yew CHAY break; 1492*8cc72361SWai Yew CHAY case ADC_NONE: /* Digital I/O */ 1493*8cc72361SWai Yew CHAY data = (!(data & (0x1<<8))); 1494*8cc72361SWai Yew CHAY break; 1495*8cc72361SWai Yew CHAY default: 1496*8cc72361SWai Yew CHAY data = 0; 1497*8cc72361SWai Yew CHAY } 1498*8cc72361SWai Yew CHAY return data; 1499*8cc72361SWai Yew CHAY } 1500*8cc72361SWai Yew CHAY 1501*8cc72361SWai Yew CHAY static int is_adc_input_selected_hendrix(struct hw *hw, enum ADCSRC type) 1502*8cc72361SWai Yew CHAY { 1503*8cc72361SWai Yew CHAY u32 data = 0; 1504*8cc72361SWai Yew CHAY 1505*8cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 1506*8cc72361SWai Yew CHAY switch (type) { 1507*8cc72361SWai Yew CHAY case ADC_MICIN: 1508*8cc72361SWai Yew CHAY data = (data & (0x1 << 7)) ? 1 : 0; 1509*8cc72361SWai Yew CHAY break; 1510*8cc72361SWai Yew CHAY case ADC_LINEIN: 1511*8cc72361SWai Yew CHAY data = (data & (0x1 << 7)) ? 0 : 1; 1512*8cc72361SWai Yew CHAY break; 1513*8cc72361SWai Yew CHAY default: 1514*8cc72361SWai Yew CHAY data = 0; 1515*8cc72361SWai Yew CHAY } 1516*8cc72361SWai Yew CHAY return data; 1517*8cc72361SWai Yew CHAY } 1518*8cc72361SWai Yew CHAY 1519*8cc72361SWai Yew CHAY static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) 1520*8cc72361SWai Yew CHAY { 1521*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1522*8cc72361SWai Yew CHAY 1523*8cc72361SWai Yew CHAY pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id); 1524*8cc72361SWai Yew CHAY if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) { 1525*8cc72361SWai Yew CHAY /* SB055x cards */ 1526*8cc72361SWai Yew CHAY return is_adc_input_selected_SB055x(hw, type); 1527*8cc72361SWai Yew CHAY } else if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) { 1528*8cc72361SWai Yew CHAY /* SB073x cards */ 1529*8cc72361SWai Yew CHAY return is_adc_input_selected_hendrix(hw, type); 1530*8cc72361SWai Yew CHAY } else if ((subsys_id & 0xf000) == 0x6000) { 1531*8cc72361SWai Yew CHAY /* Vista compatible cards */ 1532*8cc72361SWai Yew CHAY return is_adc_input_selected_hendrix(hw, type); 1533*8cc72361SWai Yew CHAY } else { 1534*8cc72361SWai Yew CHAY return is_adc_input_selected_SBx(hw, type); 1535*8cc72361SWai Yew CHAY } 1536*8cc72361SWai Yew CHAY } 1537*8cc72361SWai Yew CHAY 1538*8cc72361SWai Yew CHAY static int 1539*8cc72361SWai Yew CHAY adc_input_select_SB055x(struct hw *hw, enum ADCSRC type, unsigned char boost) 1540*8cc72361SWai Yew CHAY { 1541*8cc72361SWai Yew CHAY u32 data = 0; 1542*8cc72361SWai Yew CHAY 1543*8cc72361SWai Yew CHAY /* 1544*8cc72361SWai Yew CHAY * check and set the following GPIO bits accordingly 1545*8cc72361SWai Yew CHAY * ADC_Gain = GPIO2 1546*8cc72361SWai Yew CHAY * DRM_off = GPIO3 1547*8cc72361SWai Yew CHAY * Mic_Pwr_on = GPIO7 1548*8cc72361SWai Yew CHAY * Digital_IO_Sel = GPIO8 1549*8cc72361SWai Yew CHAY * Mic_Sw = GPIO9 1550*8cc72361SWai Yew CHAY * Aux/MicLine_Sw = GPIO12 1551*8cc72361SWai Yew CHAY */ 1552*8cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 1553*8cc72361SWai Yew CHAY data &= 0xec73; 1554*8cc72361SWai Yew CHAY switch (type) { 1555*8cc72361SWai Yew CHAY case ADC_MICIN: 1556*8cc72361SWai Yew CHAY data |= (0x1<<7) | (0x1<<8) | (0x1<<9) ; 1557*8cc72361SWai Yew CHAY data |= boost ? (0x1<<2) : 0; 1558*8cc72361SWai Yew CHAY break; 1559*8cc72361SWai Yew CHAY case ADC_LINEIN: 1560*8cc72361SWai Yew CHAY data |= (0x1<<8); 1561*8cc72361SWai Yew CHAY break; 1562*8cc72361SWai Yew CHAY case ADC_AUX: 1563*8cc72361SWai Yew CHAY data |= (0x1<<8) | (0x1<<12); 1564*8cc72361SWai Yew CHAY break; 1565*8cc72361SWai Yew CHAY case ADC_NONE: 1566*8cc72361SWai Yew CHAY data |= (0x1<<12); /* set to digital */ 1567*8cc72361SWai Yew CHAY break; 1568*8cc72361SWai Yew CHAY default: 1569*8cc72361SWai Yew CHAY return -1; 1570*8cc72361SWai Yew CHAY } 1571*8cc72361SWai Yew CHAY 1572*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 1573*8cc72361SWai Yew CHAY 1574*8cc72361SWai Yew CHAY return 0; 1575*8cc72361SWai Yew CHAY } 1576*8cc72361SWai Yew CHAY 1577*8cc72361SWai Yew CHAY 1578*8cc72361SWai Yew CHAY static int 1579*8cc72361SWai Yew CHAY adc_input_select_SBx(struct hw *hw, enum ADCSRC type, unsigned char boost) 1580*8cc72361SWai Yew CHAY { 1581*8cc72361SWai Yew CHAY u32 data = 0; 1582*8cc72361SWai Yew CHAY u32 i2c_data = 0; 1583*8cc72361SWai Yew CHAY unsigned int ret = 0; 1584*8cc72361SWai Yew CHAY 1585*8cc72361SWai Yew CHAY if (i2c_unlock(hw)) 1586*8cc72361SWai Yew CHAY return -1; 1587*8cc72361SWai Yew CHAY 1588*8cc72361SWai Yew CHAY do { 1589*8cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 1590*8cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 1591*8cc72361SWai Yew CHAY /* set i2c access mode as Direct Control */ 1592*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); 1593*8cc72361SWai Yew CHAY 1594*8cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 1595*8cc72361SWai Yew CHAY switch (type) { 1596*8cc72361SWai Yew CHAY case ADC_MICIN: 1597*8cc72361SWai Yew CHAY data |= ((0x1 << 7) | (0x1 << 8)); 1598*8cc72361SWai Yew CHAY i2c_data = 0x1; /* Mic-in */ 1599*8cc72361SWai Yew CHAY break; 1600*8cc72361SWai Yew CHAY case ADC_LINEIN: 1601*8cc72361SWai Yew CHAY data &= ~(0x1 << 7); 1602*8cc72361SWai Yew CHAY data |= (0x1 << 8); 1603*8cc72361SWai Yew CHAY i2c_data = 0x2; /* Line-in */ 1604*8cc72361SWai Yew CHAY break; 1605*8cc72361SWai Yew CHAY case ADC_NONE: 1606*8cc72361SWai Yew CHAY data &= ~(0x1 << 8); 1607*8cc72361SWai Yew CHAY i2c_data = 0x0; /* set to Digital */ 1608*8cc72361SWai Yew CHAY break; 1609*8cc72361SWai Yew CHAY default: 1610*8cc72361SWai Yew CHAY i2c_lock(hw); 1611*8cc72361SWai Yew CHAY return -1; 1612*8cc72361SWai Yew CHAY } 1613*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 1614*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 1615*8cc72361SWai Yew CHAY if (boost) { 1616*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 1617*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 1618*8cc72361SWai Yew CHAY } else { 1619*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 1620*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 1621*8cc72361SWai Yew CHAY } 1622*8cc72361SWai Yew CHAY 1623*8cc72361SWai Yew CHAY i2c_lock(hw); 1624*8cc72361SWai Yew CHAY 1625*8cc72361SWai Yew CHAY return 0; 1626*8cc72361SWai Yew CHAY } 1627*8cc72361SWai Yew CHAY 1628*8cc72361SWai Yew CHAY static int 1629*8cc72361SWai Yew CHAY adc_input_select_hendrix(struct hw *hw, enum ADCSRC type, unsigned char boost) 1630*8cc72361SWai Yew CHAY { 1631*8cc72361SWai Yew CHAY u32 data = 0; 1632*8cc72361SWai Yew CHAY u32 i2c_data = 0; 1633*8cc72361SWai Yew CHAY unsigned int ret = 0; 1634*8cc72361SWai Yew CHAY 1635*8cc72361SWai Yew CHAY if (i2c_unlock(hw)) 1636*8cc72361SWai Yew CHAY return -1; 1637*8cc72361SWai Yew CHAY 1638*8cc72361SWai Yew CHAY do { 1639*8cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 1640*8cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 1641*8cc72361SWai Yew CHAY /* set i2c access mode as Direct Control */ 1642*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); 1643*8cc72361SWai Yew CHAY 1644*8cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 1645*8cc72361SWai Yew CHAY switch (type) { 1646*8cc72361SWai Yew CHAY case ADC_MICIN: 1647*8cc72361SWai Yew CHAY data |= (0x1 << 7); 1648*8cc72361SWai Yew CHAY i2c_data = 0x1; /* Mic-in */ 1649*8cc72361SWai Yew CHAY break; 1650*8cc72361SWai Yew CHAY case ADC_LINEIN: 1651*8cc72361SWai Yew CHAY data &= ~(0x1 << 7); 1652*8cc72361SWai Yew CHAY i2c_data = 0x2; /* Line-in */ 1653*8cc72361SWai Yew CHAY break; 1654*8cc72361SWai Yew CHAY default: 1655*8cc72361SWai Yew CHAY i2c_lock(hw); 1656*8cc72361SWai Yew CHAY return -1; 1657*8cc72361SWai Yew CHAY } 1658*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 1659*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 1660*8cc72361SWai Yew CHAY if (boost) { 1661*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 1662*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 1663*8cc72361SWai Yew CHAY } else { 1664*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 1665*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 1666*8cc72361SWai Yew CHAY } 1667*8cc72361SWai Yew CHAY 1668*8cc72361SWai Yew CHAY i2c_lock(hw); 1669*8cc72361SWai Yew CHAY 1670*8cc72361SWai Yew CHAY return 0; 1671*8cc72361SWai Yew CHAY } 1672*8cc72361SWai Yew CHAY 1673*8cc72361SWai Yew CHAY static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) 1674*8cc72361SWai Yew CHAY { 1675*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1676*8cc72361SWai Yew CHAY 1677*8cc72361SWai Yew CHAY pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id); 1678*8cc72361SWai Yew CHAY if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) { 1679*8cc72361SWai Yew CHAY /* SB055x cards */ 1680*8cc72361SWai Yew CHAY return adc_input_select_SB055x(hw, type, (ADC_MICIN == type)); 1681*8cc72361SWai Yew CHAY } else if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) { 1682*8cc72361SWai Yew CHAY /* SB073x cards */ 1683*8cc72361SWai Yew CHAY return adc_input_select_hendrix(hw, type, (ADC_MICIN == type)); 1684*8cc72361SWai Yew CHAY } else if ((subsys_id & 0xf000) == 0x6000) { 1685*8cc72361SWai Yew CHAY /* Vista compatible cards */ 1686*8cc72361SWai Yew CHAY return adc_input_select_hendrix(hw, type, (ADC_MICIN == type)); 1687*8cc72361SWai Yew CHAY } else { 1688*8cc72361SWai Yew CHAY return adc_input_select_SBx(hw, type, (ADC_MICIN == type)); 1689*8cc72361SWai Yew CHAY } 1690*8cc72361SWai Yew CHAY } 1691*8cc72361SWai Yew CHAY 1692*8cc72361SWai Yew CHAY static int adc_init_SB055x(struct hw *hw, int input, int mic20db) 1693*8cc72361SWai Yew CHAY { 1694*8cc72361SWai Yew CHAY return adc_input_select_SB055x(hw, input, mic20db); 1695*8cc72361SWai Yew CHAY } 1696*8cc72361SWai Yew CHAY 1697*8cc72361SWai Yew CHAY static int adc_init_SBx(struct hw *hw, int input, int mic20db) 1698*8cc72361SWai Yew CHAY { 1699*8cc72361SWai Yew CHAY u16 gpioorg; 1700*8cc72361SWai Yew CHAY u16 input_source; 1701*8cc72361SWai Yew CHAY u32 adcdata = 0; 1702*8cc72361SWai Yew CHAY unsigned int ret = 0; 1703*8cc72361SWai Yew CHAY 1704*8cc72361SWai Yew CHAY input_source = 0x100; /* default to analog */ 1705*8cc72361SWai Yew CHAY switch (input) { 1706*8cc72361SWai Yew CHAY case ADC_MICIN: 1707*8cc72361SWai Yew CHAY adcdata = 0x1; 1708*8cc72361SWai Yew CHAY input_source = 0x180; /* set GPIO7 to select Mic */ 1709*8cc72361SWai Yew CHAY break; 1710*8cc72361SWai Yew CHAY case ADC_LINEIN: 1711*8cc72361SWai Yew CHAY adcdata = 0x2; 1712*8cc72361SWai Yew CHAY break; 1713*8cc72361SWai Yew CHAY case ADC_VIDEO: 1714*8cc72361SWai Yew CHAY adcdata = 0x4; 1715*8cc72361SWai Yew CHAY break; 1716*8cc72361SWai Yew CHAY case ADC_AUX: 1717*8cc72361SWai Yew CHAY adcdata = 0x8; 1718*8cc72361SWai Yew CHAY break; 1719*8cc72361SWai Yew CHAY case ADC_NONE: 1720*8cc72361SWai Yew CHAY adcdata = 0x0; 1721*8cc72361SWai Yew CHAY input_source = 0x0; /* set to Digital */ 1722*8cc72361SWai Yew CHAY break; 1723*8cc72361SWai Yew CHAY default: 1724*8cc72361SWai Yew CHAY break; 1725*8cc72361SWai Yew CHAY } 1726*8cc72361SWai Yew CHAY 1727*8cc72361SWai Yew CHAY if (i2c_unlock(hw)) 1728*8cc72361SWai Yew CHAY return -1; 1729*8cc72361SWai Yew CHAY 1730*8cc72361SWai Yew CHAY do { 1731*8cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 1732*8cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 1733*8cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 1734*8cc72361SWai Yew CHAY 1735*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x0e, 0x08); 1736*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x18, 0x0a); 1737*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x28, 0x86); 1738*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, adcdata); 1739*8cc72361SWai Yew CHAY 1740*8cc72361SWai Yew CHAY if (mic20db) { 1741*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xf7); 1742*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xf7); 1743*8cc72361SWai Yew CHAY } else { 1744*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); 1745*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); 1746*8cc72361SWai Yew CHAY } 1747*8cc72361SWai Yew CHAY 1748*8cc72361SWai Yew CHAY if (!(hw_read_20kx(hw, ID0) & 0x100)) 1749*8cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x16, 0x26); 1750*8cc72361SWai Yew CHAY 1751*8cc72361SWai Yew CHAY i2c_lock(hw); 1752*8cc72361SWai Yew CHAY 1753*8cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 1754*8cc72361SWai Yew CHAY gpioorg &= 0xfe7f; 1755*8cc72361SWai Yew CHAY gpioorg |= input_source; 1756*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 1757*8cc72361SWai Yew CHAY 1758*8cc72361SWai Yew CHAY return 0; 1759*8cc72361SWai Yew CHAY } 1760*8cc72361SWai Yew CHAY 1761*8cc72361SWai Yew CHAY static int hw_adc_init(struct hw *hw, const struct adc_conf *info) 1762*8cc72361SWai Yew CHAY { 1763*8cc72361SWai Yew CHAY int err = 0; 1764*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1765*8cc72361SWai Yew CHAY 1766*8cc72361SWai Yew CHAY pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id); 1767*8cc72361SWai Yew CHAY if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) { 1768*8cc72361SWai Yew CHAY /* Sb055x card */ 1769*8cc72361SWai Yew CHAY err = adc_init_SB055x(hw, info->input, info->mic20db); 1770*8cc72361SWai Yew CHAY } else { 1771*8cc72361SWai Yew CHAY err = adc_init_SBx(hw, info->input, info->mic20db); 1772*8cc72361SWai Yew CHAY } 1773*8cc72361SWai Yew CHAY 1774*8cc72361SWai Yew CHAY return err; 1775*8cc72361SWai Yew CHAY } 1776*8cc72361SWai Yew CHAY 1777*8cc72361SWai Yew CHAY static int hw_have_digit_io_switch(struct hw *hw) 1778*8cc72361SWai Yew CHAY { 1779*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1780*8cc72361SWai Yew CHAY 1781*8cc72361SWai Yew CHAY pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id); 1782*8cc72361SWai Yew CHAY /* SB073x and Vista compatible cards have no digit IO switch */ 1783*8cc72361SWai Yew CHAY return !((subsys_id == 0x0029) || (subsys_id == 0x0031) 1784*8cc72361SWai Yew CHAY || ((subsys_id & 0xf000) == 0x6000)); 1785*8cc72361SWai Yew CHAY } 1786*8cc72361SWai Yew CHAY 1787*8cc72361SWai Yew CHAY #define UAA_CFG_PWRSTATUS 0x44 1788*8cc72361SWai Yew CHAY #define UAA_CFG_SPACE_FLAG 0xA0 1789*8cc72361SWai Yew CHAY #define UAA_CORE_CHANGE 0x3FFC 1790*8cc72361SWai Yew CHAY static int uaa_to_xfi(struct pci_dev *pci) 1791*8cc72361SWai Yew CHAY { 1792*8cc72361SWai Yew CHAY unsigned int bar0, bar1, bar2, bar3, bar4, bar5; 1793*8cc72361SWai Yew CHAY unsigned int cmd, irq, cl_size, l_timer, pwr; 1794*8cc72361SWai Yew CHAY unsigned int CTLA, CTLZ, CTLL, CTLX, CTL_, CTLF, CTLi; 1795*8cc72361SWai Yew CHAY unsigned int is_uaa = 0; 1796*8cc72361SWai Yew CHAY unsigned int data[4] = {0}; 1797*8cc72361SWai Yew CHAY unsigned int io_base; 1798*8cc72361SWai Yew CHAY void *mem_base; 1799*8cc72361SWai Yew CHAY int i = 0; 1800*8cc72361SWai Yew CHAY 1801*8cc72361SWai Yew CHAY /* By default, Hendrix card UAA Bar0 should be using memory... */ 1802*8cc72361SWai Yew CHAY io_base = pci_resource_start(pci, 0); 1803*8cc72361SWai Yew CHAY mem_base = ioremap(io_base, pci_resource_len(pci, 0)); 1804*8cc72361SWai Yew CHAY if (NULL == mem_base) 1805*8cc72361SWai Yew CHAY return -ENOENT; 1806*8cc72361SWai Yew CHAY 1807*8cc72361SWai Yew CHAY CTLX = ___constant_swab32(*((unsigned int *)"CTLX")); 1808*8cc72361SWai Yew CHAY CTL_ = ___constant_swab32(*((unsigned int *)"CTL-")); 1809*8cc72361SWai Yew CHAY CTLF = ___constant_swab32(*((unsigned int *)"CTLF")); 1810*8cc72361SWai Yew CHAY CTLi = ___constant_swab32(*((unsigned int *)"CTLi")); 1811*8cc72361SWai Yew CHAY CTLA = ___constant_swab32(*((unsigned int *)"CTLA")); 1812*8cc72361SWai Yew CHAY CTLZ = ___constant_swab32(*((unsigned int *)"CTLZ")); 1813*8cc72361SWai Yew CHAY CTLL = ___constant_swab32(*((unsigned int *)"CTLL")); 1814*8cc72361SWai Yew CHAY 1815*8cc72361SWai Yew CHAY /* Read current mode from Mode Change Register */ 1816*8cc72361SWai Yew CHAY for (i = 0; i < 4; i++) 1817*8cc72361SWai Yew CHAY data[i] = readl(mem_base + UAA_CORE_CHANGE); 1818*8cc72361SWai Yew CHAY 1819*8cc72361SWai Yew CHAY /* Determine current mode... */ 1820*8cc72361SWai Yew CHAY if (data[0] == CTLA) { 1821*8cc72361SWai Yew CHAY is_uaa = ((data[1] == CTLZ && data[2] == CTLL 1822*8cc72361SWai Yew CHAY && data[3] == CTLA) || (data[1] == CTLA 1823*8cc72361SWai Yew CHAY && data[2] == CTLZ && data[3] == CTLL)); 1824*8cc72361SWai Yew CHAY } else if (data[0] == CTLZ) { 1825*8cc72361SWai Yew CHAY is_uaa = (data[1] == CTLL 1826*8cc72361SWai Yew CHAY && data[2] == CTLA && data[3] == CTLA); 1827*8cc72361SWai Yew CHAY } else if (data[0] == CTLL) { 1828*8cc72361SWai Yew CHAY is_uaa = (data[1] == CTLA 1829*8cc72361SWai Yew CHAY && data[2] == CTLA && data[3] == CTLZ); 1830*8cc72361SWai Yew CHAY } else { 1831*8cc72361SWai Yew CHAY is_uaa = 0; 1832*8cc72361SWai Yew CHAY } 1833*8cc72361SWai Yew CHAY 1834*8cc72361SWai Yew CHAY if (!is_uaa) { 1835*8cc72361SWai Yew CHAY /* Not in UAA mode currently. Return directly. */ 1836*8cc72361SWai Yew CHAY iounmap(mem_base); 1837*8cc72361SWai Yew CHAY return 0; 1838*8cc72361SWai Yew CHAY } 1839*8cc72361SWai Yew CHAY 1840*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_0, &bar0); 1841*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_1, &bar1); 1842*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_2, &bar2); 1843*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_3, &bar3); 1844*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_4, &bar4); 1845*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_5, &bar5); 1846*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_INTERRUPT_LINE, &irq); 1847*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_CACHE_LINE_SIZE, &cl_size); 1848*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_LATENCY_TIMER, &l_timer); 1849*8cc72361SWai Yew CHAY pci_read_config_dword(pci, UAA_CFG_PWRSTATUS, &pwr); 1850*8cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_COMMAND, &cmd); 1851*8cc72361SWai Yew CHAY 1852*8cc72361SWai Yew CHAY /* Set up X-Fi core PCI configuration space. */ 1853*8cc72361SWai Yew CHAY /* Switch to X-Fi config space with BAR0 exposed. */ 1854*8cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x87654321); 1855*8cc72361SWai Yew CHAY /* Copy UAA's BAR5 into X-Fi BAR0 */ 1856*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_0, bar5); 1857*8cc72361SWai Yew CHAY /* Switch to X-Fi config space without BAR0 exposed. */ 1858*8cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x12345678); 1859*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, bar1); 1860*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_2, bar2); 1861*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_3, bar3); 1862*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_4, bar4); 1863*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_INTERRUPT_LINE, irq); 1864*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_CACHE_LINE_SIZE, cl_size); 1865*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_LATENCY_TIMER, l_timer); 1866*8cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_PWRSTATUS, pwr); 1867*8cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_COMMAND, cmd); 1868*8cc72361SWai Yew CHAY 1869*8cc72361SWai Yew CHAY /* Switch to X-Fi mode */ 1870*8cc72361SWai Yew CHAY writel(CTLX, (mem_base + UAA_CORE_CHANGE)); 1871*8cc72361SWai Yew CHAY writel(CTL_, (mem_base + UAA_CORE_CHANGE)); 1872*8cc72361SWai Yew CHAY writel(CTLF, (mem_base + UAA_CORE_CHANGE)); 1873*8cc72361SWai Yew CHAY writel(CTLi, (mem_base + UAA_CORE_CHANGE)); 1874*8cc72361SWai Yew CHAY 1875*8cc72361SWai Yew CHAY iounmap(mem_base); 1876*8cc72361SWai Yew CHAY 1877*8cc72361SWai Yew CHAY return 0; 1878*8cc72361SWai Yew CHAY } 1879*8cc72361SWai Yew CHAY 1880*8cc72361SWai Yew CHAY static int hw_card_start(struct hw *hw) 1881*8cc72361SWai Yew CHAY { 1882*8cc72361SWai Yew CHAY int err = 0; 1883*8cc72361SWai Yew CHAY struct pci_dev *pci = hw->pci; 1884*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1885*8cc72361SWai Yew CHAY unsigned int dma_mask = 0; 1886*8cc72361SWai Yew CHAY 1887*8cc72361SWai Yew CHAY err = pci_enable_device(pci); 1888*8cc72361SWai Yew CHAY if (err < 0) 1889*8cc72361SWai Yew CHAY return err; 1890*8cc72361SWai Yew CHAY 1891*8cc72361SWai Yew CHAY /* Set DMA transfer mask */ 1892*8cc72361SWai Yew CHAY dma_mask = CT_XFI_DMA_MASK; 1893*8cc72361SWai Yew CHAY if (pci_set_dma_mask(pci, dma_mask) < 0 || 1894*8cc72361SWai Yew CHAY pci_set_consistent_dma_mask(pci, dma_mask) < 0) { 1895*8cc72361SWai Yew CHAY printk(KERN_ERR "architecture does not support PCI " 1896*8cc72361SWai Yew CHAY "busmaster DMA with mask 0x%x\n", dma_mask); 1897*8cc72361SWai Yew CHAY err = -ENXIO; 1898*8cc72361SWai Yew CHAY goto error1; 1899*8cc72361SWai Yew CHAY } 1900*8cc72361SWai Yew CHAY 1901*8cc72361SWai Yew CHAY err = pci_request_regions(pci, "XFi"); 1902*8cc72361SWai Yew CHAY if (err < 0) 1903*8cc72361SWai Yew CHAY goto error1; 1904*8cc72361SWai Yew CHAY 1905*8cc72361SWai Yew CHAY /* Switch to X-Fi mode from UAA mode if neeeded */ 1906*8cc72361SWai Yew CHAY pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsys_id); 1907*8cc72361SWai Yew CHAY if ((0x5 == pci->device) && (0x6000 == (subsys_id & 0x6000))) { 1908*8cc72361SWai Yew CHAY err = uaa_to_xfi(pci); 1909*8cc72361SWai Yew CHAY if (err) 1910*8cc72361SWai Yew CHAY goto error2; 1911*8cc72361SWai Yew CHAY 1912*8cc72361SWai Yew CHAY hw->io_base = pci_resource_start(pci, 5); 1913*8cc72361SWai Yew CHAY } else { 1914*8cc72361SWai Yew CHAY hw->io_base = pci_resource_start(pci, 0); 1915*8cc72361SWai Yew CHAY } 1916*8cc72361SWai Yew CHAY 1917*8cc72361SWai Yew CHAY /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED, 1918*8cc72361SWai Yew CHAY atc->chip_details->nm_card, hw))) { 1919*8cc72361SWai Yew CHAY goto error2; 1920*8cc72361SWai Yew CHAY } 1921*8cc72361SWai Yew CHAY hw->irq = pci->irq; 1922*8cc72361SWai Yew CHAY */ 1923*8cc72361SWai Yew CHAY 1924*8cc72361SWai Yew CHAY pci_set_master(pci); 1925*8cc72361SWai Yew CHAY 1926*8cc72361SWai Yew CHAY return 0; 1927*8cc72361SWai Yew CHAY 1928*8cc72361SWai Yew CHAY error2: 1929*8cc72361SWai Yew CHAY pci_release_regions(pci); 1930*8cc72361SWai Yew CHAY hw->io_base = 0; 1931*8cc72361SWai Yew CHAY error1: 1932*8cc72361SWai Yew CHAY pci_disable_device(pci); 1933*8cc72361SWai Yew CHAY return err; 1934*8cc72361SWai Yew CHAY } 1935*8cc72361SWai Yew CHAY 1936*8cc72361SWai Yew CHAY static int hw_card_stop(struct hw *hw) 1937*8cc72361SWai Yew CHAY { 1938*8cc72361SWai Yew CHAY /* TODO: Disable interrupt and so on... */ 1939*8cc72361SWai Yew CHAY return 0; 1940*8cc72361SWai Yew CHAY } 1941*8cc72361SWai Yew CHAY 1942*8cc72361SWai Yew CHAY static int hw_card_shutdown(struct hw *hw) 1943*8cc72361SWai Yew CHAY { 1944*8cc72361SWai Yew CHAY if (hw->irq >= 0) 1945*8cc72361SWai Yew CHAY free_irq(hw->irq, hw); 1946*8cc72361SWai Yew CHAY 1947*8cc72361SWai Yew CHAY hw->irq = -1; 1948*8cc72361SWai Yew CHAY 1949*8cc72361SWai Yew CHAY if (NULL != ((void *)hw->mem_base)) 1950*8cc72361SWai Yew CHAY iounmap((void *)hw->mem_base); 1951*8cc72361SWai Yew CHAY 1952*8cc72361SWai Yew CHAY hw->mem_base = (unsigned long)NULL; 1953*8cc72361SWai Yew CHAY 1954*8cc72361SWai Yew CHAY if (hw->io_base) 1955*8cc72361SWai Yew CHAY pci_release_regions(hw->pci); 1956*8cc72361SWai Yew CHAY 1957*8cc72361SWai Yew CHAY hw->io_base = 0; 1958*8cc72361SWai Yew CHAY 1959*8cc72361SWai Yew CHAY pci_disable_device(hw->pci); 1960*8cc72361SWai Yew CHAY 1961*8cc72361SWai Yew CHAY return 0; 1962*8cc72361SWai Yew CHAY } 1963*8cc72361SWai Yew CHAY 1964*8cc72361SWai Yew CHAY static int hw_card_init(struct hw *hw, struct card_conf *info) 1965*8cc72361SWai Yew CHAY { 1966*8cc72361SWai Yew CHAY int err; 1967*8cc72361SWai Yew CHAY unsigned int gctl; 1968*8cc72361SWai Yew CHAY u16 subsys_id = 0; 1969*8cc72361SWai Yew CHAY u32 data = 0; 1970*8cc72361SWai Yew CHAY struct dac_conf dac_info = {0}; 1971*8cc72361SWai Yew CHAY struct adc_conf adc_info = {0}; 1972*8cc72361SWai Yew CHAY struct daio_conf daio_info = {0}; 1973*8cc72361SWai Yew CHAY struct trn_conf trn_info = {0}; 1974*8cc72361SWai Yew CHAY 1975*8cc72361SWai Yew CHAY /* Get PCI io port base address and do Hendrix switch if needed. */ 1976*8cc72361SWai Yew CHAY if (!hw->io_base) { 1977*8cc72361SWai Yew CHAY err = hw_card_start(hw); 1978*8cc72361SWai Yew CHAY if (err) 1979*8cc72361SWai Yew CHAY return err; 1980*8cc72361SWai Yew CHAY } 1981*8cc72361SWai Yew CHAY 1982*8cc72361SWai Yew CHAY /* PLL init */ 1983*8cc72361SWai Yew CHAY err = hw_pll_init(hw, info->rsr); 1984*8cc72361SWai Yew CHAY if (err < 0) 1985*8cc72361SWai Yew CHAY return err; 1986*8cc72361SWai Yew CHAY 1987*8cc72361SWai Yew CHAY /* kick off auto-init */ 1988*8cc72361SWai Yew CHAY err = hw_auto_init(hw); 1989*8cc72361SWai Yew CHAY if (err < 0) 1990*8cc72361SWai Yew CHAY return err; 1991*8cc72361SWai Yew CHAY 1992*8cc72361SWai Yew CHAY /* Enable audio ring */ 1993*8cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 1994*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAC, 1); 1995*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_DBP, 1); 1996*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_TBP, 1); 1997*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_FBP, 1); 1998*8cc72361SWai Yew CHAY set_field(&gctl, GCTL_ET, 1); 1999*8cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 2000*8cc72361SWai Yew CHAY mdelay(10); 2001*8cc72361SWai Yew CHAY 2002*8cc72361SWai Yew CHAY /* Reset all global pending interrupts */ 2003*8cc72361SWai Yew CHAY hw_write_20kx(hw, GIE, 0); 2004*8cc72361SWai Yew CHAY /* Reset all SRC pending interrupts */ 2005*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCIP, 0); 2006*8cc72361SWai Yew CHAY mdelay(30); 2007*8cc72361SWai Yew CHAY 2008*8cc72361SWai Yew CHAY pci_read_config_word(hw->pci, PCI_SUBSYSTEM_ID, &subsys_id); 2009*8cc72361SWai Yew CHAY /* Detect the card ID and configure GPIO accordingly. */ 2010*8cc72361SWai Yew CHAY if ((subsys_id == 0x0022) || (subsys_id == 0x002F)) { 2011*8cc72361SWai Yew CHAY /* SB055x cards */ 2012*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x13fe); 2013*8cc72361SWai Yew CHAY } else if ((subsys_id == 0x0029) || (subsys_id == 0x0031)) { 2014*8cc72361SWai Yew CHAY /* SB073x cards */ 2015*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x00e6); 2016*8cc72361SWai Yew CHAY } else if ((subsys_id & 0xf000) == 0x6000) { 2017*8cc72361SWai Yew CHAY /* Vista compatible cards */ 2018*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x00c2); 2019*8cc72361SWai Yew CHAY } else { 2020*8cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x01e6); 2021*8cc72361SWai Yew CHAY } 2022*8cc72361SWai Yew CHAY 2023*8cc72361SWai Yew CHAY trn_info.vm_pgt_phys = info->vm_pgt_phys; 2024*8cc72361SWai Yew CHAY err = hw_trn_init(hw, &trn_info); 2025*8cc72361SWai Yew CHAY if (err < 0) 2026*8cc72361SWai Yew CHAY return err; 2027*8cc72361SWai Yew CHAY 2028*8cc72361SWai Yew CHAY daio_info.msr = info->msr; 2029*8cc72361SWai Yew CHAY err = hw_daio_init(hw, &daio_info); 2030*8cc72361SWai Yew CHAY if (err < 0) 2031*8cc72361SWai Yew CHAY return err; 2032*8cc72361SWai Yew CHAY 2033*8cc72361SWai Yew CHAY dac_info.msr = info->msr; 2034*8cc72361SWai Yew CHAY err = hw_dac_init(hw, &dac_info); 2035*8cc72361SWai Yew CHAY if (err < 0) 2036*8cc72361SWai Yew CHAY return err; 2037*8cc72361SWai Yew CHAY 2038*8cc72361SWai Yew CHAY adc_info.msr = info->msr; 2039*8cc72361SWai Yew CHAY adc_info.input = ADC_LINEIN; 2040*8cc72361SWai Yew CHAY adc_info.mic20db = 0; 2041*8cc72361SWai Yew CHAY err = hw_adc_init(hw, &adc_info); 2042*8cc72361SWai Yew CHAY if (err < 0) 2043*8cc72361SWai Yew CHAY return err; 2044*8cc72361SWai Yew CHAY 2045*8cc72361SWai Yew CHAY data = hw_read_20kx(hw, SRCMCTL); 2046*8cc72361SWai Yew CHAY data |= 0x1; /* Enables input from the audio ring */ 2047*8cc72361SWai Yew CHAY hw_write_20kx(hw, SRCMCTL, data); 2048*8cc72361SWai Yew CHAY 2049*8cc72361SWai Yew CHAY return 0; 2050*8cc72361SWai Yew CHAY } 2051*8cc72361SWai Yew CHAY 2052*8cc72361SWai Yew CHAY static u32 hw_read_20kx(struct hw *hw, u32 reg) 2053*8cc72361SWai Yew CHAY { 2054*8cc72361SWai Yew CHAY u32 value; 2055*8cc72361SWai Yew CHAY unsigned long flags; 2056*8cc72361SWai Yew CHAY 2057*8cc72361SWai Yew CHAY spin_lock_irqsave( 2058*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 2059*8cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x0); 2060*8cc72361SWai Yew CHAY value = inl(hw->io_base + 0x4); 2061*8cc72361SWai Yew CHAY spin_unlock_irqrestore( 2062*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 2063*8cc72361SWai Yew CHAY 2064*8cc72361SWai Yew CHAY return value; 2065*8cc72361SWai Yew CHAY } 2066*8cc72361SWai Yew CHAY 2067*8cc72361SWai Yew CHAY static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) 2068*8cc72361SWai Yew CHAY { 2069*8cc72361SWai Yew CHAY unsigned long flags; 2070*8cc72361SWai Yew CHAY 2071*8cc72361SWai Yew CHAY spin_lock_irqsave( 2072*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 2073*8cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x0); 2074*8cc72361SWai Yew CHAY outl(data, hw->io_base + 0x4); 2075*8cc72361SWai Yew CHAY spin_unlock_irqrestore( 2076*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 2077*8cc72361SWai Yew CHAY 2078*8cc72361SWai Yew CHAY } 2079*8cc72361SWai Yew CHAY 2080*8cc72361SWai Yew CHAY static u32 hw_read_pci(struct hw *hw, u32 reg) 2081*8cc72361SWai Yew CHAY { 2082*8cc72361SWai Yew CHAY u32 value; 2083*8cc72361SWai Yew CHAY unsigned long flags; 2084*8cc72361SWai Yew CHAY 2085*8cc72361SWai Yew CHAY spin_lock_irqsave( 2086*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 2087*8cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x10); 2088*8cc72361SWai Yew CHAY value = inl(hw->io_base + 0x14); 2089*8cc72361SWai Yew CHAY spin_unlock_irqrestore( 2090*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 2091*8cc72361SWai Yew CHAY 2092*8cc72361SWai Yew CHAY return value; 2093*8cc72361SWai Yew CHAY } 2094*8cc72361SWai Yew CHAY 2095*8cc72361SWai Yew CHAY static void hw_write_pci(struct hw *hw, u32 reg, u32 data) 2096*8cc72361SWai Yew CHAY { 2097*8cc72361SWai Yew CHAY unsigned long flags; 2098*8cc72361SWai Yew CHAY 2099*8cc72361SWai Yew CHAY spin_lock_irqsave( 2100*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 2101*8cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x10); 2102*8cc72361SWai Yew CHAY outl(data, hw->io_base + 0x14); 2103*8cc72361SWai Yew CHAY spin_unlock_irqrestore( 2104*8cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 2105*8cc72361SWai Yew CHAY } 2106*8cc72361SWai Yew CHAY 2107*8cc72361SWai Yew CHAY int create_20k1_hw_obj(struct hw **rhw) 2108*8cc72361SWai Yew CHAY { 2109*8cc72361SWai Yew CHAY struct hw *hw; 2110*8cc72361SWai Yew CHAY struct hw20k1 *hw20k1; 2111*8cc72361SWai Yew CHAY 2112*8cc72361SWai Yew CHAY *rhw = NULL; 2113*8cc72361SWai Yew CHAY hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL); 2114*8cc72361SWai Yew CHAY if (NULL == hw20k1) 2115*8cc72361SWai Yew CHAY return -ENOMEM; 2116*8cc72361SWai Yew CHAY 2117*8cc72361SWai Yew CHAY spin_lock_init(&hw20k1->reg_20k1_lock); 2118*8cc72361SWai Yew CHAY spin_lock_init(&hw20k1->reg_pci_lock); 2119*8cc72361SWai Yew CHAY 2120*8cc72361SWai Yew CHAY hw = &hw20k1->hw; 2121*8cc72361SWai Yew CHAY 2122*8cc72361SWai Yew CHAY hw->io_base = 0; 2123*8cc72361SWai Yew CHAY hw->mem_base = (unsigned long)NULL; 2124*8cc72361SWai Yew CHAY hw->irq = -1; 2125*8cc72361SWai Yew CHAY 2126*8cc72361SWai Yew CHAY hw->card_init = hw_card_init; 2127*8cc72361SWai Yew CHAY hw->card_stop = hw_card_stop; 2128*8cc72361SWai Yew CHAY hw->pll_init = hw_pll_init; 2129*8cc72361SWai Yew CHAY hw->is_adc_source_selected = hw_is_adc_input_selected; 2130*8cc72361SWai Yew CHAY hw->select_adc_source = hw_adc_input_select; 2131*8cc72361SWai Yew CHAY hw->have_digit_io_switch = hw_have_digit_io_switch; 2132*8cc72361SWai Yew CHAY 2133*8cc72361SWai Yew CHAY hw->src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk; 2134*8cc72361SWai Yew CHAY hw->src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk; 2135*8cc72361SWai Yew CHAY hw->src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk; 2136*8cc72361SWai Yew CHAY hw->src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk; 2137*8cc72361SWai Yew CHAY hw->src_set_state = src_set_state; 2138*8cc72361SWai Yew CHAY hw->src_set_bm = src_set_bm; 2139*8cc72361SWai Yew CHAY hw->src_set_rsr = src_set_rsr; 2140*8cc72361SWai Yew CHAY hw->src_set_sf = src_set_sf; 2141*8cc72361SWai Yew CHAY hw->src_set_wr = src_set_wr; 2142*8cc72361SWai Yew CHAY hw->src_set_pm = src_set_pm; 2143*8cc72361SWai Yew CHAY hw->src_set_rom = src_set_rom; 2144*8cc72361SWai Yew CHAY hw->src_set_vo = src_set_vo; 2145*8cc72361SWai Yew CHAY hw->src_set_st = src_set_st; 2146*8cc72361SWai Yew CHAY hw->src_set_ie = src_set_ie; 2147*8cc72361SWai Yew CHAY hw->src_set_ilsz = src_set_ilsz; 2148*8cc72361SWai Yew CHAY hw->src_set_bp = src_set_bp; 2149*8cc72361SWai Yew CHAY hw->src_set_cisz = src_set_cisz; 2150*8cc72361SWai Yew CHAY hw->src_set_ca = src_set_ca; 2151*8cc72361SWai Yew CHAY hw->src_set_sa = src_set_sa; 2152*8cc72361SWai Yew CHAY hw->src_set_la = src_set_la; 2153*8cc72361SWai Yew CHAY hw->src_set_pitch = src_set_pitch; 2154*8cc72361SWai Yew CHAY hw->src_set_dirty = src_set_dirty; 2155*8cc72361SWai Yew CHAY hw->src_set_clear_zbufs = src_set_clear_zbufs; 2156*8cc72361SWai Yew CHAY hw->src_set_dirty_all = src_set_dirty_all; 2157*8cc72361SWai Yew CHAY hw->src_commit_write = src_commit_write; 2158*8cc72361SWai Yew CHAY hw->src_get_ca = src_get_ca; 2159*8cc72361SWai Yew CHAY hw->src_get_dirty = src_get_dirty; 2160*8cc72361SWai Yew CHAY hw->src_dirty_conj_mask = src_dirty_conj_mask; 2161*8cc72361SWai Yew CHAY hw->src_mgr_enbs_src = src_mgr_enbs_src; 2162*8cc72361SWai Yew CHAY hw->src_mgr_enb_src = src_mgr_enb_src; 2163*8cc72361SWai Yew CHAY hw->src_mgr_dsb_src = src_mgr_dsb_src; 2164*8cc72361SWai Yew CHAY hw->src_mgr_commit_write = src_mgr_commit_write; 2165*8cc72361SWai Yew CHAY 2166*8cc72361SWai Yew CHAY hw->srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk; 2167*8cc72361SWai Yew CHAY hw->srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk; 2168*8cc72361SWai Yew CHAY hw->srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc; 2169*8cc72361SWai Yew CHAY hw->srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser; 2170*8cc72361SWai Yew CHAY hw->srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt; 2171*8cc72361SWai Yew CHAY hw->srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr; 2172*8cc72361SWai Yew CHAY hw->srcimp_mgr_commit_write = srcimp_mgr_commit_write; 2173*8cc72361SWai Yew CHAY 2174*8cc72361SWai Yew CHAY hw->amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk; 2175*8cc72361SWai Yew CHAY hw->amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk; 2176*8cc72361SWai Yew CHAY hw->amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk; 2177*8cc72361SWai Yew CHAY hw->amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk; 2178*8cc72361SWai Yew CHAY hw->amixer_set_mode = amixer_set_mode; 2179*8cc72361SWai Yew CHAY hw->amixer_set_iv = amixer_set_iv; 2180*8cc72361SWai Yew CHAY hw->amixer_set_x = amixer_set_x; 2181*8cc72361SWai Yew CHAY hw->amixer_set_y = amixer_set_y; 2182*8cc72361SWai Yew CHAY hw->amixer_set_sadr = amixer_set_sadr; 2183*8cc72361SWai Yew CHAY hw->amixer_set_se = amixer_set_se; 2184*8cc72361SWai Yew CHAY hw->amixer_set_dirty = amixer_set_dirty; 2185*8cc72361SWai Yew CHAY hw->amixer_set_dirty_all = amixer_set_dirty_all; 2186*8cc72361SWai Yew CHAY hw->amixer_commit_write = amixer_commit_write; 2187*8cc72361SWai Yew CHAY hw->amixer_get_y = amixer_get_y; 2188*8cc72361SWai Yew CHAY hw->amixer_get_dirty = amixer_get_dirty; 2189*8cc72361SWai Yew CHAY 2190*8cc72361SWai Yew CHAY hw->dai_get_ctrl_blk = dai_get_ctrl_blk; 2191*8cc72361SWai Yew CHAY hw->dai_put_ctrl_blk = dai_put_ctrl_blk; 2192*8cc72361SWai Yew CHAY hw->dai_srt_set_srco = dai_srt_set_srcr; 2193*8cc72361SWai Yew CHAY hw->dai_srt_set_srcm = dai_srt_set_srcl; 2194*8cc72361SWai Yew CHAY hw->dai_srt_set_rsr = dai_srt_set_rsr; 2195*8cc72361SWai Yew CHAY hw->dai_srt_set_drat = dai_srt_set_drat; 2196*8cc72361SWai Yew CHAY hw->dai_srt_set_ec = dai_srt_set_ec; 2197*8cc72361SWai Yew CHAY hw->dai_srt_set_et = dai_srt_set_et; 2198*8cc72361SWai Yew CHAY hw->dai_commit_write = dai_commit_write; 2199*8cc72361SWai Yew CHAY 2200*8cc72361SWai Yew CHAY hw->dao_get_ctrl_blk = dao_get_ctrl_blk; 2201*8cc72361SWai Yew CHAY hw->dao_put_ctrl_blk = dao_put_ctrl_blk; 2202*8cc72361SWai Yew CHAY hw->dao_set_spos = dao_set_spos; 2203*8cc72361SWai Yew CHAY hw->dao_commit_write = dao_commit_write; 2204*8cc72361SWai Yew CHAY hw->dao_get_spos = dao_get_spos; 2205*8cc72361SWai Yew CHAY 2206*8cc72361SWai Yew CHAY hw->daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk; 2207*8cc72361SWai Yew CHAY hw->daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk; 2208*8cc72361SWai Yew CHAY hw->daio_mgr_enb_dai = daio_mgr_enb_dai; 2209*8cc72361SWai Yew CHAY hw->daio_mgr_dsb_dai = daio_mgr_dsb_dai; 2210*8cc72361SWai Yew CHAY hw->daio_mgr_enb_dao = daio_mgr_enb_dao; 2211*8cc72361SWai Yew CHAY hw->daio_mgr_dsb_dao = daio_mgr_dsb_dao; 2212*8cc72361SWai Yew CHAY hw->daio_mgr_dao_init = daio_mgr_dao_init; 2213*8cc72361SWai Yew CHAY hw->daio_mgr_set_imaparc = daio_mgr_set_imaparc; 2214*8cc72361SWai Yew CHAY hw->daio_mgr_set_imapnxt = daio_mgr_set_imapnxt; 2215*8cc72361SWai Yew CHAY hw->daio_mgr_set_imapaddr = daio_mgr_set_imapaddr; 2216*8cc72361SWai Yew CHAY hw->daio_mgr_commit_write = daio_mgr_commit_write; 2217*8cc72361SWai Yew CHAY 2218*8cc72361SWai Yew CHAY *rhw = hw; 2219*8cc72361SWai Yew CHAY 2220*8cc72361SWai Yew CHAY return 0; 2221*8cc72361SWai Yew CHAY } 2222*8cc72361SWai Yew CHAY 2223*8cc72361SWai Yew CHAY int destroy_20k1_hw_obj(struct hw *hw) 2224*8cc72361SWai Yew CHAY { 2225*8cc72361SWai Yew CHAY if (hw->io_base) 2226*8cc72361SWai Yew CHAY hw_card_shutdown(hw); 2227*8cc72361SWai Yew CHAY 2228*8cc72361SWai Yew CHAY kfree(container_of(hw, struct hw20k1, hw)); 2229*8cc72361SWai Yew CHAY return 0; 2230*8cc72361SWai Yew CHAY } 2231