18cc72361SWai Yew CHAY /** 28cc72361SWai Yew CHAY * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 38cc72361SWai Yew CHAY * 48cc72361SWai Yew CHAY * This source file is released under GPL v2 license (no other versions). 58cc72361SWai Yew CHAY * See the COPYING file included in the main directory of this source 68cc72361SWai Yew CHAY * distribution for the license terms and conditions. 78cc72361SWai Yew CHAY * 88cc72361SWai Yew CHAY * @File cthw20k1.c 98cc72361SWai Yew CHAY * 108cc72361SWai Yew CHAY * @Brief 118cc72361SWai Yew CHAY * This file contains the implementation of hardware access methord for 20k1. 128cc72361SWai Yew CHAY * 138cc72361SWai Yew CHAY * @Author Liu Chun 148cc72361SWai Yew CHAY * @Date Jun 24 2008 158cc72361SWai Yew CHAY * 168cc72361SWai Yew CHAY */ 178cc72361SWai Yew CHAY 188cc72361SWai Yew CHAY #include <linux/types.h> 198cc72361SWai Yew CHAY #include <linux/slab.h> 208cc72361SWai Yew CHAY #include <linux/pci.h> 218cc72361SWai Yew CHAY #include <linux/io.h> 228cc72361SWai Yew CHAY #include <linux/string.h> 238cc72361SWai Yew CHAY #include <linux/spinlock.h> 248cc72361SWai Yew CHAY #include <linux/kernel.h> 258cc72361SWai Yew CHAY #include <linux/interrupt.h> 26d0da727eSTakashi Iwai #include <linux/delay.h> 276d74b86dSTakashi Iwai #include "cthw20k1.h" 286d74b86dSTakashi Iwai #include "ct20k1reg.h" 298cc72361SWai Yew CHAY 306d74b86dSTakashi Iwai #if BITS_PER_LONG == 32 316d74b86dSTakashi Iwai #define CT_XFI_DMA_MASK DMA_BIT_MASK(32) /* 32 bit PTE */ 326d74b86dSTakashi Iwai #else 336d74b86dSTakashi Iwai #define CT_XFI_DMA_MASK DMA_BIT_MASK(64) /* 64 bit PTE */ 346d74b86dSTakashi Iwai #endif 358cc72361SWai Yew CHAY 368cc72361SWai Yew CHAY struct hw20k1 { 378cc72361SWai Yew CHAY struct hw hw; 388cc72361SWai Yew CHAY spinlock_t reg_20k1_lock; 398cc72361SWai Yew CHAY spinlock_t reg_pci_lock; 408cc72361SWai Yew CHAY }; 418cc72361SWai Yew CHAY 428cc72361SWai Yew CHAY static u32 hw_read_20kx(struct hw *hw, u32 reg); 438cc72361SWai Yew CHAY static void hw_write_20kx(struct hw *hw, u32 reg, u32 data); 448cc72361SWai Yew CHAY static u32 hw_read_pci(struct hw *hw, u32 reg); 458cc72361SWai Yew CHAY static void hw_write_pci(struct hw *hw, u32 reg, u32 data); 468cc72361SWai Yew CHAY 478cc72361SWai Yew CHAY /* 488cc72361SWai Yew CHAY * Type definition block. 498cc72361SWai Yew CHAY * The layout of control structures can be directly applied on 20k2 chip. 508cc72361SWai Yew CHAY */ 518cc72361SWai Yew CHAY 528cc72361SWai Yew CHAY /* 538cc72361SWai Yew CHAY * SRC control block definitions. 548cc72361SWai Yew CHAY */ 558cc72361SWai Yew CHAY 568cc72361SWai Yew CHAY /* SRC resource control block */ 578cc72361SWai Yew CHAY #define SRCCTL_STATE 0x00000007 588cc72361SWai Yew CHAY #define SRCCTL_BM 0x00000008 598cc72361SWai Yew CHAY #define SRCCTL_RSR 0x00000030 608cc72361SWai Yew CHAY #define SRCCTL_SF 0x000001C0 618cc72361SWai Yew CHAY #define SRCCTL_WR 0x00000200 628cc72361SWai Yew CHAY #define SRCCTL_PM 0x00000400 638cc72361SWai Yew CHAY #define SRCCTL_ROM 0x00001800 648cc72361SWai Yew CHAY #define SRCCTL_VO 0x00002000 658cc72361SWai Yew CHAY #define SRCCTL_ST 0x00004000 668cc72361SWai Yew CHAY #define SRCCTL_IE 0x00008000 678cc72361SWai Yew CHAY #define SRCCTL_ILSZ 0x000F0000 688cc72361SWai Yew CHAY #define SRCCTL_BP 0x00100000 698cc72361SWai Yew CHAY 708cc72361SWai Yew CHAY #define SRCCCR_CISZ 0x000007FF 718cc72361SWai Yew CHAY #define SRCCCR_CWA 0x001FF800 728cc72361SWai Yew CHAY #define SRCCCR_D 0x00200000 738cc72361SWai Yew CHAY #define SRCCCR_RS 0x01C00000 748cc72361SWai Yew CHAY #define SRCCCR_NAL 0x3E000000 758cc72361SWai Yew CHAY #define SRCCCR_RA 0xC0000000 768cc72361SWai Yew CHAY 778cc72361SWai Yew CHAY #define SRCCA_CA 0x03FFFFFF 788cc72361SWai Yew CHAY #define SRCCA_RS 0x1C000000 798cc72361SWai Yew CHAY #define SRCCA_NAL 0xE0000000 808cc72361SWai Yew CHAY 818cc72361SWai Yew CHAY #define SRCSA_SA 0x03FFFFFF 828cc72361SWai Yew CHAY 838cc72361SWai Yew CHAY #define SRCLA_LA 0x03FFFFFF 848cc72361SWai Yew CHAY 858cc72361SWai Yew CHAY /* Mixer Parameter Ring ram Low and Hight register. 868cc72361SWai Yew CHAY * Fixed-point value in 8.24 format for parameter channel */ 878cc72361SWai Yew CHAY #define MPRLH_PITCH 0xFFFFFFFF 888cc72361SWai Yew CHAY 898cc72361SWai Yew CHAY /* SRC resource register dirty flags */ 908cc72361SWai Yew CHAY union src_dirty { 918cc72361SWai Yew CHAY struct { 928cc72361SWai Yew CHAY u16 ctl:1; 938cc72361SWai Yew CHAY u16 ccr:1; 948cc72361SWai Yew CHAY u16 sa:1; 958cc72361SWai Yew CHAY u16 la:1; 968cc72361SWai Yew CHAY u16 ca:1; 978cc72361SWai Yew CHAY u16 mpr:1; 988cc72361SWai Yew CHAY u16 czbfs:1; /* Clear Z-Buffers */ 998cc72361SWai Yew CHAY u16 rsv:9; 1008cc72361SWai Yew CHAY } bf; 1018cc72361SWai Yew CHAY u16 data; 1028cc72361SWai Yew CHAY }; 1038cc72361SWai Yew CHAY 1048cc72361SWai Yew CHAY struct src_rsc_ctrl_blk { 1058cc72361SWai Yew CHAY unsigned int ctl; 1068cc72361SWai Yew CHAY unsigned int ccr; 1078cc72361SWai Yew CHAY unsigned int ca; 1088cc72361SWai Yew CHAY unsigned int sa; 1098cc72361SWai Yew CHAY unsigned int la; 1108cc72361SWai Yew CHAY unsigned int mpr; 1118cc72361SWai Yew CHAY union src_dirty dirty; 1128cc72361SWai Yew CHAY }; 1138cc72361SWai Yew CHAY 1148cc72361SWai Yew CHAY /* SRC manager control block */ 1158cc72361SWai Yew CHAY union src_mgr_dirty { 1168cc72361SWai Yew CHAY struct { 1178cc72361SWai Yew CHAY u16 enb0:1; 1188cc72361SWai Yew CHAY u16 enb1:1; 1198cc72361SWai Yew CHAY u16 enb2:1; 1208cc72361SWai Yew CHAY u16 enb3:1; 1218cc72361SWai Yew CHAY u16 enb4:1; 1228cc72361SWai Yew CHAY u16 enb5:1; 1238cc72361SWai Yew CHAY u16 enb6:1; 1248cc72361SWai Yew CHAY u16 enb7:1; 1258cc72361SWai Yew CHAY u16 enbsa:1; 1268cc72361SWai Yew CHAY u16 rsv:7; 1278cc72361SWai Yew CHAY } bf; 1288cc72361SWai Yew CHAY u16 data; 1298cc72361SWai Yew CHAY }; 1308cc72361SWai Yew CHAY 1318cc72361SWai Yew CHAY struct src_mgr_ctrl_blk { 1328cc72361SWai Yew CHAY unsigned int enbsa; 1338cc72361SWai Yew CHAY unsigned int enb[8]; 1348cc72361SWai Yew CHAY union src_mgr_dirty dirty; 1358cc72361SWai Yew CHAY }; 1368cc72361SWai Yew CHAY 1378cc72361SWai Yew CHAY /* SRCIMP manager control block */ 1388cc72361SWai Yew CHAY #define SRCAIM_ARC 0x00000FFF 1398cc72361SWai Yew CHAY #define SRCAIM_NXT 0x00FF0000 1408cc72361SWai Yew CHAY #define SRCAIM_SRC 0xFF000000 1418cc72361SWai Yew CHAY 1428cc72361SWai Yew CHAY struct srcimap { 1438cc72361SWai Yew CHAY unsigned int srcaim; 1448cc72361SWai Yew CHAY unsigned int idx; 1458cc72361SWai Yew CHAY }; 1468cc72361SWai Yew CHAY 1478cc72361SWai Yew CHAY /* SRCIMP manager register dirty flags */ 1488cc72361SWai Yew CHAY union srcimp_mgr_dirty { 1498cc72361SWai Yew CHAY struct { 1508cc72361SWai Yew CHAY u16 srcimap:1; 1518cc72361SWai Yew CHAY u16 rsv:15; 1528cc72361SWai Yew CHAY } bf; 1538cc72361SWai Yew CHAY u16 data; 1548cc72361SWai Yew CHAY }; 1558cc72361SWai Yew CHAY 1568cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk { 1578cc72361SWai Yew CHAY struct srcimap srcimap; 1588cc72361SWai Yew CHAY union srcimp_mgr_dirty dirty; 1598cc72361SWai Yew CHAY }; 1608cc72361SWai Yew CHAY 1618cc72361SWai Yew CHAY /* 1628cc72361SWai Yew CHAY * Function implementation block. 1638cc72361SWai Yew CHAY */ 1648cc72361SWai Yew CHAY 1658cc72361SWai Yew CHAY static int src_get_rsc_ctrl_blk(void **rblk) 1668cc72361SWai Yew CHAY { 1678cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *blk; 1688cc72361SWai Yew CHAY 1698cc72361SWai Yew CHAY *rblk = NULL; 1708cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 17135ebf6e7STakashi Iwai if (!blk) 1728cc72361SWai Yew CHAY return -ENOMEM; 1738cc72361SWai Yew CHAY 1748cc72361SWai Yew CHAY *rblk = blk; 1758cc72361SWai Yew CHAY 1768cc72361SWai Yew CHAY return 0; 1778cc72361SWai Yew CHAY } 1788cc72361SWai Yew CHAY 1798cc72361SWai Yew CHAY static int src_put_rsc_ctrl_blk(void *blk) 1808cc72361SWai Yew CHAY { 1818cc72361SWai Yew CHAY kfree((struct src_rsc_ctrl_blk *)blk); 1828cc72361SWai Yew CHAY 1838cc72361SWai Yew CHAY return 0; 1848cc72361SWai Yew CHAY } 1858cc72361SWai Yew CHAY 1868cc72361SWai Yew CHAY static int src_set_state(void *blk, unsigned int state) 1878cc72361SWai Yew CHAY { 1888cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 1898cc72361SWai Yew CHAY 1908cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_STATE, state); 1918cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 1928cc72361SWai Yew CHAY return 0; 1938cc72361SWai Yew CHAY } 1948cc72361SWai Yew CHAY 1958cc72361SWai Yew CHAY static int src_set_bm(void *blk, unsigned int bm) 1968cc72361SWai Yew CHAY { 1978cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 1988cc72361SWai Yew CHAY 1998cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_BM, bm); 2008cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2018cc72361SWai Yew CHAY return 0; 2028cc72361SWai Yew CHAY } 2038cc72361SWai Yew CHAY 2048cc72361SWai Yew CHAY static int src_set_rsr(void *blk, unsigned int rsr) 2058cc72361SWai Yew CHAY { 2068cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2078cc72361SWai Yew CHAY 2088cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_RSR, rsr); 2098cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2108cc72361SWai Yew CHAY return 0; 2118cc72361SWai Yew CHAY } 2128cc72361SWai Yew CHAY 2138cc72361SWai Yew CHAY static int src_set_sf(void *blk, unsigned int sf) 2148cc72361SWai Yew CHAY { 2158cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2168cc72361SWai Yew CHAY 2178cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_SF, sf); 2188cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2198cc72361SWai Yew CHAY return 0; 2208cc72361SWai Yew CHAY } 2218cc72361SWai Yew CHAY 2228cc72361SWai Yew CHAY static int src_set_wr(void *blk, unsigned int wr) 2238cc72361SWai Yew CHAY { 2248cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2258cc72361SWai Yew CHAY 2268cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_WR, wr); 2278cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2288cc72361SWai Yew CHAY return 0; 2298cc72361SWai Yew CHAY } 2308cc72361SWai Yew CHAY 2318cc72361SWai Yew CHAY static int src_set_pm(void *blk, unsigned int pm) 2328cc72361SWai Yew CHAY { 2338cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2348cc72361SWai Yew CHAY 2358cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_PM, pm); 2368cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2378cc72361SWai Yew CHAY return 0; 2388cc72361SWai Yew CHAY } 2398cc72361SWai Yew CHAY 2408cc72361SWai Yew CHAY static int src_set_rom(void *blk, unsigned int rom) 2418cc72361SWai Yew CHAY { 2428cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2438cc72361SWai Yew CHAY 2448cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ROM, rom); 2458cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2468cc72361SWai Yew CHAY return 0; 2478cc72361SWai Yew CHAY } 2488cc72361SWai Yew CHAY 2498cc72361SWai Yew CHAY static int src_set_vo(void *blk, unsigned int vo) 2508cc72361SWai Yew CHAY { 2518cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2528cc72361SWai Yew CHAY 2538cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_VO, vo); 2548cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2558cc72361SWai Yew CHAY return 0; 2568cc72361SWai Yew CHAY } 2578cc72361SWai Yew CHAY 2588cc72361SWai Yew CHAY static int src_set_st(void *blk, unsigned int st) 2598cc72361SWai Yew CHAY { 2608cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2618cc72361SWai Yew CHAY 2628cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ST, st); 2638cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2648cc72361SWai Yew CHAY return 0; 2658cc72361SWai Yew CHAY } 2668cc72361SWai Yew CHAY 2678cc72361SWai Yew CHAY static int src_set_ie(void *blk, unsigned int ie) 2688cc72361SWai Yew CHAY { 2698cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2708cc72361SWai Yew CHAY 2718cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_IE, ie); 2728cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2738cc72361SWai Yew CHAY return 0; 2748cc72361SWai Yew CHAY } 2758cc72361SWai Yew CHAY 2768cc72361SWai Yew CHAY static int src_set_ilsz(void *blk, unsigned int ilsz) 2778cc72361SWai Yew CHAY { 2788cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2798cc72361SWai Yew CHAY 2808cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz); 2818cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2828cc72361SWai Yew CHAY return 0; 2838cc72361SWai Yew CHAY } 2848cc72361SWai Yew CHAY 2858cc72361SWai Yew CHAY static int src_set_bp(void *blk, unsigned int bp) 2868cc72361SWai Yew CHAY { 2878cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2888cc72361SWai Yew CHAY 2898cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_BP, bp); 2908cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2918cc72361SWai Yew CHAY return 0; 2928cc72361SWai Yew CHAY } 2938cc72361SWai Yew CHAY 2948cc72361SWai Yew CHAY static int src_set_cisz(void *blk, unsigned int cisz) 2958cc72361SWai Yew CHAY { 2968cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2978cc72361SWai Yew CHAY 2988cc72361SWai Yew CHAY set_field(&ctl->ccr, SRCCCR_CISZ, cisz); 2998cc72361SWai Yew CHAY ctl->dirty.bf.ccr = 1; 3008cc72361SWai Yew CHAY return 0; 3018cc72361SWai Yew CHAY } 3028cc72361SWai Yew CHAY 3038cc72361SWai Yew CHAY static int src_set_ca(void *blk, unsigned int ca) 3048cc72361SWai Yew CHAY { 3058cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3068cc72361SWai Yew CHAY 3078cc72361SWai Yew CHAY set_field(&ctl->ca, SRCCA_CA, ca); 3088cc72361SWai Yew CHAY ctl->dirty.bf.ca = 1; 3098cc72361SWai Yew CHAY return 0; 3108cc72361SWai Yew CHAY } 3118cc72361SWai Yew CHAY 3128cc72361SWai Yew CHAY static int src_set_sa(void *blk, unsigned int sa) 3138cc72361SWai Yew CHAY { 3148cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3158cc72361SWai Yew CHAY 3168cc72361SWai Yew CHAY set_field(&ctl->sa, SRCSA_SA, sa); 3178cc72361SWai Yew CHAY ctl->dirty.bf.sa = 1; 3188cc72361SWai Yew CHAY return 0; 3198cc72361SWai Yew CHAY } 3208cc72361SWai Yew CHAY 3218cc72361SWai Yew CHAY static int src_set_la(void *blk, unsigned int la) 3228cc72361SWai Yew CHAY { 3238cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3248cc72361SWai Yew CHAY 3258cc72361SWai Yew CHAY set_field(&ctl->la, SRCLA_LA, la); 3268cc72361SWai Yew CHAY ctl->dirty.bf.la = 1; 3278cc72361SWai Yew CHAY return 0; 3288cc72361SWai Yew CHAY } 3298cc72361SWai Yew CHAY 3308cc72361SWai Yew CHAY static int src_set_pitch(void *blk, unsigned int pitch) 3318cc72361SWai Yew CHAY { 3328cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3338cc72361SWai Yew CHAY 3348cc72361SWai Yew CHAY set_field(&ctl->mpr, MPRLH_PITCH, pitch); 3358cc72361SWai Yew CHAY ctl->dirty.bf.mpr = 1; 3368cc72361SWai Yew CHAY return 0; 3378cc72361SWai Yew CHAY } 3388cc72361SWai Yew CHAY 3398cc72361SWai Yew CHAY static int src_set_clear_zbufs(void *blk, unsigned int clear) 3408cc72361SWai Yew CHAY { 3418cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0); 3428cc72361SWai Yew CHAY return 0; 3438cc72361SWai Yew CHAY } 3448cc72361SWai Yew CHAY 3458cc72361SWai Yew CHAY static int src_set_dirty(void *blk, unsigned int flags) 3468cc72361SWai Yew CHAY { 3478cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 3488cc72361SWai Yew CHAY return 0; 3498cc72361SWai Yew CHAY } 3508cc72361SWai Yew CHAY 3518cc72361SWai Yew CHAY static int src_set_dirty_all(void *blk) 3528cc72361SWai Yew CHAY { 3538cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 3548cc72361SWai Yew CHAY return 0; 3558cc72361SWai Yew CHAY } 3568cc72361SWai Yew CHAY 3578cc72361SWai Yew CHAY #define AR_SLOT_SIZE 4096 3588cc72361SWai Yew CHAY #define AR_SLOT_BLOCK_SIZE 16 3598cc72361SWai Yew CHAY #define AR_PTS_PITCH 6 3608cc72361SWai Yew CHAY #define AR_PARAM_SRC_OFFSET 0x60 3618cc72361SWai Yew CHAY 3628cc72361SWai Yew CHAY static unsigned int src_param_pitch_mixer(unsigned int src_idx) 3638cc72361SWai Yew CHAY { 3648cc72361SWai Yew CHAY return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE 3658cc72361SWai Yew CHAY - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE; 3668cc72361SWai Yew CHAY 3678cc72361SWai Yew CHAY } 3688cc72361SWai Yew CHAY 3698cc72361SWai Yew CHAY static int src_commit_write(struct hw *hw, unsigned int idx, void *blk) 3708cc72361SWai Yew CHAY { 3718cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 372514eef9cSTakashi Iwai int i; 3738cc72361SWai Yew CHAY 3748cc72361SWai Yew CHAY if (ctl->dirty.bf.czbfs) { 3758cc72361SWai Yew CHAY /* Clear Z-Buffer registers */ 3768cc72361SWai Yew CHAY for (i = 0; i < 8; i++) 3778cc72361SWai Yew CHAY hw_write_20kx(hw, SRCUPZ+idx*0x100+i*0x4, 0); 3788cc72361SWai Yew CHAY 3798cc72361SWai Yew CHAY for (i = 0; i < 4; i++) 3808cc72361SWai Yew CHAY hw_write_20kx(hw, SRCDN0Z+idx*0x100+i*0x4, 0); 3818cc72361SWai Yew CHAY 3828cc72361SWai Yew CHAY for (i = 0; i < 8; i++) 3838cc72361SWai Yew CHAY hw_write_20kx(hw, SRCDN1Z+idx*0x100+i*0x4, 0); 3848cc72361SWai Yew CHAY 3858cc72361SWai Yew CHAY ctl->dirty.bf.czbfs = 0; 3868cc72361SWai Yew CHAY } 3878cc72361SWai Yew CHAY if (ctl->dirty.bf.mpr) { 3888cc72361SWai Yew CHAY /* Take the parameter mixer resource in the same group as that 3898cc72361SWai Yew CHAY * the idx src is in for simplicity. Unlike src, all conjugate 3908cc72361SWai Yew CHAY * parameter mixer resources must be programmed for 3918cc72361SWai Yew CHAY * corresponding conjugate src resources. */ 3928cc72361SWai Yew CHAY unsigned int pm_idx = src_param_pitch_mixer(idx); 3938cc72361SWai Yew CHAY hw_write_20kx(hw, PRING_LO_HI+4*pm_idx, ctl->mpr); 3948cc72361SWai Yew CHAY hw_write_20kx(hw, PMOPLO+8*pm_idx, 0x3); 3958cc72361SWai Yew CHAY hw_write_20kx(hw, PMOPHI+8*pm_idx, 0x0); 3968cc72361SWai Yew CHAY ctl->dirty.bf.mpr = 0; 3978cc72361SWai Yew CHAY } 3988cc72361SWai Yew CHAY if (ctl->dirty.bf.sa) { 3998cc72361SWai Yew CHAY hw_write_20kx(hw, SRCSA+idx*0x100, ctl->sa); 4008cc72361SWai Yew CHAY ctl->dirty.bf.sa = 0; 4018cc72361SWai Yew CHAY } 4028cc72361SWai Yew CHAY if (ctl->dirty.bf.la) { 4038cc72361SWai Yew CHAY hw_write_20kx(hw, SRCLA+idx*0x100, ctl->la); 4048cc72361SWai Yew CHAY ctl->dirty.bf.la = 0; 4058cc72361SWai Yew CHAY } 4068cc72361SWai Yew CHAY if (ctl->dirty.bf.ca) { 4078cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCA+idx*0x100, ctl->ca); 4088cc72361SWai Yew CHAY ctl->dirty.bf.ca = 0; 4098cc72361SWai Yew CHAY } 4108cc72361SWai Yew CHAY 4118cc72361SWai Yew CHAY /* Write srccf register */ 4128cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCF+idx*0x100, 0x0); 4138cc72361SWai Yew CHAY 4148cc72361SWai Yew CHAY if (ctl->dirty.bf.ccr) { 4158cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCCR+idx*0x100, ctl->ccr); 4168cc72361SWai Yew CHAY ctl->dirty.bf.ccr = 0; 4178cc72361SWai Yew CHAY } 4188cc72361SWai Yew CHAY if (ctl->dirty.bf.ctl) { 4198cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCTL+idx*0x100, ctl->ctl); 4208cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 0; 4218cc72361SWai Yew CHAY } 4228cc72361SWai Yew CHAY 4238cc72361SWai Yew CHAY return 0; 4248cc72361SWai Yew CHAY } 4258cc72361SWai Yew CHAY 4268cc72361SWai Yew CHAY static int src_get_ca(struct hw *hw, unsigned int idx, void *blk) 4278cc72361SWai Yew CHAY { 4288cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 4298cc72361SWai Yew CHAY 4308cc72361SWai Yew CHAY ctl->ca = hw_read_20kx(hw, SRCCA+idx*0x100); 4318cc72361SWai Yew CHAY ctl->dirty.bf.ca = 0; 4328cc72361SWai Yew CHAY 4338cc72361SWai Yew CHAY return get_field(ctl->ca, SRCCA_CA); 4348cc72361SWai Yew CHAY } 4358cc72361SWai Yew CHAY 4368cc72361SWai Yew CHAY static unsigned int src_get_dirty(void *blk) 4378cc72361SWai Yew CHAY { 4388cc72361SWai Yew CHAY return ((struct src_rsc_ctrl_blk *)blk)->dirty.data; 4398cc72361SWai Yew CHAY } 4408cc72361SWai Yew CHAY 4418cc72361SWai Yew CHAY static unsigned int src_dirty_conj_mask(void) 4428cc72361SWai Yew CHAY { 4438cc72361SWai Yew CHAY return 0x20; 4448cc72361SWai Yew CHAY } 4458cc72361SWai Yew CHAY 4468cc72361SWai Yew CHAY static int src_mgr_enbs_src(void *blk, unsigned int idx) 4478cc72361SWai Yew CHAY { 4488cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enbsa = ~(0x0); 4498cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1; 4508cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 4518cc72361SWai Yew CHAY return 0; 4528cc72361SWai Yew CHAY } 4538cc72361SWai Yew CHAY 4548cc72361SWai Yew CHAY static int src_mgr_enb_src(void *blk, unsigned int idx) 4558cc72361SWai Yew CHAY { 4568cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 4578cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 4588cc72361SWai Yew CHAY return 0; 4598cc72361SWai Yew CHAY } 4608cc72361SWai Yew CHAY 4618cc72361SWai Yew CHAY static int src_mgr_dsb_src(void *blk, unsigned int idx) 4628cc72361SWai Yew CHAY { 4638cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32)); 4648cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 4658cc72361SWai Yew CHAY return 0; 4668cc72361SWai Yew CHAY } 4678cc72361SWai Yew CHAY 4688cc72361SWai Yew CHAY static int src_mgr_commit_write(struct hw *hw, void *blk) 4698cc72361SWai Yew CHAY { 4708cc72361SWai Yew CHAY struct src_mgr_ctrl_blk *ctl = blk; 471514eef9cSTakashi Iwai int i; 472514eef9cSTakashi Iwai unsigned int ret; 4738cc72361SWai Yew CHAY 4748cc72361SWai Yew CHAY if (ctl->dirty.bf.enbsa) { 4758cc72361SWai Yew CHAY do { 4768cc72361SWai Yew CHAY ret = hw_read_20kx(hw, SRCENBSTAT); 4778cc72361SWai Yew CHAY } while (ret & 0x1); 4788cc72361SWai Yew CHAY hw_write_20kx(hw, SRCENBS, ctl->enbsa); 4798cc72361SWai Yew CHAY ctl->dirty.bf.enbsa = 0; 4808cc72361SWai Yew CHAY } 4818cc72361SWai Yew CHAY for (i = 0; i < 8; i++) { 4828cc72361SWai Yew CHAY if ((ctl->dirty.data & (0x1 << i))) { 4838cc72361SWai Yew CHAY hw_write_20kx(hw, SRCENB+(i*0x100), ctl->enb[i]); 4848cc72361SWai Yew CHAY ctl->dirty.data &= ~(0x1 << i); 4858cc72361SWai Yew CHAY } 4868cc72361SWai Yew CHAY } 4878cc72361SWai Yew CHAY 4888cc72361SWai Yew CHAY return 0; 4898cc72361SWai Yew CHAY } 4908cc72361SWai Yew CHAY 4918cc72361SWai Yew CHAY static int src_mgr_get_ctrl_blk(void **rblk) 4928cc72361SWai Yew CHAY { 4938cc72361SWai Yew CHAY struct src_mgr_ctrl_blk *blk; 4948cc72361SWai Yew CHAY 4958cc72361SWai Yew CHAY *rblk = NULL; 4968cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 49735ebf6e7STakashi Iwai if (!blk) 4988cc72361SWai Yew CHAY return -ENOMEM; 4998cc72361SWai Yew CHAY 5008cc72361SWai Yew CHAY *rblk = blk; 5018cc72361SWai Yew CHAY 5028cc72361SWai Yew CHAY return 0; 5038cc72361SWai Yew CHAY } 5048cc72361SWai Yew CHAY 5058cc72361SWai Yew CHAY static int src_mgr_put_ctrl_blk(void *blk) 5068cc72361SWai Yew CHAY { 5078cc72361SWai Yew CHAY kfree((struct src_mgr_ctrl_blk *)blk); 5088cc72361SWai Yew CHAY 5098cc72361SWai Yew CHAY return 0; 5108cc72361SWai Yew CHAY } 5118cc72361SWai Yew CHAY 5128cc72361SWai Yew CHAY static int srcimp_mgr_get_ctrl_blk(void **rblk) 5138cc72361SWai Yew CHAY { 5148cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *blk; 5158cc72361SWai Yew CHAY 5168cc72361SWai Yew CHAY *rblk = NULL; 5178cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 51835ebf6e7STakashi Iwai if (!blk) 5198cc72361SWai Yew CHAY return -ENOMEM; 5208cc72361SWai Yew CHAY 5218cc72361SWai Yew CHAY *rblk = blk; 5228cc72361SWai Yew CHAY 5238cc72361SWai Yew CHAY return 0; 5248cc72361SWai Yew CHAY } 5258cc72361SWai Yew CHAY 5268cc72361SWai Yew CHAY static int srcimp_mgr_put_ctrl_blk(void *blk) 5278cc72361SWai Yew CHAY { 5288cc72361SWai Yew CHAY kfree((struct srcimp_mgr_ctrl_blk *)blk); 5298cc72361SWai Yew CHAY 5308cc72361SWai Yew CHAY return 0; 5318cc72361SWai Yew CHAY } 5328cc72361SWai Yew CHAY 5338cc72361SWai Yew CHAY static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot) 5348cc72361SWai Yew CHAY { 5358cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5368cc72361SWai Yew CHAY 5378cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot); 5388cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5398cc72361SWai Yew CHAY return 0; 5408cc72361SWai Yew CHAY } 5418cc72361SWai Yew CHAY 5428cc72361SWai Yew CHAY static int srcimp_mgr_set_imapuser(void *blk, unsigned int user) 5438cc72361SWai Yew CHAY { 5448cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5458cc72361SWai Yew CHAY 5468cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user); 5478cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5488cc72361SWai Yew CHAY return 0; 5498cc72361SWai Yew CHAY } 5508cc72361SWai Yew CHAY 5518cc72361SWai Yew CHAY static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next) 5528cc72361SWai Yew CHAY { 5538cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5548cc72361SWai Yew CHAY 5558cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next); 5568cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5578cc72361SWai Yew CHAY return 0; 5588cc72361SWai Yew CHAY } 5598cc72361SWai Yew CHAY 5608cc72361SWai Yew CHAY static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr) 5618cc72361SWai Yew CHAY { 5628cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5638cc72361SWai Yew CHAY 5648cc72361SWai Yew CHAY ctl->srcimap.idx = addr; 5658cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5668cc72361SWai Yew CHAY return 0; 5678cc72361SWai Yew CHAY } 5688cc72361SWai Yew CHAY 5698cc72361SWai Yew CHAY static int srcimp_mgr_commit_write(struct hw *hw, void *blk) 5708cc72361SWai Yew CHAY { 5718cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5728cc72361SWai Yew CHAY 5738cc72361SWai Yew CHAY if (ctl->dirty.bf.srcimap) { 5748cc72361SWai Yew CHAY hw_write_20kx(hw, SRCIMAP+ctl->srcimap.idx*0x100, 5758cc72361SWai Yew CHAY ctl->srcimap.srcaim); 5768cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 0; 5778cc72361SWai Yew CHAY } 5788cc72361SWai Yew CHAY 5798cc72361SWai Yew CHAY return 0; 5808cc72361SWai Yew CHAY } 5818cc72361SWai Yew CHAY 5828cc72361SWai Yew CHAY /* 5838cc72361SWai Yew CHAY * AMIXER control block definitions. 5848cc72361SWai Yew CHAY */ 5858cc72361SWai Yew CHAY 5868cc72361SWai Yew CHAY #define AMOPLO_M 0x00000003 5878cc72361SWai Yew CHAY #define AMOPLO_X 0x0003FFF0 5888cc72361SWai Yew CHAY #define AMOPLO_Y 0xFFFC0000 5898cc72361SWai Yew CHAY 5908cc72361SWai Yew CHAY #define AMOPHI_SADR 0x000000FF 5918cc72361SWai Yew CHAY #define AMOPHI_SE 0x80000000 5928cc72361SWai Yew CHAY 5938cc72361SWai Yew CHAY /* AMIXER resource register dirty flags */ 5948cc72361SWai Yew CHAY union amixer_dirty { 5958cc72361SWai Yew CHAY struct { 5968cc72361SWai Yew CHAY u16 amoplo:1; 5978cc72361SWai Yew CHAY u16 amophi:1; 5988cc72361SWai Yew CHAY u16 rsv:14; 5998cc72361SWai Yew CHAY } bf; 6008cc72361SWai Yew CHAY u16 data; 6018cc72361SWai Yew CHAY }; 6028cc72361SWai Yew CHAY 6038cc72361SWai Yew CHAY /* AMIXER resource control block */ 6048cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk { 6058cc72361SWai Yew CHAY unsigned int amoplo; 6068cc72361SWai Yew CHAY unsigned int amophi; 6078cc72361SWai Yew CHAY union amixer_dirty dirty; 6088cc72361SWai Yew CHAY }; 6098cc72361SWai Yew CHAY 6108cc72361SWai Yew CHAY static int amixer_set_mode(void *blk, unsigned int mode) 6118cc72361SWai Yew CHAY { 6128cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6138cc72361SWai Yew CHAY 6148cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_M, mode); 6158cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 6168cc72361SWai Yew CHAY return 0; 6178cc72361SWai Yew CHAY } 6188cc72361SWai Yew CHAY 6198cc72361SWai Yew CHAY static int amixer_set_iv(void *blk, unsigned int iv) 6208cc72361SWai Yew CHAY { 6218cc72361SWai Yew CHAY /* 20k1 amixer does not have this field */ 6228cc72361SWai Yew CHAY return 0; 6238cc72361SWai Yew CHAY } 6248cc72361SWai Yew CHAY 6258cc72361SWai Yew CHAY static int amixer_set_x(void *blk, unsigned int x) 6268cc72361SWai Yew CHAY { 6278cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6288cc72361SWai Yew CHAY 6298cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_X, x); 6308cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 6318cc72361SWai Yew CHAY return 0; 6328cc72361SWai Yew CHAY } 6338cc72361SWai Yew CHAY 6348cc72361SWai Yew CHAY static int amixer_set_y(void *blk, unsigned int y) 6358cc72361SWai Yew CHAY { 6368cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6378cc72361SWai Yew CHAY 6388cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_Y, y); 6398cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 6408cc72361SWai Yew CHAY return 0; 6418cc72361SWai Yew CHAY } 6428cc72361SWai Yew CHAY 6438cc72361SWai Yew CHAY static int amixer_set_sadr(void *blk, unsigned int sadr) 6448cc72361SWai Yew CHAY { 6458cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6468cc72361SWai Yew CHAY 6478cc72361SWai Yew CHAY set_field(&ctl->amophi, AMOPHI_SADR, sadr); 6488cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 1; 6498cc72361SWai Yew CHAY return 0; 6508cc72361SWai Yew CHAY } 6518cc72361SWai Yew CHAY 6528cc72361SWai Yew CHAY static int amixer_set_se(void *blk, unsigned int se) 6538cc72361SWai Yew CHAY { 6548cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6558cc72361SWai Yew CHAY 6568cc72361SWai Yew CHAY set_field(&ctl->amophi, AMOPHI_SE, se); 6578cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 1; 6588cc72361SWai Yew CHAY return 0; 6598cc72361SWai Yew CHAY } 6608cc72361SWai Yew CHAY 6618cc72361SWai Yew CHAY static int amixer_set_dirty(void *blk, unsigned int flags) 6628cc72361SWai Yew CHAY { 6638cc72361SWai Yew CHAY ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 6648cc72361SWai Yew CHAY return 0; 6658cc72361SWai Yew CHAY } 6668cc72361SWai Yew CHAY 6678cc72361SWai Yew CHAY static int amixer_set_dirty_all(void *blk) 6688cc72361SWai Yew CHAY { 6698cc72361SWai Yew CHAY ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 6708cc72361SWai Yew CHAY return 0; 6718cc72361SWai Yew CHAY } 6728cc72361SWai Yew CHAY 6738cc72361SWai Yew CHAY static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) 6748cc72361SWai Yew CHAY { 6758cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6768cc72361SWai Yew CHAY 6778cc72361SWai Yew CHAY if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { 6788cc72361SWai Yew CHAY hw_write_20kx(hw, AMOPLO+idx*8, ctl->amoplo); 6798cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 0; 6808cc72361SWai Yew CHAY hw_write_20kx(hw, AMOPHI+idx*8, ctl->amophi); 6818cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 0; 6828cc72361SWai Yew CHAY } 6838cc72361SWai Yew CHAY 6848cc72361SWai Yew CHAY return 0; 6858cc72361SWai Yew CHAY } 6868cc72361SWai Yew CHAY 6878cc72361SWai Yew CHAY static int amixer_get_y(void *blk) 6888cc72361SWai Yew CHAY { 6898cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6908cc72361SWai Yew CHAY 6918cc72361SWai Yew CHAY return get_field(ctl->amoplo, AMOPLO_Y); 6928cc72361SWai Yew CHAY } 6938cc72361SWai Yew CHAY 6948cc72361SWai Yew CHAY static unsigned int amixer_get_dirty(void *blk) 6958cc72361SWai Yew CHAY { 6968cc72361SWai Yew CHAY return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; 6978cc72361SWai Yew CHAY } 6988cc72361SWai Yew CHAY 6998cc72361SWai Yew CHAY static int amixer_rsc_get_ctrl_blk(void **rblk) 7008cc72361SWai Yew CHAY { 7018cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *blk; 7028cc72361SWai Yew CHAY 7038cc72361SWai Yew CHAY *rblk = NULL; 7048cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 70535ebf6e7STakashi Iwai if (!blk) 7068cc72361SWai Yew CHAY return -ENOMEM; 7078cc72361SWai Yew CHAY 7088cc72361SWai Yew CHAY *rblk = blk; 7098cc72361SWai Yew CHAY 7108cc72361SWai Yew CHAY return 0; 7118cc72361SWai Yew CHAY } 7128cc72361SWai Yew CHAY 7138cc72361SWai Yew CHAY static int amixer_rsc_put_ctrl_blk(void *blk) 7148cc72361SWai Yew CHAY { 7158cc72361SWai Yew CHAY kfree((struct amixer_rsc_ctrl_blk *)blk); 7168cc72361SWai Yew CHAY 7178cc72361SWai Yew CHAY return 0; 7188cc72361SWai Yew CHAY } 7198cc72361SWai Yew CHAY 7208cc72361SWai Yew CHAY static int amixer_mgr_get_ctrl_blk(void **rblk) 7218cc72361SWai Yew CHAY { 7228cc72361SWai Yew CHAY /*amixer_mgr_ctrl_blk_t *blk;*/ 7238cc72361SWai Yew CHAY 7248cc72361SWai Yew CHAY *rblk = NULL; 7258cc72361SWai Yew CHAY /*blk = kzalloc(sizeof(*blk), GFP_KERNEL); 72635ebf6e7STakashi Iwai if (!blk) 7278cc72361SWai Yew CHAY return -ENOMEM; 7288cc72361SWai Yew CHAY 7298cc72361SWai Yew CHAY *rblk = blk;*/ 7308cc72361SWai Yew CHAY 7318cc72361SWai Yew CHAY return 0; 7328cc72361SWai Yew CHAY } 7338cc72361SWai Yew CHAY 7348cc72361SWai Yew CHAY static int amixer_mgr_put_ctrl_blk(void *blk) 7358cc72361SWai Yew CHAY { 7368cc72361SWai Yew CHAY /*kfree((amixer_mgr_ctrl_blk_t *)blk);*/ 7378cc72361SWai Yew CHAY 7388cc72361SWai Yew CHAY return 0; 7398cc72361SWai Yew CHAY } 7408cc72361SWai Yew CHAY 7418cc72361SWai Yew CHAY /* 7428cc72361SWai Yew CHAY * DAIO control block definitions. 7438cc72361SWai Yew CHAY */ 7448cc72361SWai Yew CHAY 7458cc72361SWai Yew CHAY /* Receiver Sample Rate Tracker Control register */ 7468cc72361SWai Yew CHAY #define SRTCTL_SRCR 0x000000FF 7478cc72361SWai Yew CHAY #define SRTCTL_SRCL 0x0000FF00 7488cc72361SWai Yew CHAY #define SRTCTL_RSR 0x00030000 7498cc72361SWai Yew CHAY #define SRTCTL_DRAT 0x000C0000 7508cc72361SWai Yew CHAY #define SRTCTL_RLE 0x10000000 7518cc72361SWai Yew CHAY #define SRTCTL_RLP 0x20000000 7528cc72361SWai Yew CHAY #define SRTCTL_EC 0x40000000 7538cc72361SWai Yew CHAY #define SRTCTL_ET 0x80000000 7548cc72361SWai Yew CHAY 7558cc72361SWai Yew CHAY /* DAIO Receiver register dirty flags */ 7568cc72361SWai Yew CHAY union dai_dirty { 7578cc72361SWai Yew CHAY struct { 7588cc72361SWai Yew CHAY u16 srtctl:1; 7598cc72361SWai Yew CHAY u16 rsv:15; 7608cc72361SWai Yew CHAY } bf; 7618cc72361SWai Yew CHAY u16 data; 7628cc72361SWai Yew CHAY }; 7638cc72361SWai Yew CHAY 7648cc72361SWai Yew CHAY /* DAIO Receiver control block */ 7658cc72361SWai Yew CHAY struct dai_ctrl_blk { 7668cc72361SWai Yew CHAY unsigned int srtctl; 7678cc72361SWai Yew CHAY union dai_dirty dirty; 7688cc72361SWai Yew CHAY }; 7698cc72361SWai Yew CHAY 7708cc72361SWai Yew CHAY /* S/PDIF Transmitter register dirty flags */ 7718cc72361SWai Yew CHAY union dao_dirty { 7728cc72361SWai Yew CHAY struct { 7738cc72361SWai Yew CHAY u16 spos:1; 7748cc72361SWai Yew CHAY u16 rsv:15; 7758cc72361SWai Yew CHAY } bf; 7768cc72361SWai Yew CHAY u16 data; 7778cc72361SWai Yew CHAY }; 7788cc72361SWai Yew CHAY 7798cc72361SWai Yew CHAY /* S/PDIF Transmitter control block */ 7808cc72361SWai Yew CHAY struct dao_ctrl_blk { 7818cc72361SWai Yew CHAY unsigned int spos; /* S/PDIF Output Channel Status Register */ 7828cc72361SWai Yew CHAY union dao_dirty dirty; 7838cc72361SWai Yew CHAY }; 7848cc72361SWai Yew CHAY 7858cc72361SWai Yew CHAY /* Audio Input Mapper RAM */ 7868cc72361SWai Yew CHAY #define AIM_ARC 0x00000FFF 7878cc72361SWai Yew CHAY #define AIM_NXT 0x007F0000 7888cc72361SWai Yew CHAY 7898cc72361SWai Yew CHAY struct daoimap { 7908cc72361SWai Yew CHAY unsigned int aim; 7918cc72361SWai Yew CHAY unsigned int idx; 7928cc72361SWai Yew CHAY }; 7938cc72361SWai Yew CHAY 7948cc72361SWai Yew CHAY /* I2S Transmitter/Receiver Control register */ 7958cc72361SWai Yew CHAY #define I2SCTL_EA 0x00000004 7968cc72361SWai Yew CHAY #define I2SCTL_EI 0x00000010 7978cc72361SWai Yew CHAY 7988cc72361SWai Yew CHAY /* S/PDIF Transmitter Control register */ 7998cc72361SWai Yew CHAY #define SPOCTL_OE 0x00000001 8008cc72361SWai Yew CHAY #define SPOCTL_OS 0x0000000E 8018cc72361SWai Yew CHAY #define SPOCTL_RIV 0x00000010 8028cc72361SWai Yew CHAY #define SPOCTL_LIV 0x00000020 8038cc72361SWai Yew CHAY #define SPOCTL_SR 0x000000C0 8048cc72361SWai Yew CHAY 8058cc72361SWai Yew CHAY /* S/PDIF Receiver Control register */ 8068cc72361SWai Yew CHAY #define SPICTL_EN 0x00000001 8078cc72361SWai Yew CHAY #define SPICTL_I24 0x00000002 8088cc72361SWai Yew CHAY #define SPICTL_IB 0x00000004 8098cc72361SWai Yew CHAY #define SPICTL_SM 0x00000008 8108cc72361SWai Yew CHAY #define SPICTL_VM 0x00000010 8118cc72361SWai Yew CHAY 8128cc72361SWai Yew CHAY /* DAIO manager register dirty flags */ 8138cc72361SWai Yew CHAY union daio_mgr_dirty { 8148cc72361SWai Yew CHAY struct { 8158cc72361SWai Yew CHAY u32 i2soctl:4; 8168cc72361SWai Yew CHAY u32 i2sictl:4; 8178cc72361SWai Yew CHAY u32 spoctl:4; 8188cc72361SWai Yew CHAY u32 spictl:4; 8198cc72361SWai Yew CHAY u32 daoimap:1; 8208cc72361SWai Yew CHAY u32 rsv:15; 8218cc72361SWai Yew CHAY } bf; 8228cc72361SWai Yew CHAY u32 data; 8238cc72361SWai Yew CHAY }; 8248cc72361SWai Yew CHAY 8258cc72361SWai Yew CHAY /* DAIO manager control block */ 8268cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk { 8278cc72361SWai Yew CHAY unsigned int i2sctl; 8288cc72361SWai Yew CHAY unsigned int spoctl; 8298cc72361SWai Yew CHAY unsigned int spictl; 8308cc72361SWai Yew CHAY struct daoimap daoimap; 8318cc72361SWai Yew CHAY union daio_mgr_dirty dirty; 8328cc72361SWai Yew CHAY }; 8338cc72361SWai Yew CHAY 8348cc72361SWai Yew CHAY static int dai_srt_set_srcr(void *blk, unsigned int src) 8358cc72361SWai Yew CHAY { 8368cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8378cc72361SWai Yew CHAY 8388cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_SRCR, src); 8398cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8408cc72361SWai Yew CHAY return 0; 8418cc72361SWai Yew CHAY } 8428cc72361SWai Yew CHAY 8438cc72361SWai Yew CHAY static int dai_srt_set_srcl(void *blk, unsigned int src) 8448cc72361SWai Yew CHAY { 8458cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8468cc72361SWai Yew CHAY 8478cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_SRCL, src); 8488cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8498cc72361SWai Yew CHAY return 0; 8508cc72361SWai Yew CHAY } 8518cc72361SWai Yew CHAY 8528cc72361SWai Yew CHAY static int dai_srt_set_rsr(void *blk, unsigned int rsr) 8538cc72361SWai Yew CHAY { 8548cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8558cc72361SWai Yew CHAY 8568cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_RSR, rsr); 8578cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8588cc72361SWai Yew CHAY return 0; 8598cc72361SWai Yew CHAY } 8608cc72361SWai Yew CHAY 8618cc72361SWai Yew CHAY static int dai_srt_set_drat(void *blk, unsigned int drat) 8628cc72361SWai Yew CHAY { 8638cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8648cc72361SWai Yew CHAY 8658cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_DRAT, drat); 8668cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8678cc72361SWai Yew CHAY return 0; 8688cc72361SWai Yew CHAY } 8698cc72361SWai Yew CHAY 8708cc72361SWai Yew CHAY static int dai_srt_set_ec(void *blk, unsigned int ec) 8718cc72361SWai Yew CHAY { 8728cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8738cc72361SWai Yew CHAY 8748cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_EC, ec ? 1 : 0); 8758cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8768cc72361SWai Yew CHAY return 0; 8778cc72361SWai Yew CHAY } 8788cc72361SWai Yew CHAY 8798cc72361SWai Yew CHAY static int dai_srt_set_et(void *blk, unsigned int et) 8808cc72361SWai Yew CHAY { 8818cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8828cc72361SWai Yew CHAY 8838cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_ET, et ? 1 : 0); 8848cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8858cc72361SWai Yew CHAY return 0; 8868cc72361SWai Yew CHAY } 8878cc72361SWai Yew CHAY 8888cc72361SWai Yew CHAY static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) 8898cc72361SWai Yew CHAY { 8908cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8918cc72361SWai Yew CHAY 8928cc72361SWai Yew CHAY if (ctl->dirty.bf.srtctl) { 8938cc72361SWai Yew CHAY if (idx < 4) { 8948cc72361SWai Yew CHAY /* S/PDIF SRTs */ 8958cc72361SWai Yew CHAY hw_write_20kx(hw, SRTSCTL+0x4*idx, ctl->srtctl); 8968cc72361SWai Yew CHAY } else { 8978cc72361SWai Yew CHAY /* I2S SRT */ 8988cc72361SWai Yew CHAY hw_write_20kx(hw, SRTICTL, ctl->srtctl); 8998cc72361SWai Yew CHAY } 9008cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 0; 9018cc72361SWai Yew CHAY } 9028cc72361SWai Yew CHAY 9038cc72361SWai Yew CHAY return 0; 9048cc72361SWai Yew CHAY } 9058cc72361SWai Yew CHAY 9068cc72361SWai Yew CHAY static int dai_get_ctrl_blk(void **rblk) 9078cc72361SWai Yew CHAY { 9088cc72361SWai Yew CHAY struct dai_ctrl_blk *blk; 9098cc72361SWai Yew CHAY 9108cc72361SWai Yew CHAY *rblk = NULL; 9118cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 91235ebf6e7STakashi Iwai if (!blk) 9138cc72361SWai Yew CHAY return -ENOMEM; 9148cc72361SWai Yew CHAY 9158cc72361SWai Yew CHAY *rblk = blk; 9168cc72361SWai Yew CHAY 9178cc72361SWai Yew CHAY return 0; 9188cc72361SWai Yew CHAY } 9198cc72361SWai Yew CHAY 9208cc72361SWai Yew CHAY static int dai_put_ctrl_blk(void *blk) 9218cc72361SWai Yew CHAY { 9228cc72361SWai Yew CHAY kfree((struct dai_ctrl_blk *)blk); 9238cc72361SWai Yew CHAY 9248cc72361SWai Yew CHAY return 0; 9258cc72361SWai Yew CHAY } 9268cc72361SWai Yew CHAY 9278cc72361SWai Yew CHAY static int dao_set_spos(void *blk, unsigned int spos) 9288cc72361SWai Yew CHAY { 9298cc72361SWai Yew CHAY ((struct dao_ctrl_blk *)blk)->spos = spos; 9308cc72361SWai Yew CHAY ((struct dao_ctrl_blk *)blk)->dirty.bf.spos = 1; 9318cc72361SWai Yew CHAY return 0; 9328cc72361SWai Yew CHAY } 9338cc72361SWai Yew CHAY 9348cc72361SWai Yew CHAY static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) 9358cc72361SWai Yew CHAY { 9368cc72361SWai Yew CHAY struct dao_ctrl_blk *ctl = blk; 9378cc72361SWai Yew CHAY 9388cc72361SWai Yew CHAY if (ctl->dirty.bf.spos) { 9398cc72361SWai Yew CHAY if (idx < 4) { 9408cc72361SWai Yew CHAY /* S/PDIF SPOSx */ 9418cc72361SWai Yew CHAY hw_write_20kx(hw, SPOS+0x4*idx, ctl->spos); 9428cc72361SWai Yew CHAY } 9438cc72361SWai Yew CHAY ctl->dirty.bf.spos = 0; 9448cc72361SWai Yew CHAY } 9458cc72361SWai Yew CHAY 9468cc72361SWai Yew CHAY return 0; 9478cc72361SWai Yew CHAY } 9488cc72361SWai Yew CHAY 9498cc72361SWai Yew CHAY static int dao_get_spos(void *blk, unsigned int *spos) 9508cc72361SWai Yew CHAY { 9518cc72361SWai Yew CHAY *spos = ((struct dao_ctrl_blk *)blk)->spos; 9528cc72361SWai Yew CHAY return 0; 9538cc72361SWai Yew CHAY } 9548cc72361SWai Yew CHAY 9558cc72361SWai Yew CHAY static int dao_get_ctrl_blk(void **rblk) 9568cc72361SWai Yew CHAY { 9578cc72361SWai Yew CHAY struct dao_ctrl_blk *blk; 9588cc72361SWai Yew CHAY 9598cc72361SWai Yew CHAY *rblk = NULL; 9608cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 96135ebf6e7STakashi Iwai if (!blk) 9628cc72361SWai Yew CHAY return -ENOMEM; 9638cc72361SWai Yew CHAY 9648cc72361SWai Yew CHAY *rblk = blk; 9658cc72361SWai Yew CHAY 9668cc72361SWai Yew CHAY return 0; 9678cc72361SWai Yew CHAY } 9688cc72361SWai Yew CHAY 9698cc72361SWai Yew CHAY static int dao_put_ctrl_blk(void *blk) 9708cc72361SWai Yew CHAY { 9718cc72361SWai Yew CHAY kfree((struct dao_ctrl_blk *)blk); 9728cc72361SWai Yew CHAY 9738cc72361SWai Yew CHAY return 0; 9748cc72361SWai Yew CHAY } 9758cc72361SWai Yew CHAY 9768cc72361SWai Yew CHAY static int daio_mgr_enb_dai(void *blk, unsigned int idx) 9778cc72361SWai Yew CHAY { 9788cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 9798cc72361SWai Yew CHAY 9808cc72361SWai Yew CHAY if (idx < 4) { 9818cc72361SWai Yew CHAY /* S/PDIF input */ 9828cc72361SWai Yew CHAY set_field(&ctl->spictl, SPICTL_EN << (idx*8), 1); 9838cc72361SWai Yew CHAY ctl->dirty.bf.spictl |= (0x1 << idx); 9848cc72361SWai Yew CHAY } else { 9858cc72361SWai Yew CHAY /* I2S input */ 9868cc72361SWai Yew CHAY idx %= 4; 9878cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 1); 9888cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl |= (0x1 << idx); 9898cc72361SWai Yew CHAY } 9908cc72361SWai Yew CHAY return 0; 9918cc72361SWai Yew CHAY } 9928cc72361SWai Yew CHAY 9938cc72361SWai Yew CHAY static int daio_mgr_dsb_dai(void *blk, unsigned int idx) 9948cc72361SWai Yew CHAY { 9958cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 9968cc72361SWai Yew CHAY 9978cc72361SWai Yew CHAY if (idx < 4) { 9988cc72361SWai Yew CHAY /* S/PDIF input */ 9998cc72361SWai Yew CHAY set_field(&ctl->spictl, SPICTL_EN << (idx*8), 0); 10008cc72361SWai Yew CHAY ctl->dirty.bf.spictl |= (0x1 << idx); 10018cc72361SWai Yew CHAY } else { 10028cc72361SWai Yew CHAY /* I2S input */ 10038cc72361SWai Yew CHAY idx %= 4; 10048cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 0); 10058cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl |= (0x1 << idx); 10068cc72361SWai Yew CHAY } 10078cc72361SWai Yew CHAY return 0; 10088cc72361SWai Yew CHAY } 10098cc72361SWai Yew CHAY 10108cc72361SWai Yew CHAY static int daio_mgr_enb_dao(void *blk, unsigned int idx) 10118cc72361SWai Yew CHAY { 10128cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10138cc72361SWai Yew CHAY 10148cc72361SWai Yew CHAY if (idx < 4) { 10158cc72361SWai Yew CHAY /* S/PDIF output */ 10168cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 1); 10178cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 10188cc72361SWai Yew CHAY } else { 10198cc72361SWai Yew CHAY /* I2S output */ 10208cc72361SWai Yew CHAY idx %= 4; 10218cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 1); 10228cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl |= (0x1 << idx); 10238cc72361SWai Yew CHAY } 10248cc72361SWai Yew CHAY return 0; 10258cc72361SWai Yew CHAY } 10268cc72361SWai Yew CHAY 10278cc72361SWai Yew CHAY static int daio_mgr_dsb_dao(void *blk, unsigned int idx) 10288cc72361SWai Yew CHAY { 10298cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10308cc72361SWai Yew CHAY 10318cc72361SWai Yew CHAY if (idx < 4) { 10328cc72361SWai Yew CHAY /* S/PDIF output */ 10338cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 0); 10348cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 10358cc72361SWai Yew CHAY } else { 10368cc72361SWai Yew CHAY /* I2S output */ 10378cc72361SWai Yew CHAY idx %= 4; 10388cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 0); 10398cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl |= (0x1 << idx); 10408cc72361SWai Yew CHAY } 10418cc72361SWai Yew CHAY return 0; 10428cc72361SWai Yew CHAY } 10438cc72361SWai Yew CHAY 10448cc72361SWai Yew CHAY static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) 10458cc72361SWai Yew CHAY { 10468cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10478cc72361SWai Yew CHAY 10488cc72361SWai Yew CHAY if (idx < 4) { 10498cc72361SWai Yew CHAY /* S/PDIF output */ 10508cc72361SWai Yew CHAY switch ((conf & 0x7)) { 10518cc72361SWai Yew CHAY case 0: 10528cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 3); 10538cc72361SWai Yew CHAY break; /* CDIF */ 10548cc72361SWai Yew CHAY case 1: 10558cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 0); 10568cc72361SWai Yew CHAY break; 10578cc72361SWai Yew CHAY case 2: 10588cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 1); 10598cc72361SWai Yew CHAY break; 10608cc72361SWai Yew CHAY case 4: 10618cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 2); 10628cc72361SWai Yew CHAY break; 10638cc72361SWai Yew CHAY default: 10648cc72361SWai Yew CHAY break; 10658cc72361SWai Yew CHAY } 10668cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_LIV << (idx*8), 10678cc72361SWai Yew CHAY (conf >> 4) & 0x1); /* Non-audio */ 10688cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_RIV << (idx*8), 10698cc72361SWai Yew CHAY (conf >> 4) & 0x1); /* Non-audio */ 10708cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OS << (idx*8), 10718cc72361SWai Yew CHAY ((conf >> 3) & 0x1) ? 2 : 2); /* Raw */ 10728cc72361SWai Yew CHAY 10738cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 10748cc72361SWai Yew CHAY } else { 10758cc72361SWai Yew CHAY /* I2S output */ 10768cc72361SWai Yew CHAY /*idx %= 4; */ 10778cc72361SWai Yew CHAY } 10788cc72361SWai Yew CHAY return 0; 10798cc72361SWai Yew CHAY } 10808cc72361SWai Yew CHAY 10818cc72361SWai Yew CHAY static int daio_mgr_set_imaparc(void *blk, unsigned int slot) 10828cc72361SWai Yew CHAY { 10838cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10848cc72361SWai Yew CHAY 10858cc72361SWai Yew CHAY set_field(&ctl->daoimap.aim, AIM_ARC, slot); 10868cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 10878cc72361SWai Yew CHAY return 0; 10888cc72361SWai Yew CHAY } 10898cc72361SWai Yew CHAY 10908cc72361SWai Yew CHAY static int daio_mgr_set_imapnxt(void *blk, unsigned int next) 10918cc72361SWai Yew CHAY { 10928cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10938cc72361SWai Yew CHAY 10948cc72361SWai Yew CHAY set_field(&ctl->daoimap.aim, AIM_NXT, next); 10958cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 10968cc72361SWai Yew CHAY return 0; 10978cc72361SWai Yew CHAY } 10988cc72361SWai Yew CHAY 10998cc72361SWai Yew CHAY static int daio_mgr_set_imapaddr(void *blk, unsigned int addr) 11008cc72361SWai Yew CHAY { 11018cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 11028cc72361SWai Yew CHAY 11038cc72361SWai Yew CHAY ctl->daoimap.idx = addr; 11048cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 11058cc72361SWai Yew CHAY return 0; 11068cc72361SWai Yew CHAY } 11078cc72361SWai Yew CHAY 11088cc72361SWai Yew CHAY static int daio_mgr_commit_write(struct hw *hw, void *blk) 11098cc72361SWai Yew CHAY { 11108cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1111514eef9cSTakashi Iwai int i; 11128cc72361SWai Yew CHAY 11138cc72361SWai Yew CHAY if (ctl->dirty.bf.i2sictl || ctl->dirty.bf.i2soctl) { 11148cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 11158cc72361SWai Yew CHAY if ((ctl->dirty.bf.i2sictl & (0x1 << i))) 11168cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl &= ~(0x1 << i); 11178cc72361SWai Yew CHAY 11188cc72361SWai Yew CHAY if ((ctl->dirty.bf.i2soctl & (0x1 << i))) 11198cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl &= ~(0x1 << i); 11208cc72361SWai Yew CHAY } 11218cc72361SWai Yew CHAY hw_write_20kx(hw, I2SCTL, ctl->i2sctl); 11228cc72361SWai Yew CHAY mdelay(1); 11238cc72361SWai Yew CHAY } 11248cc72361SWai Yew CHAY if (ctl->dirty.bf.spoctl) { 11258cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 11268cc72361SWai Yew CHAY if ((ctl->dirty.bf.spoctl & (0x1 << i))) 11278cc72361SWai Yew CHAY ctl->dirty.bf.spoctl &= ~(0x1 << i); 11288cc72361SWai Yew CHAY } 11298cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, ctl->spoctl); 11308cc72361SWai Yew CHAY mdelay(1); 11318cc72361SWai Yew CHAY } 11328cc72361SWai Yew CHAY if (ctl->dirty.bf.spictl) { 11338cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 11348cc72361SWai Yew CHAY if ((ctl->dirty.bf.spictl & (0x1 << i))) 11358cc72361SWai Yew CHAY ctl->dirty.bf.spictl &= ~(0x1 << i); 11368cc72361SWai Yew CHAY } 11378cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, ctl->spictl); 11388cc72361SWai Yew CHAY mdelay(1); 11398cc72361SWai Yew CHAY } 11408cc72361SWai Yew CHAY if (ctl->dirty.bf.daoimap) { 11418cc72361SWai Yew CHAY hw_write_20kx(hw, DAOIMAP+ctl->daoimap.idx*4, 11428cc72361SWai Yew CHAY ctl->daoimap.aim); 11438cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 0; 11448cc72361SWai Yew CHAY } 11458cc72361SWai Yew CHAY 11468cc72361SWai Yew CHAY return 0; 11478cc72361SWai Yew CHAY } 11488cc72361SWai Yew CHAY 11498cc72361SWai Yew CHAY static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) 11508cc72361SWai Yew CHAY { 11518cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *blk; 11528cc72361SWai Yew CHAY 11538cc72361SWai Yew CHAY *rblk = NULL; 11548cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 115535ebf6e7STakashi Iwai if (!blk) 11568cc72361SWai Yew CHAY return -ENOMEM; 11578cc72361SWai Yew CHAY 11588cc72361SWai Yew CHAY blk->i2sctl = hw_read_20kx(hw, I2SCTL); 11598cc72361SWai Yew CHAY blk->spoctl = hw_read_20kx(hw, SPOCTL); 11608cc72361SWai Yew CHAY blk->spictl = hw_read_20kx(hw, SPICTL); 11618cc72361SWai Yew CHAY 11628cc72361SWai Yew CHAY *rblk = blk; 11638cc72361SWai Yew CHAY 11648cc72361SWai Yew CHAY return 0; 11658cc72361SWai Yew CHAY } 11668cc72361SWai Yew CHAY 11678cc72361SWai Yew CHAY static int daio_mgr_put_ctrl_blk(void *blk) 11688cc72361SWai Yew CHAY { 11698cc72361SWai Yew CHAY kfree((struct daio_mgr_ctrl_blk *)blk); 11708cc72361SWai Yew CHAY 11718cc72361SWai Yew CHAY return 0; 11728cc72361SWai Yew CHAY } 11738cc72361SWai Yew CHAY 1174b7bbf876STakashi Iwai /* Timer interrupt */ 1175b7bbf876STakashi Iwai static int set_timer_irq(struct hw *hw, int enable) 1176b7bbf876STakashi Iwai { 1177b7bbf876STakashi Iwai hw_write_20kx(hw, GIE, enable ? IT_INT : 0); 1178b7bbf876STakashi Iwai return 0; 1179b7bbf876STakashi Iwai } 1180b7bbf876STakashi Iwai 1181b7bbf876STakashi Iwai static int set_timer_tick(struct hw *hw, unsigned int ticks) 1182b7bbf876STakashi Iwai { 1183b7bbf876STakashi Iwai if (ticks) 1184b7bbf876STakashi Iwai ticks |= TIMR_IE | TIMR_IP; 1185b7bbf876STakashi Iwai hw_write_20kx(hw, TIMR, ticks); 1186b7bbf876STakashi Iwai return 0; 1187b7bbf876STakashi Iwai } 1188b7bbf876STakashi Iwai 118954de6bc8STakashi Iwai static unsigned int get_wc(struct hw *hw) 119054de6bc8STakashi Iwai { 119154de6bc8STakashi Iwai return hw_read_20kx(hw, WC); 119254de6bc8STakashi Iwai } 119354de6bc8STakashi Iwai 11948cc72361SWai Yew CHAY /* Card hardware initialization block */ 11958cc72361SWai Yew CHAY struct dac_conf { 11968cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 11978cc72361SWai Yew CHAY }; 11988cc72361SWai Yew CHAY 11998cc72361SWai Yew CHAY struct adc_conf { 12008cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 12018cc72361SWai Yew CHAY unsigned char input; /* the input source of ADC */ 12028cc72361SWai Yew CHAY unsigned char mic20db; /* boost mic by 20db if input is microphone */ 12038cc72361SWai Yew CHAY }; 12048cc72361SWai Yew CHAY 12058cc72361SWai Yew CHAY struct daio_conf { 12068cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 12078cc72361SWai Yew CHAY }; 12088cc72361SWai Yew CHAY 12098cc72361SWai Yew CHAY struct trn_conf { 12108cc72361SWai Yew CHAY unsigned long vm_pgt_phys; 12118cc72361SWai Yew CHAY }; 12128cc72361SWai Yew CHAY 12138cc72361SWai Yew CHAY static int hw_daio_init(struct hw *hw, const struct daio_conf *info) 12148cc72361SWai Yew CHAY { 1215514eef9cSTakashi Iwai u32 i2sorg; 1216514eef9cSTakashi Iwai u32 spdorg; 12178cc72361SWai Yew CHAY 12188cc72361SWai Yew CHAY /* Read I2S CTL. Keep original value. */ 12198cc72361SWai Yew CHAY /*i2sorg = hw_read_20kx(hw, I2SCTL);*/ 12208cc72361SWai Yew CHAY i2sorg = 0x94040404; /* enable all audio out and I2S-D input */ 12218cc72361SWai Yew CHAY /* Program I2S with proper master sample rate and enable 12228cc72361SWai Yew CHAY * the correct I2S channel. */ 12238cc72361SWai Yew CHAY i2sorg &= 0xfffffffc; 12248cc72361SWai Yew CHAY 12258cc72361SWai Yew CHAY /* Enable S/PDIF-out-A in fixed 24-bit data 12268cc72361SWai Yew CHAY * format and default to 48kHz. */ 12278cc72361SWai Yew CHAY /* Disable all before doing any changes. */ 12288cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, 0x0); 12298cc72361SWai Yew CHAY spdorg = 0x05; 12308cc72361SWai Yew CHAY 12318cc72361SWai Yew CHAY switch (info->msr) { 12328cc72361SWai Yew CHAY case 1: 12338cc72361SWai Yew CHAY i2sorg |= 1; 12348cc72361SWai Yew CHAY spdorg |= (0x0 << 6); 12358cc72361SWai Yew CHAY break; 12368cc72361SWai Yew CHAY case 2: 12378cc72361SWai Yew CHAY i2sorg |= 2; 12388cc72361SWai Yew CHAY spdorg |= (0x1 << 6); 12398cc72361SWai Yew CHAY break; 12408cc72361SWai Yew CHAY case 4: 12418cc72361SWai Yew CHAY i2sorg |= 3; 12428cc72361SWai Yew CHAY spdorg |= (0x2 << 6); 12438cc72361SWai Yew CHAY break; 12448cc72361SWai Yew CHAY default: 12458cc72361SWai Yew CHAY i2sorg |= 1; 12468cc72361SWai Yew CHAY break; 12478cc72361SWai Yew CHAY } 12488cc72361SWai Yew CHAY 12498cc72361SWai Yew CHAY hw_write_20kx(hw, I2SCTL, i2sorg); 12508cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, spdorg); 12518cc72361SWai Yew CHAY 12528cc72361SWai Yew CHAY /* Enable S/PDIF-in-A in fixed 24-bit data format. */ 12538cc72361SWai Yew CHAY /* Disable all before doing any changes. */ 12548cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, 0x0); 12558cc72361SWai Yew CHAY mdelay(1); 12568cc72361SWai Yew CHAY spdorg = 0x0a0a0a0a; 12578cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, spdorg); 12588cc72361SWai Yew CHAY mdelay(1); 12598cc72361SWai Yew CHAY 12608cc72361SWai Yew CHAY return 0; 12618cc72361SWai Yew CHAY } 12628cc72361SWai Yew CHAY 12638cc72361SWai Yew CHAY /* TRANSPORT operations */ 12648cc72361SWai Yew CHAY static int hw_trn_init(struct hw *hw, const struct trn_conf *info) 12658cc72361SWai Yew CHAY { 1266514eef9cSTakashi Iwai u32 trnctl; 1267514eef9cSTakashi Iwai u32 ptp_phys_low, ptp_phys_high; 12688cc72361SWai Yew CHAY 12698cc72361SWai Yew CHAY /* Set up device page table */ 12708cc72361SWai Yew CHAY if ((~0UL) == info->vm_pgt_phys) { 12718cc72361SWai Yew CHAY printk(KERN_ERR "Wrong device page table page address!\n"); 12728cc72361SWai Yew CHAY return -1; 12738cc72361SWai Yew CHAY } 12748cc72361SWai Yew CHAY 12758cc72361SWai Yew CHAY trnctl = 0x13; /* 32-bit, 4k-size page */ 1276cd391e20STakashi Iwai ptp_phys_low = (u32)info->vm_pgt_phys; 1277cd391e20STakashi Iwai ptp_phys_high = upper_32_bits(info->vm_pgt_phys); 1278cd391e20STakashi Iwai if (sizeof(void *) == 8) /* 64bit address */ 12798cc72361SWai Yew CHAY trnctl |= (1 << 2); 1280cd391e20STakashi Iwai #if 0 /* Only 4k h/w pages for simplicitiy */ 12818cc72361SWai Yew CHAY #if PAGE_SIZE == 8192 12828cc72361SWai Yew CHAY trnctl |= (1<<5); 12838cc72361SWai Yew CHAY #endif 1284cd391e20STakashi Iwai #endif 12858cc72361SWai Yew CHAY hw_write_20kx(hw, PTPALX, ptp_phys_low); 12868cc72361SWai Yew CHAY hw_write_20kx(hw, PTPAHX, ptp_phys_high); 12878cc72361SWai Yew CHAY hw_write_20kx(hw, TRNCTL, trnctl); 128825985edcSLucas De Marchi hw_write_20kx(hw, TRNIS, 0x200c01); /* really needed? */ 12898cc72361SWai Yew CHAY 12908cc72361SWai Yew CHAY return 0; 12918cc72361SWai Yew CHAY } 12928cc72361SWai Yew CHAY 12938cc72361SWai Yew CHAY /* Card initialization */ 12948cc72361SWai Yew CHAY #define GCTL_EAC 0x00000001 12958cc72361SWai Yew CHAY #define GCTL_EAI 0x00000002 12968cc72361SWai Yew CHAY #define GCTL_BEP 0x00000004 12978cc72361SWai Yew CHAY #define GCTL_BES 0x00000008 12988cc72361SWai Yew CHAY #define GCTL_DSP 0x00000010 12998cc72361SWai Yew CHAY #define GCTL_DBP 0x00000020 13008cc72361SWai Yew CHAY #define GCTL_ABP 0x00000040 13018cc72361SWai Yew CHAY #define GCTL_TBP 0x00000080 13028cc72361SWai Yew CHAY #define GCTL_SBP 0x00000100 13038cc72361SWai Yew CHAY #define GCTL_FBP 0x00000200 13048cc72361SWai Yew CHAY #define GCTL_XA 0x00000400 13058cc72361SWai Yew CHAY #define GCTL_ET 0x00000800 13068cc72361SWai Yew CHAY #define GCTL_PR 0x00001000 13078cc72361SWai Yew CHAY #define GCTL_MRL 0x00002000 13088cc72361SWai Yew CHAY #define GCTL_SDE 0x00004000 13098cc72361SWai Yew CHAY #define GCTL_SDI 0x00008000 13108cc72361SWai Yew CHAY #define GCTL_SM 0x00010000 13118cc72361SWai Yew CHAY #define GCTL_SR 0x00020000 13128cc72361SWai Yew CHAY #define GCTL_SD 0x00040000 13138cc72361SWai Yew CHAY #define GCTL_SE 0x00080000 13148cc72361SWai Yew CHAY #define GCTL_AID 0x00100000 13158cc72361SWai Yew CHAY 13168cc72361SWai Yew CHAY static int hw_pll_init(struct hw *hw, unsigned int rsr) 13178cc72361SWai Yew CHAY { 13188cc72361SWai Yew CHAY unsigned int pllctl; 1319514eef9cSTakashi Iwai int i; 13208cc72361SWai Yew CHAY 13218cc72361SWai Yew CHAY pllctl = (48000 == rsr) ? 0x1480a001 : 0x1480a731; 13228cc72361SWai Yew CHAY for (i = 0; i < 3; i++) { 13238cc72361SWai Yew CHAY if (hw_read_20kx(hw, PLLCTL) == pllctl) 13248cc72361SWai Yew CHAY break; 13258cc72361SWai Yew CHAY 13268cc72361SWai Yew CHAY hw_write_20kx(hw, PLLCTL, pllctl); 13278cc72361SWai Yew CHAY mdelay(40); 13288cc72361SWai Yew CHAY } 13298cc72361SWai Yew CHAY if (i >= 3) { 13308cc72361SWai Yew CHAY printk(KERN_ALERT "PLL initialization failed!!!\n"); 13318cc72361SWai Yew CHAY return -EBUSY; 13328cc72361SWai Yew CHAY } 13338cc72361SWai Yew CHAY 13348cc72361SWai Yew CHAY return 0; 13358cc72361SWai Yew CHAY } 13368cc72361SWai Yew CHAY 13378cc72361SWai Yew CHAY static int hw_auto_init(struct hw *hw) 13388cc72361SWai Yew CHAY { 13398cc72361SWai Yew CHAY unsigned int gctl; 13408cc72361SWai Yew CHAY int i; 13418cc72361SWai Yew CHAY 13428cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 13438cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAI, 0); 13448cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 13458cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAI, 1); 13468cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 13478cc72361SWai Yew CHAY mdelay(10); 13488cc72361SWai Yew CHAY for (i = 0; i < 400000; i++) { 13498cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 13508cc72361SWai Yew CHAY if (get_field(gctl, GCTL_AID)) 13518cc72361SWai Yew CHAY break; 13528cc72361SWai Yew CHAY } 13538cc72361SWai Yew CHAY if (!get_field(gctl, GCTL_AID)) { 13548cc72361SWai Yew CHAY printk(KERN_ALERT "Card Auto-init failed!!!\n"); 13558cc72361SWai Yew CHAY return -EBUSY; 13568cc72361SWai Yew CHAY } 13578cc72361SWai Yew CHAY 13588cc72361SWai Yew CHAY return 0; 13598cc72361SWai Yew CHAY } 13608cc72361SWai Yew CHAY 13618cc72361SWai Yew CHAY static int i2c_unlock(struct hw *hw) 13628cc72361SWai Yew CHAY { 13638cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13648cc72361SWai Yew CHAY return 0; 13658cc72361SWai Yew CHAY 13668cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x8c); 13678cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x0e); 13688cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13698cc72361SWai Yew CHAY return 0; 13708cc72361SWai Yew CHAY 13718cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0xee); 13728cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0xaa); 13738cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13748cc72361SWai Yew CHAY return 0; 13758cc72361SWai Yew CHAY 13768cc72361SWai Yew CHAY return -1; 13778cc72361SWai Yew CHAY } 13788cc72361SWai Yew CHAY 13798cc72361SWai Yew CHAY static void i2c_lock(struct hw *hw) 13808cc72361SWai Yew CHAY { 13818cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13828cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x00); 13838cc72361SWai Yew CHAY } 13848cc72361SWai Yew CHAY 13858cc72361SWai Yew CHAY static void i2c_write(struct hw *hw, u32 device, u32 addr, u32 data) 13868cc72361SWai Yew CHAY { 1387514eef9cSTakashi Iwai unsigned int ret; 13888cc72361SWai Yew CHAY 13898cc72361SWai Yew CHAY do { 13908cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 13918cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 13928cc72361SWai Yew CHAY hw_write_pci(hw, 0xE0, device); 13938cc72361SWai Yew CHAY hw_write_pci(hw, 0xE4, (data << 8) | (addr & 0xff)); 13948cc72361SWai Yew CHAY } 13958cc72361SWai Yew CHAY 13968cc72361SWai Yew CHAY /* DAC operations */ 13978cc72361SWai Yew CHAY 13988cc72361SWai Yew CHAY static int hw_reset_dac(struct hw *hw) 13998cc72361SWai Yew CHAY { 1400514eef9cSTakashi Iwai u32 i; 1401514eef9cSTakashi Iwai u16 gpioorg; 1402514eef9cSTakashi Iwai unsigned int ret; 14038cc72361SWai Yew CHAY 14048cc72361SWai Yew CHAY if (i2c_unlock(hw)) 14058cc72361SWai Yew CHAY return -1; 14068cc72361SWai Yew CHAY 14078cc72361SWai Yew CHAY do { 14088cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 14098cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 14108cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 14118cc72361SWai Yew CHAY 14128cc72361SWai Yew CHAY /* To be effective, need to reset the DAC twice. */ 14138cc72361SWai Yew CHAY for (i = 0; i < 2; i++) { 14148cc72361SWai Yew CHAY /* set gpio */ 14158cc72361SWai Yew CHAY mdelay(100); 14168cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14178cc72361SWai Yew CHAY gpioorg &= 0xfffd; 14188cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14198cc72361SWai Yew CHAY mdelay(1); 14208cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg | 0x2); 14218cc72361SWai Yew CHAY } 14228cc72361SWai Yew CHAY 14238cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x01, 0x80); 14248cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x02, 0x10); 14258cc72361SWai Yew CHAY 14268cc72361SWai Yew CHAY i2c_lock(hw); 14278cc72361SWai Yew CHAY 14288cc72361SWai Yew CHAY return 0; 14298cc72361SWai Yew CHAY } 14308cc72361SWai Yew CHAY 14318cc72361SWai Yew CHAY static int hw_dac_init(struct hw *hw, const struct dac_conf *info) 14328cc72361SWai Yew CHAY { 1433514eef9cSTakashi Iwai u32 data; 1434514eef9cSTakashi Iwai u16 gpioorg; 1435514eef9cSTakashi Iwai unsigned int ret; 14368cc72361SWai Yew CHAY 14379470195aSTakashi Iwai if (hw->model == CTSB055X) { 14388cc72361SWai Yew CHAY /* SB055x, unmute outputs */ 14398cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14408cc72361SWai Yew CHAY gpioorg &= 0xffbf; /* set GPIO6 to low */ 14418cc72361SWai Yew CHAY gpioorg |= 2; /* set GPIO1 to high */ 14428cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14438cc72361SWai Yew CHAY return 0; 14448cc72361SWai Yew CHAY } 14458cc72361SWai Yew CHAY 14468cc72361SWai Yew CHAY /* mute outputs */ 14478cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14488cc72361SWai Yew CHAY gpioorg &= 0xffbf; 14498cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14508cc72361SWai Yew CHAY 14518cc72361SWai Yew CHAY hw_reset_dac(hw); 14528cc72361SWai Yew CHAY 14538cc72361SWai Yew CHAY if (i2c_unlock(hw)) 14548cc72361SWai Yew CHAY return -1; 14558cc72361SWai Yew CHAY 14568cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 14578cc72361SWai Yew CHAY do { 14588cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 14598cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 14608cc72361SWai Yew CHAY 14618cc72361SWai Yew CHAY switch (info->msr) { 14628cc72361SWai Yew CHAY case 1: 14638cc72361SWai Yew CHAY data = 0x24; 14648cc72361SWai Yew CHAY break; 14658cc72361SWai Yew CHAY case 2: 14668cc72361SWai Yew CHAY data = 0x25; 14678cc72361SWai Yew CHAY break; 14688cc72361SWai Yew CHAY case 4: 14698cc72361SWai Yew CHAY data = 0x26; 14708cc72361SWai Yew CHAY break; 14718cc72361SWai Yew CHAY default: 14728cc72361SWai Yew CHAY data = 0x24; 14738cc72361SWai Yew CHAY break; 14748cc72361SWai Yew CHAY } 14758cc72361SWai Yew CHAY 14768cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x06, data); 14778cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x09, data); 14788cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x0c, data); 14798cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x0f, data); 14808cc72361SWai Yew CHAY 14818cc72361SWai Yew CHAY i2c_lock(hw); 14828cc72361SWai Yew CHAY 14838cc72361SWai Yew CHAY /* unmute outputs */ 14848cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14858cc72361SWai Yew CHAY gpioorg = gpioorg | 0x40; 14868cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14878cc72361SWai Yew CHAY 14888cc72361SWai Yew CHAY return 0; 14898cc72361SWai Yew CHAY } 14908cc72361SWai Yew CHAY 14918cc72361SWai Yew CHAY /* ADC operations */ 14928cc72361SWai Yew CHAY 14938cc72361SWai Yew CHAY static int is_adc_input_selected_SB055x(struct hw *hw, enum ADCSRC type) 14948cc72361SWai Yew CHAY { 1495514eef9cSTakashi Iwai return 0; 14968cc72361SWai Yew CHAY } 14978cc72361SWai Yew CHAY 14988cc72361SWai Yew CHAY static int is_adc_input_selected_SBx(struct hw *hw, enum ADCSRC type) 14998cc72361SWai Yew CHAY { 1500514eef9cSTakashi Iwai u32 data; 15018cc72361SWai Yew CHAY 15028cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 15038cc72361SWai Yew CHAY switch (type) { 15048cc72361SWai Yew CHAY case ADC_MICIN: 15058cc72361SWai Yew CHAY data = ((data & (0x1<<7)) && (data & (0x1<<8))); 15068cc72361SWai Yew CHAY break; 15078cc72361SWai Yew CHAY case ADC_LINEIN: 15088cc72361SWai Yew CHAY data = (!(data & (0x1<<7)) && (data & (0x1<<8))); 15098cc72361SWai Yew CHAY break; 15108cc72361SWai Yew CHAY case ADC_NONE: /* Digital I/O */ 15118cc72361SWai Yew CHAY data = (!(data & (0x1<<8))); 15128cc72361SWai Yew CHAY break; 15138cc72361SWai Yew CHAY default: 15148cc72361SWai Yew CHAY data = 0; 15158cc72361SWai Yew CHAY } 15168cc72361SWai Yew CHAY return data; 15178cc72361SWai Yew CHAY } 15188cc72361SWai Yew CHAY 15198cc72361SWai Yew CHAY static int is_adc_input_selected_hendrix(struct hw *hw, enum ADCSRC type) 15208cc72361SWai Yew CHAY { 1521514eef9cSTakashi Iwai u32 data; 15228cc72361SWai Yew CHAY 15238cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 15248cc72361SWai Yew CHAY switch (type) { 15258cc72361SWai Yew CHAY case ADC_MICIN: 15268cc72361SWai Yew CHAY data = (data & (0x1 << 7)) ? 1 : 0; 15278cc72361SWai Yew CHAY break; 15288cc72361SWai Yew CHAY case ADC_LINEIN: 15298cc72361SWai Yew CHAY data = (data & (0x1 << 7)) ? 0 : 1; 15308cc72361SWai Yew CHAY break; 15318cc72361SWai Yew CHAY default: 15328cc72361SWai Yew CHAY data = 0; 15338cc72361SWai Yew CHAY } 15348cc72361SWai Yew CHAY return data; 15358cc72361SWai Yew CHAY } 15368cc72361SWai Yew CHAY 15378cc72361SWai Yew CHAY static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) 15388cc72361SWai Yew CHAY { 15399470195aSTakashi Iwai switch (hw->model) { 15409470195aSTakashi Iwai case CTSB055X: 15418cc72361SWai Yew CHAY return is_adc_input_selected_SB055x(hw, type); 15429470195aSTakashi Iwai case CTSB073X: 15438cc72361SWai Yew CHAY return is_adc_input_selected_hendrix(hw, type); 154409521d2eSTakashi Iwai case CTUAA: 15458cc72361SWai Yew CHAY return is_adc_input_selected_hendrix(hw, type); 15469470195aSTakashi Iwai default: 15478cc72361SWai Yew CHAY return is_adc_input_selected_SBx(hw, type); 15488cc72361SWai Yew CHAY } 15498cc72361SWai Yew CHAY } 15508cc72361SWai Yew CHAY 15518cc72361SWai Yew CHAY static int 15528cc72361SWai Yew CHAY adc_input_select_SB055x(struct hw *hw, enum ADCSRC type, unsigned char boost) 15538cc72361SWai Yew CHAY { 1554514eef9cSTakashi Iwai u32 data; 15558cc72361SWai Yew CHAY 15568cc72361SWai Yew CHAY /* 15578cc72361SWai Yew CHAY * check and set the following GPIO bits accordingly 15588cc72361SWai Yew CHAY * ADC_Gain = GPIO2 15598cc72361SWai Yew CHAY * DRM_off = GPIO3 15608cc72361SWai Yew CHAY * Mic_Pwr_on = GPIO7 15618cc72361SWai Yew CHAY * Digital_IO_Sel = GPIO8 15628cc72361SWai Yew CHAY * Mic_Sw = GPIO9 15638cc72361SWai Yew CHAY * Aux/MicLine_Sw = GPIO12 15648cc72361SWai Yew CHAY */ 15658cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 15668cc72361SWai Yew CHAY data &= 0xec73; 15678cc72361SWai Yew CHAY switch (type) { 15688cc72361SWai Yew CHAY case ADC_MICIN: 15698cc72361SWai Yew CHAY data |= (0x1<<7) | (0x1<<8) | (0x1<<9) ; 15708cc72361SWai Yew CHAY data |= boost ? (0x1<<2) : 0; 15718cc72361SWai Yew CHAY break; 15728cc72361SWai Yew CHAY case ADC_LINEIN: 15738cc72361SWai Yew CHAY data |= (0x1<<8); 15748cc72361SWai Yew CHAY break; 15758cc72361SWai Yew CHAY case ADC_AUX: 15768cc72361SWai Yew CHAY data |= (0x1<<8) | (0x1<<12); 15778cc72361SWai Yew CHAY break; 15788cc72361SWai Yew CHAY case ADC_NONE: 15798cc72361SWai Yew CHAY data |= (0x1<<12); /* set to digital */ 15808cc72361SWai Yew CHAY break; 15818cc72361SWai Yew CHAY default: 15828cc72361SWai Yew CHAY return -1; 15838cc72361SWai Yew CHAY } 15848cc72361SWai Yew CHAY 15858cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 15868cc72361SWai Yew CHAY 15878cc72361SWai Yew CHAY return 0; 15888cc72361SWai Yew CHAY } 15898cc72361SWai Yew CHAY 15908cc72361SWai Yew CHAY 15918cc72361SWai Yew CHAY static int 15928cc72361SWai Yew CHAY adc_input_select_SBx(struct hw *hw, enum ADCSRC type, unsigned char boost) 15938cc72361SWai Yew CHAY { 1594514eef9cSTakashi Iwai u32 data; 1595514eef9cSTakashi Iwai u32 i2c_data; 1596514eef9cSTakashi Iwai unsigned int ret; 15978cc72361SWai Yew CHAY 15988cc72361SWai Yew CHAY if (i2c_unlock(hw)) 15998cc72361SWai Yew CHAY return -1; 16008cc72361SWai Yew CHAY 16018cc72361SWai Yew CHAY do { 16028cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 16038cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 16048cc72361SWai Yew CHAY /* set i2c access mode as Direct Control */ 16058cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); 16068cc72361SWai Yew CHAY 16078cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 16088cc72361SWai Yew CHAY switch (type) { 16098cc72361SWai Yew CHAY case ADC_MICIN: 16108cc72361SWai Yew CHAY data |= ((0x1 << 7) | (0x1 << 8)); 16118cc72361SWai Yew CHAY i2c_data = 0x1; /* Mic-in */ 16128cc72361SWai Yew CHAY break; 16138cc72361SWai Yew CHAY case ADC_LINEIN: 16148cc72361SWai Yew CHAY data &= ~(0x1 << 7); 16158cc72361SWai Yew CHAY data |= (0x1 << 8); 16168cc72361SWai Yew CHAY i2c_data = 0x2; /* Line-in */ 16178cc72361SWai Yew CHAY break; 16188cc72361SWai Yew CHAY case ADC_NONE: 16198cc72361SWai Yew CHAY data &= ~(0x1 << 8); 16208cc72361SWai Yew CHAY i2c_data = 0x0; /* set to Digital */ 16218cc72361SWai Yew CHAY break; 16228cc72361SWai Yew CHAY default: 16238cc72361SWai Yew CHAY i2c_lock(hw); 16248cc72361SWai Yew CHAY return -1; 16258cc72361SWai Yew CHAY } 16268cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 16278cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 16288cc72361SWai Yew CHAY if (boost) { 16298cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 16308cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 16318cc72361SWai Yew CHAY } else { 16328cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 16338cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 16348cc72361SWai Yew CHAY } 16358cc72361SWai Yew CHAY 16368cc72361SWai Yew CHAY i2c_lock(hw); 16378cc72361SWai Yew CHAY 16388cc72361SWai Yew CHAY return 0; 16398cc72361SWai Yew CHAY } 16408cc72361SWai Yew CHAY 16418cc72361SWai Yew CHAY static int 16428cc72361SWai Yew CHAY adc_input_select_hendrix(struct hw *hw, enum ADCSRC type, unsigned char boost) 16438cc72361SWai Yew CHAY { 1644514eef9cSTakashi Iwai u32 data; 1645514eef9cSTakashi Iwai u32 i2c_data; 1646514eef9cSTakashi Iwai unsigned int ret; 16478cc72361SWai Yew CHAY 16488cc72361SWai Yew CHAY if (i2c_unlock(hw)) 16498cc72361SWai Yew CHAY return -1; 16508cc72361SWai Yew CHAY 16518cc72361SWai Yew CHAY do { 16528cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 16538cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 16548cc72361SWai Yew CHAY /* set i2c access mode as Direct Control */ 16558cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); 16568cc72361SWai Yew CHAY 16578cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 16588cc72361SWai Yew CHAY switch (type) { 16598cc72361SWai Yew CHAY case ADC_MICIN: 16608cc72361SWai Yew CHAY data |= (0x1 << 7); 16618cc72361SWai Yew CHAY i2c_data = 0x1; /* Mic-in */ 16628cc72361SWai Yew CHAY break; 16638cc72361SWai Yew CHAY case ADC_LINEIN: 16648cc72361SWai Yew CHAY data &= ~(0x1 << 7); 16658cc72361SWai Yew CHAY i2c_data = 0x2; /* Line-in */ 16668cc72361SWai Yew CHAY break; 16678cc72361SWai Yew CHAY default: 16688cc72361SWai Yew CHAY i2c_lock(hw); 16698cc72361SWai Yew CHAY return -1; 16708cc72361SWai Yew CHAY } 16718cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 16728cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 16738cc72361SWai Yew CHAY if (boost) { 16748cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 16758cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 16768cc72361SWai Yew CHAY } else { 16778cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 16788cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 16798cc72361SWai Yew CHAY } 16808cc72361SWai Yew CHAY 16818cc72361SWai Yew CHAY i2c_lock(hw); 16828cc72361SWai Yew CHAY 16838cc72361SWai Yew CHAY return 0; 16848cc72361SWai Yew CHAY } 16858cc72361SWai Yew CHAY 16868cc72361SWai Yew CHAY static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) 16878cc72361SWai Yew CHAY { 16889470195aSTakashi Iwai int state = type == ADC_MICIN; 16898cc72361SWai Yew CHAY 16909470195aSTakashi Iwai switch (hw->model) { 16919470195aSTakashi Iwai case CTSB055X: 16929470195aSTakashi Iwai return adc_input_select_SB055x(hw, type, state); 16939470195aSTakashi Iwai case CTSB073X: 16949470195aSTakashi Iwai return adc_input_select_hendrix(hw, type, state); 169509521d2eSTakashi Iwai case CTUAA: 16969470195aSTakashi Iwai return adc_input_select_hendrix(hw, type, state); 16979470195aSTakashi Iwai default: 16989470195aSTakashi Iwai return adc_input_select_SBx(hw, type, state); 16998cc72361SWai Yew CHAY } 17008cc72361SWai Yew CHAY } 17018cc72361SWai Yew CHAY 17028cc72361SWai Yew CHAY static int adc_init_SB055x(struct hw *hw, int input, int mic20db) 17038cc72361SWai Yew CHAY { 17048cc72361SWai Yew CHAY return adc_input_select_SB055x(hw, input, mic20db); 17058cc72361SWai Yew CHAY } 17068cc72361SWai Yew CHAY 17078cc72361SWai Yew CHAY static int adc_init_SBx(struct hw *hw, int input, int mic20db) 17088cc72361SWai Yew CHAY { 17098cc72361SWai Yew CHAY u16 gpioorg; 17108cc72361SWai Yew CHAY u16 input_source; 1711514eef9cSTakashi Iwai u32 adcdata; 1712514eef9cSTakashi Iwai unsigned int ret; 17138cc72361SWai Yew CHAY 17148cc72361SWai Yew CHAY input_source = 0x100; /* default to analog */ 17158cc72361SWai Yew CHAY switch (input) { 17168cc72361SWai Yew CHAY case ADC_MICIN: 17178cc72361SWai Yew CHAY adcdata = 0x1; 17188cc72361SWai Yew CHAY input_source = 0x180; /* set GPIO7 to select Mic */ 17198cc72361SWai Yew CHAY break; 17208cc72361SWai Yew CHAY case ADC_LINEIN: 17218cc72361SWai Yew CHAY adcdata = 0x2; 17228cc72361SWai Yew CHAY break; 17238cc72361SWai Yew CHAY case ADC_VIDEO: 17248cc72361SWai Yew CHAY adcdata = 0x4; 17258cc72361SWai Yew CHAY break; 17268cc72361SWai Yew CHAY case ADC_AUX: 17278cc72361SWai Yew CHAY adcdata = 0x8; 17288cc72361SWai Yew CHAY break; 17298cc72361SWai Yew CHAY case ADC_NONE: 17308cc72361SWai Yew CHAY adcdata = 0x0; 17318cc72361SWai Yew CHAY input_source = 0x0; /* set to Digital */ 17328cc72361SWai Yew CHAY break; 17338cc72361SWai Yew CHAY default: 1734514eef9cSTakashi Iwai adcdata = 0x0; 17358cc72361SWai Yew CHAY break; 17368cc72361SWai Yew CHAY } 17378cc72361SWai Yew CHAY 17388cc72361SWai Yew CHAY if (i2c_unlock(hw)) 17398cc72361SWai Yew CHAY return -1; 17408cc72361SWai Yew CHAY 17418cc72361SWai Yew CHAY do { 17428cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 17438cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 17448cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 17458cc72361SWai Yew CHAY 17468cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x0e, 0x08); 17478cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x18, 0x0a); 17488cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x28, 0x86); 17498cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, adcdata); 17508cc72361SWai Yew CHAY 17518cc72361SWai Yew CHAY if (mic20db) { 17528cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xf7); 17538cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xf7); 17548cc72361SWai Yew CHAY } else { 17558cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); 17568cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); 17578cc72361SWai Yew CHAY } 17588cc72361SWai Yew CHAY 17598cc72361SWai Yew CHAY if (!(hw_read_20kx(hw, ID0) & 0x100)) 17608cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x16, 0x26); 17618cc72361SWai Yew CHAY 17628cc72361SWai Yew CHAY i2c_lock(hw); 17638cc72361SWai Yew CHAY 17648cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 17658cc72361SWai Yew CHAY gpioorg &= 0xfe7f; 17668cc72361SWai Yew CHAY gpioorg |= input_source; 17678cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 17688cc72361SWai Yew CHAY 17698cc72361SWai Yew CHAY return 0; 17708cc72361SWai Yew CHAY } 17718cc72361SWai Yew CHAY 17728cc72361SWai Yew CHAY static int hw_adc_init(struct hw *hw, const struct adc_conf *info) 17738cc72361SWai Yew CHAY { 17749470195aSTakashi Iwai if (hw->model == CTSB055X) 17759470195aSTakashi Iwai return adc_init_SB055x(hw, info->input, info->mic20db); 17769470195aSTakashi Iwai else 17779470195aSTakashi Iwai return adc_init_SBx(hw, info->input, info->mic20db); 17788cc72361SWai Yew CHAY } 17798cc72361SWai Yew CHAY 17808cc72361SWai Yew CHAY static int hw_have_digit_io_switch(struct hw *hw) 17818cc72361SWai Yew CHAY { 17828cc72361SWai Yew CHAY /* SB073x and Vista compatible cards have no digit IO switch */ 178309521d2eSTakashi Iwai return !(hw->model == CTSB073X || hw->model == CTUAA); 17848cc72361SWai Yew CHAY } 17858cc72361SWai Yew CHAY 1786*55309216SHarry Butterworth static int hw_have_dedicated_mic(struct hw *hw) 1787*55309216SHarry Butterworth { 1788*55309216SHarry Butterworth return 0; 1789*55309216SHarry Butterworth } 1790*55309216SHarry Butterworth 1791*55309216SHarry Butterworth static int hw_have_output_switch(struct hw *hw) 1792*55309216SHarry Butterworth { 1793*55309216SHarry Butterworth return 0; 1794*55309216SHarry Butterworth } 1795*55309216SHarry Butterworth 1796*55309216SHarry Butterworth static int hw_have_mic_source_switch(struct hw *hw) 1797*55309216SHarry Butterworth { 1798*55309216SHarry Butterworth return 0; 1799*55309216SHarry Butterworth } 1800*55309216SHarry Butterworth 180142a0b318STakashi Iwai #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) 180242a0b318STakashi Iwai 18038cc72361SWai Yew CHAY #define UAA_CFG_PWRSTATUS 0x44 18048cc72361SWai Yew CHAY #define UAA_CFG_SPACE_FLAG 0xA0 18058cc72361SWai Yew CHAY #define UAA_CORE_CHANGE 0x3FFC 18068cc72361SWai Yew CHAY static int uaa_to_xfi(struct pci_dev *pci) 18078cc72361SWai Yew CHAY { 18088cc72361SWai Yew CHAY unsigned int bar0, bar1, bar2, bar3, bar4, bar5; 18098cc72361SWai Yew CHAY unsigned int cmd, irq, cl_size, l_timer, pwr; 1810514eef9cSTakashi Iwai unsigned int is_uaa; 18118cc72361SWai Yew CHAY unsigned int data[4] = {0}; 18128cc72361SWai Yew CHAY unsigned int io_base; 18138cc72361SWai Yew CHAY void *mem_base; 1814514eef9cSTakashi Iwai int i; 181542a0b318STakashi Iwai const u32 CTLX = CTLBITS('C', 'T', 'L', 'X'); 181642a0b318STakashi Iwai const u32 CTL_ = CTLBITS('C', 'T', 'L', '-'); 181742a0b318STakashi Iwai const u32 CTLF = CTLBITS('C', 'T', 'L', 'F'); 181842a0b318STakashi Iwai const u32 CTLi = CTLBITS('C', 'T', 'L', 'i'); 181942a0b318STakashi Iwai const u32 CTLA = CTLBITS('C', 'T', 'L', 'A'); 182042a0b318STakashi Iwai const u32 CTLZ = CTLBITS('C', 'T', 'L', 'Z'); 182142a0b318STakashi Iwai const u32 CTLL = CTLBITS('C', 'T', 'L', 'L'); 18228cc72361SWai Yew CHAY 18238cc72361SWai Yew CHAY /* By default, Hendrix card UAA Bar0 should be using memory... */ 18248cc72361SWai Yew CHAY io_base = pci_resource_start(pci, 0); 18258cc72361SWai Yew CHAY mem_base = ioremap(io_base, pci_resource_len(pci, 0)); 182635ebf6e7STakashi Iwai if (!mem_base) 18278cc72361SWai Yew CHAY return -ENOENT; 18288cc72361SWai Yew CHAY 18298cc72361SWai Yew CHAY /* Read current mode from Mode Change Register */ 18308cc72361SWai Yew CHAY for (i = 0; i < 4; i++) 18318cc72361SWai Yew CHAY data[i] = readl(mem_base + UAA_CORE_CHANGE); 18328cc72361SWai Yew CHAY 18338cc72361SWai Yew CHAY /* Determine current mode... */ 18348cc72361SWai Yew CHAY if (data[0] == CTLA) { 18358cc72361SWai Yew CHAY is_uaa = ((data[1] == CTLZ && data[2] == CTLL 18368cc72361SWai Yew CHAY && data[3] == CTLA) || (data[1] == CTLA 18378cc72361SWai Yew CHAY && data[2] == CTLZ && data[3] == CTLL)); 18388cc72361SWai Yew CHAY } else if (data[0] == CTLZ) { 18398cc72361SWai Yew CHAY is_uaa = (data[1] == CTLL 18408cc72361SWai Yew CHAY && data[2] == CTLA && data[3] == CTLA); 18418cc72361SWai Yew CHAY } else if (data[0] == CTLL) { 18428cc72361SWai Yew CHAY is_uaa = (data[1] == CTLA 18438cc72361SWai Yew CHAY && data[2] == CTLA && data[3] == CTLZ); 18448cc72361SWai Yew CHAY } else { 18458cc72361SWai Yew CHAY is_uaa = 0; 18468cc72361SWai Yew CHAY } 18478cc72361SWai Yew CHAY 18488cc72361SWai Yew CHAY if (!is_uaa) { 18498cc72361SWai Yew CHAY /* Not in UAA mode currently. Return directly. */ 18508cc72361SWai Yew CHAY iounmap(mem_base); 18518cc72361SWai Yew CHAY return 0; 18528cc72361SWai Yew CHAY } 18538cc72361SWai Yew CHAY 18548cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_0, &bar0); 18558cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_1, &bar1); 18568cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_2, &bar2); 18578cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_3, &bar3); 18588cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_4, &bar4); 18598cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_5, &bar5); 18608cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_INTERRUPT_LINE, &irq); 18618cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_CACHE_LINE_SIZE, &cl_size); 18628cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_LATENCY_TIMER, &l_timer); 18638cc72361SWai Yew CHAY pci_read_config_dword(pci, UAA_CFG_PWRSTATUS, &pwr); 18648cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_COMMAND, &cmd); 18658cc72361SWai Yew CHAY 18668cc72361SWai Yew CHAY /* Set up X-Fi core PCI configuration space. */ 18678cc72361SWai Yew CHAY /* Switch to X-Fi config space with BAR0 exposed. */ 18688cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x87654321); 18698cc72361SWai Yew CHAY /* Copy UAA's BAR5 into X-Fi BAR0 */ 18708cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_0, bar5); 18718cc72361SWai Yew CHAY /* Switch to X-Fi config space without BAR0 exposed. */ 18728cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x12345678); 18738cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, bar1); 18748cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_2, bar2); 18758cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_3, bar3); 18768cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_4, bar4); 18778cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_INTERRUPT_LINE, irq); 18788cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_CACHE_LINE_SIZE, cl_size); 18798cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_LATENCY_TIMER, l_timer); 18808cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_PWRSTATUS, pwr); 18818cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_COMMAND, cmd); 18828cc72361SWai Yew CHAY 18838cc72361SWai Yew CHAY /* Switch to X-Fi mode */ 18848cc72361SWai Yew CHAY writel(CTLX, (mem_base + UAA_CORE_CHANGE)); 18858cc72361SWai Yew CHAY writel(CTL_, (mem_base + UAA_CORE_CHANGE)); 18868cc72361SWai Yew CHAY writel(CTLF, (mem_base + UAA_CORE_CHANGE)); 18878cc72361SWai Yew CHAY writel(CTLi, (mem_base + UAA_CORE_CHANGE)); 18888cc72361SWai Yew CHAY 18898cc72361SWai Yew CHAY iounmap(mem_base); 18908cc72361SWai Yew CHAY 18918cc72361SWai Yew CHAY return 0; 18928cc72361SWai Yew CHAY } 18938cc72361SWai Yew CHAY 1894b7bbf876STakashi Iwai static irqreturn_t ct_20k1_interrupt(int irq, void *dev_id) 1895b7bbf876STakashi Iwai { 1896b7bbf876STakashi Iwai struct hw *hw = dev_id; 1897b7bbf876STakashi Iwai unsigned int status; 1898b7bbf876STakashi Iwai 1899b7bbf876STakashi Iwai status = hw_read_20kx(hw, GIP); 1900b7bbf876STakashi Iwai if (!status) 1901b7bbf876STakashi Iwai return IRQ_NONE; 1902b7bbf876STakashi Iwai 1903b7bbf876STakashi Iwai if (hw->irq_callback) 1904b7bbf876STakashi Iwai hw->irq_callback(hw->irq_callback_data, status); 1905b7bbf876STakashi Iwai 1906b7bbf876STakashi Iwai hw_write_20kx(hw, GIP, status); 1907b7bbf876STakashi Iwai return IRQ_HANDLED; 1908b7bbf876STakashi Iwai } 1909b7bbf876STakashi Iwai 19108cc72361SWai Yew CHAY static int hw_card_start(struct hw *hw) 19118cc72361SWai Yew CHAY { 1912514eef9cSTakashi Iwai int err; 19138cc72361SWai Yew CHAY struct pci_dev *pci = hw->pci; 19148cc72361SWai Yew CHAY 19158cc72361SWai Yew CHAY err = pci_enable_device(pci); 19168cc72361SWai Yew CHAY if (err < 0) 19178cc72361SWai Yew CHAY return err; 19188cc72361SWai Yew CHAY 19198cc72361SWai Yew CHAY /* Set DMA transfer mask */ 19206bc5874aSTakashi Iwai if (pci_set_dma_mask(pci, CT_XFI_DMA_MASK) < 0 || 19216bc5874aSTakashi Iwai pci_set_consistent_dma_mask(pci, CT_XFI_DMA_MASK) < 0) { 19228cc72361SWai Yew CHAY printk(KERN_ERR "architecture does not support PCI " 19236bc5874aSTakashi Iwai "busmaster DMA with mask 0x%llx\n", 19246bc5874aSTakashi Iwai CT_XFI_DMA_MASK); 19258cc72361SWai Yew CHAY err = -ENXIO; 19268cc72361SWai Yew CHAY goto error1; 19278cc72361SWai Yew CHAY } 19288cc72361SWai Yew CHAY 192929959a09SWai Yew CHAY if (!hw->io_base) { 19308cc72361SWai Yew CHAY err = pci_request_regions(pci, "XFi"); 19318cc72361SWai Yew CHAY if (err < 0) 19328cc72361SWai Yew CHAY goto error1; 19338cc72361SWai Yew CHAY 193429959a09SWai Yew CHAY if (hw->model == CTUAA) 193529959a09SWai Yew CHAY hw->io_base = pci_resource_start(pci, 5); 193629959a09SWai Yew CHAY else 193729959a09SWai Yew CHAY hw->io_base = pci_resource_start(pci, 0); 193829959a09SWai Yew CHAY 193929959a09SWai Yew CHAY } 194029959a09SWai Yew CHAY 19418cc72361SWai Yew CHAY /* Switch to X-Fi mode from UAA mode if neeeded */ 194209521d2eSTakashi Iwai if (hw->model == CTUAA) { 19438cc72361SWai Yew CHAY err = uaa_to_xfi(pci); 19448cc72361SWai Yew CHAY if (err) 19458cc72361SWai Yew CHAY goto error2; 19468cc72361SWai Yew CHAY 19478cc72361SWai Yew CHAY } 19488cc72361SWai Yew CHAY 194929959a09SWai Yew CHAY if (hw->irq < 0) { 1950b7bbf876STakashi Iwai err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, 1951b7bbf876STakashi Iwai "ctxfi", hw); 1952b7bbf876STakashi Iwai if (err < 0) { 1953b7bbf876STakashi Iwai printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); 19548cc72361SWai Yew CHAY goto error2; 19558cc72361SWai Yew CHAY } 19568cc72361SWai Yew CHAY hw->irq = pci->irq; 195729959a09SWai Yew CHAY } 19588cc72361SWai Yew CHAY 19598cc72361SWai Yew CHAY pci_set_master(pci); 19608cc72361SWai Yew CHAY 19618cc72361SWai Yew CHAY return 0; 19628cc72361SWai Yew CHAY 19638cc72361SWai Yew CHAY error2: 19648cc72361SWai Yew CHAY pci_release_regions(pci); 19658cc72361SWai Yew CHAY hw->io_base = 0; 19668cc72361SWai Yew CHAY error1: 19678cc72361SWai Yew CHAY pci_disable_device(pci); 19688cc72361SWai Yew CHAY return err; 19698cc72361SWai Yew CHAY } 19708cc72361SWai Yew CHAY 19718cc72361SWai Yew CHAY static int hw_card_stop(struct hw *hw) 19728cc72361SWai Yew CHAY { 197329959a09SWai Yew CHAY unsigned int data; 197429959a09SWai Yew CHAY 197529959a09SWai Yew CHAY /* disable transport bus master and queueing of request */ 197629959a09SWai Yew CHAY hw_write_20kx(hw, TRNCTL, 0x00); 197729959a09SWai Yew CHAY 197829959a09SWai Yew CHAY /* disable pll */ 197929959a09SWai Yew CHAY data = hw_read_20kx(hw, PLLCTL); 198029959a09SWai Yew CHAY hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12)))); 198129959a09SWai Yew CHAY 19828cc72361SWai Yew CHAY /* TODO: Disable interrupt and so on... */ 1983b7bbf876STakashi Iwai if (hw->irq >= 0) 1984b7bbf876STakashi Iwai synchronize_irq(hw->irq); 19858cc72361SWai Yew CHAY return 0; 19868cc72361SWai Yew CHAY } 19878cc72361SWai Yew CHAY 19888cc72361SWai Yew CHAY static int hw_card_shutdown(struct hw *hw) 19898cc72361SWai Yew CHAY { 19908cc72361SWai Yew CHAY if (hw->irq >= 0) 19918cc72361SWai Yew CHAY free_irq(hw->irq, hw); 19928cc72361SWai Yew CHAY 19938cc72361SWai Yew CHAY hw->irq = -1; 19948cc72361SWai Yew CHAY 199535ebf6e7STakashi Iwai if (hw->mem_base) 19968cc72361SWai Yew CHAY iounmap((void *)hw->mem_base); 19978cc72361SWai Yew CHAY 19988cc72361SWai Yew CHAY hw->mem_base = (unsigned long)NULL; 19998cc72361SWai Yew CHAY 20008cc72361SWai Yew CHAY if (hw->io_base) 20018cc72361SWai Yew CHAY pci_release_regions(hw->pci); 20028cc72361SWai Yew CHAY 20038cc72361SWai Yew CHAY hw->io_base = 0; 20048cc72361SWai Yew CHAY 20058cc72361SWai Yew CHAY pci_disable_device(hw->pci); 20068cc72361SWai Yew CHAY 20078cc72361SWai Yew CHAY return 0; 20088cc72361SWai Yew CHAY } 20098cc72361SWai Yew CHAY 20108cc72361SWai Yew CHAY static int hw_card_init(struct hw *hw, struct card_conf *info) 20118cc72361SWai Yew CHAY { 20128cc72361SWai Yew CHAY int err; 20138cc72361SWai Yew CHAY unsigned int gctl; 2014514eef9cSTakashi Iwai u32 data; 20158cc72361SWai Yew CHAY struct dac_conf dac_info = {0}; 20168cc72361SWai Yew CHAY struct adc_conf adc_info = {0}; 20178cc72361SWai Yew CHAY struct daio_conf daio_info = {0}; 20188cc72361SWai Yew CHAY struct trn_conf trn_info = {0}; 20198cc72361SWai Yew CHAY 20208cc72361SWai Yew CHAY /* Get PCI io port base address and do Hendrix switch if needed. */ 20218cc72361SWai Yew CHAY err = hw_card_start(hw); 20228cc72361SWai Yew CHAY if (err) 20238cc72361SWai Yew CHAY return err; 20248cc72361SWai Yew CHAY 20258cc72361SWai Yew CHAY /* PLL init */ 20268cc72361SWai Yew CHAY err = hw_pll_init(hw, info->rsr); 20278cc72361SWai Yew CHAY if (err < 0) 20288cc72361SWai Yew CHAY return err; 20298cc72361SWai Yew CHAY 20308cc72361SWai Yew CHAY /* kick off auto-init */ 20318cc72361SWai Yew CHAY err = hw_auto_init(hw); 20328cc72361SWai Yew CHAY if (err < 0) 20338cc72361SWai Yew CHAY return err; 20348cc72361SWai Yew CHAY 20358cc72361SWai Yew CHAY /* Enable audio ring */ 20368cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 20378cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAC, 1); 20388cc72361SWai Yew CHAY set_field(&gctl, GCTL_DBP, 1); 20398cc72361SWai Yew CHAY set_field(&gctl, GCTL_TBP, 1); 20408cc72361SWai Yew CHAY set_field(&gctl, GCTL_FBP, 1); 20418cc72361SWai Yew CHAY set_field(&gctl, GCTL_ET, 1); 20428cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 20438cc72361SWai Yew CHAY mdelay(10); 20448cc72361SWai Yew CHAY 20458cc72361SWai Yew CHAY /* Reset all global pending interrupts */ 20468cc72361SWai Yew CHAY hw_write_20kx(hw, GIE, 0); 20478cc72361SWai Yew CHAY /* Reset all SRC pending interrupts */ 20488cc72361SWai Yew CHAY hw_write_20kx(hw, SRCIP, 0); 20498cc72361SWai Yew CHAY mdelay(30); 20508cc72361SWai Yew CHAY 20518cc72361SWai Yew CHAY /* Detect the card ID and configure GPIO accordingly. */ 20529470195aSTakashi Iwai switch (hw->model) { 20539470195aSTakashi Iwai case CTSB055X: 20548cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x13fe); 20559470195aSTakashi Iwai break; 20569470195aSTakashi Iwai case CTSB073X: 20578cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x00e6); 20589470195aSTakashi Iwai break; 205909521d2eSTakashi Iwai case CTUAA: 20608cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x00c2); 20619470195aSTakashi Iwai break; 20629470195aSTakashi Iwai default: 20638cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x01e6); 20649470195aSTakashi Iwai break; 20658cc72361SWai Yew CHAY } 20668cc72361SWai Yew CHAY 20678cc72361SWai Yew CHAY trn_info.vm_pgt_phys = info->vm_pgt_phys; 20688cc72361SWai Yew CHAY err = hw_trn_init(hw, &trn_info); 20698cc72361SWai Yew CHAY if (err < 0) 20708cc72361SWai Yew CHAY return err; 20718cc72361SWai Yew CHAY 20728cc72361SWai Yew CHAY daio_info.msr = info->msr; 20738cc72361SWai Yew CHAY err = hw_daio_init(hw, &daio_info); 20748cc72361SWai Yew CHAY if (err < 0) 20758cc72361SWai Yew CHAY return err; 20768cc72361SWai Yew CHAY 20778cc72361SWai Yew CHAY dac_info.msr = info->msr; 20788cc72361SWai Yew CHAY err = hw_dac_init(hw, &dac_info); 20798cc72361SWai Yew CHAY if (err < 0) 20808cc72361SWai Yew CHAY return err; 20818cc72361SWai Yew CHAY 20828cc72361SWai Yew CHAY adc_info.msr = info->msr; 20838cc72361SWai Yew CHAY adc_info.input = ADC_LINEIN; 20848cc72361SWai Yew CHAY adc_info.mic20db = 0; 20858cc72361SWai Yew CHAY err = hw_adc_init(hw, &adc_info); 20868cc72361SWai Yew CHAY if (err < 0) 20878cc72361SWai Yew CHAY return err; 20888cc72361SWai Yew CHAY 20898cc72361SWai Yew CHAY data = hw_read_20kx(hw, SRCMCTL); 20908cc72361SWai Yew CHAY data |= 0x1; /* Enables input from the audio ring */ 20918cc72361SWai Yew CHAY hw_write_20kx(hw, SRCMCTL, data); 20928cc72361SWai Yew CHAY 20938cc72361SWai Yew CHAY return 0; 20948cc72361SWai Yew CHAY } 20958cc72361SWai Yew CHAY 209629959a09SWai Yew CHAY #ifdef CONFIG_PM 209729959a09SWai Yew CHAY static int hw_suspend(struct hw *hw, pm_message_t state) 209829959a09SWai Yew CHAY { 209929959a09SWai Yew CHAY struct pci_dev *pci = hw->pci; 210029959a09SWai Yew CHAY 210129959a09SWai Yew CHAY hw_card_stop(hw); 210229959a09SWai Yew CHAY 210329959a09SWai Yew CHAY if (hw->model == CTUAA) { 210429959a09SWai Yew CHAY /* Switch to UAA config space. */ 210529959a09SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); 210629959a09SWai Yew CHAY } 210729959a09SWai Yew CHAY 210829959a09SWai Yew CHAY pci_disable_device(pci); 210929959a09SWai Yew CHAY pci_save_state(pci); 211029959a09SWai Yew CHAY pci_set_power_state(pci, pci_choose_state(pci, state)); 211129959a09SWai Yew CHAY 211229959a09SWai Yew CHAY return 0; 211329959a09SWai Yew CHAY } 211429959a09SWai Yew CHAY 211529959a09SWai Yew CHAY static int hw_resume(struct hw *hw, struct card_conf *info) 211629959a09SWai Yew CHAY { 211729959a09SWai Yew CHAY struct pci_dev *pci = hw->pci; 211829959a09SWai Yew CHAY 211929959a09SWai Yew CHAY pci_set_power_state(pci, PCI_D0); 212029959a09SWai Yew CHAY pci_restore_state(pci); 212129959a09SWai Yew CHAY 212229959a09SWai Yew CHAY /* Re-initialize card hardware. */ 212329959a09SWai Yew CHAY return hw_card_init(hw, info); 212429959a09SWai Yew CHAY } 212529959a09SWai Yew CHAY #endif 212629959a09SWai Yew CHAY 21278cc72361SWai Yew CHAY static u32 hw_read_20kx(struct hw *hw, u32 reg) 21288cc72361SWai Yew CHAY { 21298cc72361SWai Yew CHAY u32 value; 21308cc72361SWai Yew CHAY unsigned long flags; 21318cc72361SWai Yew CHAY 21328cc72361SWai Yew CHAY spin_lock_irqsave( 21338cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21348cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x0); 21358cc72361SWai Yew CHAY value = inl(hw->io_base + 0x4); 21368cc72361SWai Yew CHAY spin_unlock_irqrestore( 21378cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21388cc72361SWai Yew CHAY 21398cc72361SWai Yew CHAY return value; 21408cc72361SWai Yew CHAY } 21418cc72361SWai Yew CHAY 21428cc72361SWai Yew CHAY static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) 21438cc72361SWai Yew CHAY { 21448cc72361SWai Yew CHAY unsigned long flags; 21458cc72361SWai Yew CHAY 21468cc72361SWai Yew CHAY spin_lock_irqsave( 21478cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21488cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x0); 21498cc72361SWai Yew CHAY outl(data, hw->io_base + 0x4); 21508cc72361SWai Yew CHAY spin_unlock_irqrestore( 21518cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21528cc72361SWai Yew CHAY 21538cc72361SWai Yew CHAY } 21548cc72361SWai Yew CHAY 21558cc72361SWai Yew CHAY static u32 hw_read_pci(struct hw *hw, u32 reg) 21568cc72361SWai Yew CHAY { 21578cc72361SWai Yew CHAY u32 value; 21588cc72361SWai Yew CHAY unsigned long flags; 21598cc72361SWai Yew CHAY 21608cc72361SWai Yew CHAY spin_lock_irqsave( 21618cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21628cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x10); 21638cc72361SWai Yew CHAY value = inl(hw->io_base + 0x14); 21648cc72361SWai Yew CHAY spin_unlock_irqrestore( 21658cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21668cc72361SWai Yew CHAY 21678cc72361SWai Yew CHAY return value; 21688cc72361SWai Yew CHAY } 21698cc72361SWai Yew CHAY 21708cc72361SWai Yew CHAY static void hw_write_pci(struct hw *hw, u32 reg, u32 data) 21718cc72361SWai Yew CHAY { 21728cc72361SWai Yew CHAY unsigned long flags; 21738cc72361SWai Yew CHAY 21748cc72361SWai Yew CHAY spin_lock_irqsave( 21758cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21768cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x10); 21778cc72361SWai Yew CHAY outl(data, hw->io_base + 0x14); 21788cc72361SWai Yew CHAY spin_unlock_irqrestore( 21798cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21808cc72361SWai Yew CHAY } 21818cc72361SWai Yew CHAY 21822a36f67fSTakashi Iwai static struct hw ct20k1_preset __devinitdata = { 21832a36f67fSTakashi Iwai .irq = -1, 21842a36f67fSTakashi Iwai 21852a36f67fSTakashi Iwai .card_init = hw_card_init, 21862a36f67fSTakashi Iwai .card_stop = hw_card_stop, 21872a36f67fSTakashi Iwai .pll_init = hw_pll_init, 21882a36f67fSTakashi Iwai .is_adc_source_selected = hw_is_adc_input_selected, 21892a36f67fSTakashi Iwai .select_adc_source = hw_adc_input_select, 21902a36f67fSTakashi Iwai .have_digit_io_switch = hw_have_digit_io_switch, 2191*55309216SHarry Butterworth .have_dedicated_mic = hw_have_dedicated_mic, 2192*55309216SHarry Butterworth .have_output_switch = hw_have_output_switch, 2193*55309216SHarry Butterworth .have_mic_source_switch = hw_have_mic_source_switch, 219429959a09SWai Yew CHAY #ifdef CONFIG_PM 219529959a09SWai Yew CHAY .suspend = hw_suspend, 219629959a09SWai Yew CHAY .resume = hw_resume, 219729959a09SWai Yew CHAY #endif 21982a36f67fSTakashi Iwai 21992a36f67fSTakashi Iwai .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, 22002a36f67fSTakashi Iwai .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, 22012a36f67fSTakashi Iwai .src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk, 22022a36f67fSTakashi Iwai .src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk, 22032a36f67fSTakashi Iwai .src_set_state = src_set_state, 22042a36f67fSTakashi Iwai .src_set_bm = src_set_bm, 22052a36f67fSTakashi Iwai .src_set_rsr = src_set_rsr, 22062a36f67fSTakashi Iwai .src_set_sf = src_set_sf, 22072a36f67fSTakashi Iwai .src_set_wr = src_set_wr, 22082a36f67fSTakashi Iwai .src_set_pm = src_set_pm, 22092a36f67fSTakashi Iwai .src_set_rom = src_set_rom, 22102a36f67fSTakashi Iwai .src_set_vo = src_set_vo, 22112a36f67fSTakashi Iwai .src_set_st = src_set_st, 22122a36f67fSTakashi Iwai .src_set_ie = src_set_ie, 22132a36f67fSTakashi Iwai .src_set_ilsz = src_set_ilsz, 22142a36f67fSTakashi Iwai .src_set_bp = src_set_bp, 22152a36f67fSTakashi Iwai .src_set_cisz = src_set_cisz, 22162a36f67fSTakashi Iwai .src_set_ca = src_set_ca, 22172a36f67fSTakashi Iwai .src_set_sa = src_set_sa, 22182a36f67fSTakashi Iwai .src_set_la = src_set_la, 22192a36f67fSTakashi Iwai .src_set_pitch = src_set_pitch, 22202a36f67fSTakashi Iwai .src_set_dirty = src_set_dirty, 22212a36f67fSTakashi Iwai .src_set_clear_zbufs = src_set_clear_zbufs, 22222a36f67fSTakashi Iwai .src_set_dirty_all = src_set_dirty_all, 22232a36f67fSTakashi Iwai .src_commit_write = src_commit_write, 22242a36f67fSTakashi Iwai .src_get_ca = src_get_ca, 22252a36f67fSTakashi Iwai .src_get_dirty = src_get_dirty, 22262a36f67fSTakashi Iwai .src_dirty_conj_mask = src_dirty_conj_mask, 22272a36f67fSTakashi Iwai .src_mgr_enbs_src = src_mgr_enbs_src, 22282a36f67fSTakashi Iwai .src_mgr_enb_src = src_mgr_enb_src, 22292a36f67fSTakashi Iwai .src_mgr_dsb_src = src_mgr_dsb_src, 22302a36f67fSTakashi Iwai .src_mgr_commit_write = src_mgr_commit_write, 22312a36f67fSTakashi Iwai 22322a36f67fSTakashi Iwai .srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk, 22332a36f67fSTakashi Iwai .srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk, 22342a36f67fSTakashi Iwai .srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc, 22352a36f67fSTakashi Iwai .srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser, 22362a36f67fSTakashi Iwai .srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt, 22372a36f67fSTakashi Iwai .srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr, 22382a36f67fSTakashi Iwai .srcimp_mgr_commit_write = srcimp_mgr_commit_write, 22392a36f67fSTakashi Iwai 22402a36f67fSTakashi Iwai .amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk, 22412a36f67fSTakashi Iwai .amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk, 22422a36f67fSTakashi Iwai .amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk, 22432a36f67fSTakashi Iwai .amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk, 22442a36f67fSTakashi Iwai .amixer_set_mode = amixer_set_mode, 22452a36f67fSTakashi Iwai .amixer_set_iv = amixer_set_iv, 22462a36f67fSTakashi Iwai .amixer_set_x = amixer_set_x, 22472a36f67fSTakashi Iwai .amixer_set_y = amixer_set_y, 22482a36f67fSTakashi Iwai .amixer_set_sadr = amixer_set_sadr, 22492a36f67fSTakashi Iwai .amixer_set_se = amixer_set_se, 22502a36f67fSTakashi Iwai .amixer_set_dirty = amixer_set_dirty, 22512a36f67fSTakashi Iwai .amixer_set_dirty_all = amixer_set_dirty_all, 22522a36f67fSTakashi Iwai .amixer_commit_write = amixer_commit_write, 22532a36f67fSTakashi Iwai .amixer_get_y = amixer_get_y, 22542a36f67fSTakashi Iwai .amixer_get_dirty = amixer_get_dirty, 22552a36f67fSTakashi Iwai 22562a36f67fSTakashi Iwai .dai_get_ctrl_blk = dai_get_ctrl_blk, 22572a36f67fSTakashi Iwai .dai_put_ctrl_blk = dai_put_ctrl_blk, 22582a36f67fSTakashi Iwai .dai_srt_set_srco = dai_srt_set_srcr, 22592a36f67fSTakashi Iwai .dai_srt_set_srcm = dai_srt_set_srcl, 22602a36f67fSTakashi Iwai .dai_srt_set_rsr = dai_srt_set_rsr, 22612a36f67fSTakashi Iwai .dai_srt_set_drat = dai_srt_set_drat, 22622a36f67fSTakashi Iwai .dai_srt_set_ec = dai_srt_set_ec, 22632a36f67fSTakashi Iwai .dai_srt_set_et = dai_srt_set_et, 22642a36f67fSTakashi Iwai .dai_commit_write = dai_commit_write, 22652a36f67fSTakashi Iwai 22662a36f67fSTakashi Iwai .dao_get_ctrl_blk = dao_get_ctrl_blk, 22672a36f67fSTakashi Iwai .dao_put_ctrl_blk = dao_put_ctrl_blk, 22682a36f67fSTakashi Iwai .dao_set_spos = dao_set_spos, 22692a36f67fSTakashi Iwai .dao_commit_write = dao_commit_write, 22702a36f67fSTakashi Iwai .dao_get_spos = dao_get_spos, 22712a36f67fSTakashi Iwai 22722a36f67fSTakashi Iwai .daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk, 22732a36f67fSTakashi Iwai .daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk, 22742a36f67fSTakashi Iwai .daio_mgr_enb_dai = daio_mgr_enb_dai, 22752a36f67fSTakashi Iwai .daio_mgr_dsb_dai = daio_mgr_dsb_dai, 22762a36f67fSTakashi Iwai .daio_mgr_enb_dao = daio_mgr_enb_dao, 22772a36f67fSTakashi Iwai .daio_mgr_dsb_dao = daio_mgr_dsb_dao, 22782a36f67fSTakashi Iwai .daio_mgr_dao_init = daio_mgr_dao_init, 22792a36f67fSTakashi Iwai .daio_mgr_set_imaparc = daio_mgr_set_imaparc, 22802a36f67fSTakashi Iwai .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, 22812a36f67fSTakashi Iwai .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, 22822a36f67fSTakashi Iwai .daio_mgr_commit_write = daio_mgr_commit_write, 22832a36f67fSTakashi Iwai 22842a36f67fSTakashi Iwai .set_timer_irq = set_timer_irq, 22852a36f67fSTakashi Iwai .set_timer_tick = set_timer_tick, 228654de6bc8STakashi Iwai .get_wc = get_wc, 22872a36f67fSTakashi Iwai }; 22882a36f67fSTakashi Iwai 22892a36f67fSTakashi Iwai int __devinit create_20k1_hw_obj(struct hw **rhw) 22908cc72361SWai Yew CHAY { 22918cc72361SWai Yew CHAY struct hw20k1 *hw20k1; 22928cc72361SWai Yew CHAY 22938cc72361SWai Yew CHAY *rhw = NULL; 22948cc72361SWai Yew CHAY hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL); 229535ebf6e7STakashi Iwai if (!hw20k1) 22968cc72361SWai Yew CHAY return -ENOMEM; 22978cc72361SWai Yew CHAY 22988cc72361SWai Yew CHAY spin_lock_init(&hw20k1->reg_20k1_lock); 22998cc72361SWai Yew CHAY spin_lock_init(&hw20k1->reg_pci_lock); 23008cc72361SWai Yew CHAY 23012a36f67fSTakashi Iwai hw20k1->hw = ct20k1_preset; 23028cc72361SWai Yew CHAY 23032a36f67fSTakashi Iwai *rhw = &hw20k1->hw; 23048cc72361SWai Yew CHAY 23058cc72361SWai Yew CHAY return 0; 23068cc72361SWai Yew CHAY } 23078cc72361SWai Yew CHAY 23088cc72361SWai Yew CHAY int destroy_20k1_hw_obj(struct hw *hw) 23098cc72361SWai Yew CHAY { 23108cc72361SWai Yew CHAY if (hw->io_base) 23118cc72361SWai Yew CHAY hw_card_shutdown(hw); 23128cc72361SWai Yew CHAY 23138cc72361SWai Yew CHAY kfree(container_of(hw, struct hw20k1, hw)); 23148cc72361SWai Yew CHAY return 0; 23158cc72361SWai Yew CHAY } 2316