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 308cc72361SWai Yew CHAY struct hw20k1 { 318cc72361SWai Yew CHAY struct hw hw; 328cc72361SWai Yew CHAY spinlock_t reg_20k1_lock; 338cc72361SWai Yew CHAY spinlock_t reg_pci_lock; 348cc72361SWai Yew CHAY }; 358cc72361SWai Yew CHAY 368cc72361SWai Yew CHAY static u32 hw_read_20kx(struct hw *hw, u32 reg); 378cc72361SWai Yew CHAY static void hw_write_20kx(struct hw *hw, u32 reg, u32 data); 388cc72361SWai Yew CHAY static u32 hw_read_pci(struct hw *hw, u32 reg); 398cc72361SWai Yew CHAY static void hw_write_pci(struct hw *hw, u32 reg, u32 data); 408cc72361SWai Yew CHAY 418cc72361SWai Yew CHAY /* 428cc72361SWai Yew CHAY * Type definition block. 438cc72361SWai Yew CHAY * The layout of control structures can be directly applied on 20k2 chip. 448cc72361SWai Yew CHAY */ 458cc72361SWai Yew CHAY 468cc72361SWai Yew CHAY /* 478cc72361SWai Yew CHAY * SRC control block definitions. 488cc72361SWai Yew CHAY */ 498cc72361SWai Yew CHAY 508cc72361SWai Yew CHAY /* SRC resource control block */ 518cc72361SWai Yew CHAY #define SRCCTL_STATE 0x00000007 528cc72361SWai Yew CHAY #define SRCCTL_BM 0x00000008 538cc72361SWai Yew CHAY #define SRCCTL_RSR 0x00000030 548cc72361SWai Yew CHAY #define SRCCTL_SF 0x000001C0 558cc72361SWai Yew CHAY #define SRCCTL_WR 0x00000200 568cc72361SWai Yew CHAY #define SRCCTL_PM 0x00000400 578cc72361SWai Yew CHAY #define SRCCTL_ROM 0x00001800 588cc72361SWai Yew CHAY #define SRCCTL_VO 0x00002000 598cc72361SWai Yew CHAY #define SRCCTL_ST 0x00004000 608cc72361SWai Yew CHAY #define SRCCTL_IE 0x00008000 618cc72361SWai Yew CHAY #define SRCCTL_ILSZ 0x000F0000 628cc72361SWai Yew CHAY #define SRCCTL_BP 0x00100000 638cc72361SWai Yew CHAY 648cc72361SWai Yew CHAY #define SRCCCR_CISZ 0x000007FF 658cc72361SWai Yew CHAY #define SRCCCR_CWA 0x001FF800 668cc72361SWai Yew CHAY #define SRCCCR_D 0x00200000 678cc72361SWai Yew CHAY #define SRCCCR_RS 0x01C00000 688cc72361SWai Yew CHAY #define SRCCCR_NAL 0x3E000000 698cc72361SWai Yew CHAY #define SRCCCR_RA 0xC0000000 708cc72361SWai Yew CHAY 718cc72361SWai Yew CHAY #define SRCCA_CA 0x03FFFFFF 728cc72361SWai Yew CHAY #define SRCCA_RS 0x1C000000 738cc72361SWai Yew CHAY #define SRCCA_NAL 0xE0000000 748cc72361SWai Yew CHAY 758cc72361SWai Yew CHAY #define SRCSA_SA 0x03FFFFFF 768cc72361SWai Yew CHAY 778cc72361SWai Yew CHAY #define SRCLA_LA 0x03FFFFFF 788cc72361SWai Yew CHAY 798cc72361SWai Yew CHAY /* Mixer Parameter Ring ram Low and Hight register. 808cc72361SWai Yew CHAY * Fixed-point value in 8.24 format for parameter channel */ 818cc72361SWai Yew CHAY #define MPRLH_PITCH 0xFFFFFFFF 828cc72361SWai Yew CHAY 838cc72361SWai Yew CHAY /* SRC resource register dirty flags */ 848cc72361SWai Yew CHAY union src_dirty { 858cc72361SWai Yew CHAY struct { 868cc72361SWai Yew CHAY u16 ctl:1; 878cc72361SWai Yew CHAY u16 ccr:1; 888cc72361SWai Yew CHAY u16 sa:1; 898cc72361SWai Yew CHAY u16 la:1; 908cc72361SWai Yew CHAY u16 ca:1; 918cc72361SWai Yew CHAY u16 mpr:1; 928cc72361SWai Yew CHAY u16 czbfs:1; /* Clear Z-Buffers */ 938cc72361SWai Yew CHAY u16 rsv:9; 948cc72361SWai Yew CHAY } bf; 958cc72361SWai Yew CHAY u16 data; 968cc72361SWai Yew CHAY }; 978cc72361SWai Yew CHAY 988cc72361SWai Yew CHAY struct src_rsc_ctrl_blk { 998cc72361SWai Yew CHAY unsigned int ctl; 1008cc72361SWai Yew CHAY unsigned int ccr; 1018cc72361SWai Yew CHAY unsigned int ca; 1028cc72361SWai Yew CHAY unsigned int sa; 1038cc72361SWai Yew CHAY unsigned int la; 1048cc72361SWai Yew CHAY unsigned int mpr; 1058cc72361SWai Yew CHAY union src_dirty dirty; 1068cc72361SWai Yew CHAY }; 1078cc72361SWai Yew CHAY 1088cc72361SWai Yew CHAY /* SRC manager control block */ 1098cc72361SWai Yew CHAY union src_mgr_dirty { 1108cc72361SWai Yew CHAY struct { 1118cc72361SWai Yew CHAY u16 enb0:1; 1128cc72361SWai Yew CHAY u16 enb1:1; 1138cc72361SWai Yew CHAY u16 enb2:1; 1148cc72361SWai Yew CHAY u16 enb3:1; 1158cc72361SWai Yew CHAY u16 enb4:1; 1168cc72361SWai Yew CHAY u16 enb5:1; 1178cc72361SWai Yew CHAY u16 enb6:1; 1188cc72361SWai Yew CHAY u16 enb7:1; 1198cc72361SWai Yew CHAY u16 enbsa:1; 1208cc72361SWai Yew CHAY u16 rsv:7; 1218cc72361SWai Yew CHAY } bf; 1228cc72361SWai Yew CHAY u16 data; 1238cc72361SWai Yew CHAY }; 1248cc72361SWai Yew CHAY 1258cc72361SWai Yew CHAY struct src_mgr_ctrl_blk { 1268cc72361SWai Yew CHAY unsigned int enbsa; 1278cc72361SWai Yew CHAY unsigned int enb[8]; 1288cc72361SWai Yew CHAY union src_mgr_dirty dirty; 1298cc72361SWai Yew CHAY }; 1308cc72361SWai Yew CHAY 1318cc72361SWai Yew CHAY /* SRCIMP manager control block */ 1328cc72361SWai Yew CHAY #define SRCAIM_ARC 0x00000FFF 1338cc72361SWai Yew CHAY #define SRCAIM_NXT 0x00FF0000 1348cc72361SWai Yew CHAY #define SRCAIM_SRC 0xFF000000 1358cc72361SWai Yew CHAY 1368cc72361SWai Yew CHAY struct srcimap { 1378cc72361SWai Yew CHAY unsigned int srcaim; 1388cc72361SWai Yew CHAY unsigned int idx; 1398cc72361SWai Yew CHAY }; 1408cc72361SWai Yew CHAY 1418cc72361SWai Yew CHAY /* SRCIMP manager register dirty flags */ 1428cc72361SWai Yew CHAY union srcimp_mgr_dirty { 1438cc72361SWai Yew CHAY struct { 1448cc72361SWai Yew CHAY u16 srcimap:1; 1458cc72361SWai Yew CHAY u16 rsv:15; 1468cc72361SWai Yew CHAY } bf; 1478cc72361SWai Yew CHAY u16 data; 1488cc72361SWai Yew CHAY }; 1498cc72361SWai Yew CHAY 1508cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk { 1518cc72361SWai Yew CHAY struct srcimap srcimap; 1528cc72361SWai Yew CHAY union srcimp_mgr_dirty dirty; 1538cc72361SWai Yew CHAY }; 1548cc72361SWai Yew CHAY 1558cc72361SWai Yew CHAY /* 1568cc72361SWai Yew CHAY * Function implementation block. 1578cc72361SWai Yew CHAY */ 1588cc72361SWai Yew CHAY 1598cc72361SWai Yew CHAY static int src_get_rsc_ctrl_blk(void **rblk) 1608cc72361SWai Yew CHAY { 1618cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *blk; 1628cc72361SWai Yew CHAY 1638cc72361SWai Yew CHAY *rblk = NULL; 1648cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 16535ebf6e7STakashi Iwai if (!blk) 1668cc72361SWai Yew CHAY return -ENOMEM; 1678cc72361SWai Yew CHAY 1688cc72361SWai Yew CHAY *rblk = blk; 1698cc72361SWai Yew CHAY 1708cc72361SWai Yew CHAY return 0; 1718cc72361SWai Yew CHAY } 1728cc72361SWai Yew CHAY 1738cc72361SWai Yew CHAY static int src_put_rsc_ctrl_blk(void *blk) 1748cc72361SWai Yew CHAY { 1758cc72361SWai Yew CHAY kfree((struct src_rsc_ctrl_blk *)blk); 1768cc72361SWai Yew CHAY 1778cc72361SWai Yew CHAY return 0; 1788cc72361SWai Yew CHAY } 1798cc72361SWai Yew CHAY 1808cc72361SWai Yew CHAY static int src_set_state(void *blk, unsigned int state) 1818cc72361SWai Yew CHAY { 1828cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 1838cc72361SWai Yew CHAY 1848cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_STATE, state); 1858cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 1868cc72361SWai Yew CHAY return 0; 1878cc72361SWai Yew CHAY } 1888cc72361SWai Yew CHAY 1898cc72361SWai Yew CHAY static int src_set_bm(void *blk, unsigned int bm) 1908cc72361SWai Yew CHAY { 1918cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 1928cc72361SWai Yew CHAY 1938cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_BM, bm); 1948cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 1958cc72361SWai Yew CHAY return 0; 1968cc72361SWai Yew CHAY } 1978cc72361SWai Yew CHAY 1988cc72361SWai Yew CHAY static int src_set_rsr(void *blk, unsigned int rsr) 1998cc72361SWai Yew CHAY { 2008cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2018cc72361SWai Yew CHAY 2028cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_RSR, rsr); 2038cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2048cc72361SWai Yew CHAY return 0; 2058cc72361SWai Yew CHAY } 2068cc72361SWai Yew CHAY 2078cc72361SWai Yew CHAY static int src_set_sf(void *blk, unsigned int sf) 2088cc72361SWai Yew CHAY { 2098cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2108cc72361SWai Yew CHAY 2118cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_SF, sf); 2128cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2138cc72361SWai Yew CHAY return 0; 2148cc72361SWai Yew CHAY } 2158cc72361SWai Yew CHAY 2168cc72361SWai Yew CHAY static int src_set_wr(void *blk, unsigned int wr) 2178cc72361SWai Yew CHAY { 2188cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2198cc72361SWai Yew CHAY 2208cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_WR, wr); 2218cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2228cc72361SWai Yew CHAY return 0; 2238cc72361SWai Yew CHAY } 2248cc72361SWai Yew CHAY 2258cc72361SWai Yew CHAY static int src_set_pm(void *blk, unsigned int pm) 2268cc72361SWai Yew CHAY { 2278cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2288cc72361SWai Yew CHAY 2298cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_PM, pm); 2308cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2318cc72361SWai Yew CHAY return 0; 2328cc72361SWai Yew CHAY } 2338cc72361SWai Yew CHAY 2348cc72361SWai Yew CHAY static int src_set_rom(void *blk, unsigned int rom) 2358cc72361SWai Yew CHAY { 2368cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2378cc72361SWai Yew CHAY 2388cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ROM, rom); 2398cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2408cc72361SWai Yew CHAY return 0; 2418cc72361SWai Yew CHAY } 2428cc72361SWai Yew CHAY 2438cc72361SWai Yew CHAY static int src_set_vo(void *blk, unsigned int vo) 2448cc72361SWai Yew CHAY { 2458cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2468cc72361SWai Yew CHAY 2478cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_VO, vo); 2488cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2498cc72361SWai Yew CHAY return 0; 2508cc72361SWai Yew CHAY } 2518cc72361SWai Yew CHAY 2528cc72361SWai Yew CHAY static int src_set_st(void *blk, unsigned int st) 2538cc72361SWai Yew CHAY { 2548cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2558cc72361SWai Yew CHAY 2568cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ST, st); 2578cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2588cc72361SWai Yew CHAY return 0; 2598cc72361SWai Yew CHAY } 2608cc72361SWai Yew CHAY 2618cc72361SWai Yew CHAY static int src_set_ie(void *blk, unsigned int ie) 2628cc72361SWai Yew CHAY { 2638cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2648cc72361SWai Yew CHAY 2658cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_IE, ie); 2668cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2678cc72361SWai Yew CHAY return 0; 2688cc72361SWai Yew CHAY } 2698cc72361SWai Yew CHAY 2708cc72361SWai Yew CHAY static int src_set_ilsz(void *blk, unsigned int ilsz) 2718cc72361SWai Yew CHAY { 2728cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2738cc72361SWai Yew CHAY 2748cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz); 2758cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2768cc72361SWai Yew CHAY return 0; 2778cc72361SWai Yew CHAY } 2788cc72361SWai Yew CHAY 2798cc72361SWai Yew CHAY static int src_set_bp(void *blk, unsigned int bp) 2808cc72361SWai Yew CHAY { 2818cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2828cc72361SWai Yew CHAY 2838cc72361SWai Yew CHAY set_field(&ctl->ctl, SRCCTL_BP, bp); 2848cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 1; 2858cc72361SWai Yew CHAY return 0; 2868cc72361SWai Yew CHAY } 2878cc72361SWai Yew CHAY 2888cc72361SWai Yew CHAY static int src_set_cisz(void *blk, unsigned int cisz) 2898cc72361SWai Yew CHAY { 2908cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 2918cc72361SWai Yew CHAY 2928cc72361SWai Yew CHAY set_field(&ctl->ccr, SRCCCR_CISZ, cisz); 2938cc72361SWai Yew CHAY ctl->dirty.bf.ccr = 1; 2948cc72361SWai Yew CHAY return 0; 2958cc72361SWai Yew CHAY } 2968cc72361SWai Yew CHAY 2978cc72361SWai Yew CHAY static int src_set_ca(void *blk, unsigned int ca) 2988cc72361SWai Yew CHAY { 2998cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3008cc72361SWai Yew CHAY 3018cc72361SWai Yew CHAY set_field(&ctl->ca, SRCCA_CA, ca); 3028cc72361SWai Yew CHAY ctl->dirty.bf.ca = 1; 3038cc72361SWai Yew CHAY return 0; 3048cc72361SWai Yew CHAY } 3058cc72361SWai Yew CHAY 3068cc72361SWai Yew CHAY static int src_set_sa(void *blk, unsigned int sa) 3078cc72361SWai Yew CHAY { 3088cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3098cc72361SWai Yew CHAY 3108cc72361SWai Yew CHAY set_field(&ctl->sa, SRCSA_SA, sa); 3118cc72361SWai Yew CHAY ctl->dirty.bf.sa = 1; 3128cc72361SWai Yew CHAY return 0; 3138cc72361SWai Yew CHAY } 3148cc72361SWai Yew CHAY 3158cc72361SWai Yew CHAY static int src_set_la(void *blk, unsigned int la) 3168cc72361SWai Yew CHAY { 3178cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3188cc72361SWai Yew CHAY 3198cc72361SWai Yew CHAY set_field(&ctl->la, SRCLA_LA, la); 3208cc72361SWai Yew CHAY ctl->dirty.bf.la = 1; 3218cc72361SWai Yew CHAY return 0; 3228cc72361SWai Yew CHAY } 3238cc72361SWai Yew CHAY 3248cc72361SWai Yew CHAY static int src_set_pitch(void *blk, unsigned int pitch) 3258cc72361SWai Yew CHAY { 3268cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 3278cc72361SWai Yew CHAY 3288cc72361SWai Yew CHAY set_field(&ctl->mpr, MPRLH_PITCH, pitch); 3298cc72361SWai Yew CHAY ctl->dirty.bf.mpr = 1; 3308cc72361SWai Yew CHAY return 0; 3318cc72361SWai Yew CHAY } 3328cc72361SWai Yew CHAY 3338cc72361SWai Yew CHAY static int src_set_clear_zbufs(void *blk, unsigned int clear) 3348cc72361SWai Yew CHAY { 3358cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0); 3368cc72361SWai Yew CHAY return 0; 3378cc72361SWai Yew CHAY } 3388cc72361SWai Yew CHAY 3398cc72361SWai Yew CHAY static int src_set_dirty(void *blk, unsigned int flags) 3408cc72361SWai Yew CHAY { 3418cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 3428cc72361SWai Yew CHAY return 0; 3438cc72361SWai Yew CHAY } 3448cc72361SWai Yew CHAY 3458cc72361SWai Yew CHAY static int src_set_dirty_all(void *blk) 3468cc72361SWai Yew CHAY { 3478cc72361SWai Yew CHAY ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 3488cc72361SWai Yew CHAY return 0; 3498cc72361SWai Yew CHAY } 3508cc72361SWai Yew CHAY 3518cc72361SWai Yew CHAY #define AR_SLOT_SIZE 4096 3528cc72361SWai Yew CHAY #define AR_SLOT_BLOCK_SIZE 16 3538cc72361SWai Yew CHAY #define AR_PTS_PITCH 6 3548cc72361SWai Yew CHAY #define AR_PARAM_SRC_OFFSET 0x60 3558cc72361SWai Yew CHAY 3568cc72361SWai Yew CHAY static unsigned int src_param_pitch_mixer(unsigned int src_idx) 3578cc72361SWai Yew CHAY { 3588cc72361SWai Yew CHAY return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE 3598cc72361SWai Yew CHAY - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE; 3608cc72361SWai Yew CHAY 3618cc72361SWai Yew CHAY } 3628cc72361SWai Yew CHAY 3638cc72361SWai Yew CHAY static int src_commit_write(struct hw *hw, unsigned int idx, void *blk) 3648cc72361SWai Yew CHAY { 3658cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 366514eef9cSTakashi Iwai int i; 3678cc72361SWai Yew CHAY 3688cc72361SWai Yew CHAY if (ctl->dirty.bf.czbfs) { 3698cc72361SWai Yew CHAY /* Clear Z-Buffer registers */ 3708cc72361SWai Yew CHAY for (i = 0; i < 8; i++) 3718cc72361SWai Yew CHAY hw_write_20kx(hw, SRCUPZ+idx*0x100+i*0x4, 0); 3728cc72361SWai Yew CHAY 3738cc72361SWai Yew CHAY for (i = 0; i < 4; i++) 3748cc72361SWai Yew CHAY hw_write_20kx(hw, SRCDN0Z+idx*0x100+i*0x4, 0); 3758cc72361SWai Yew CHAY 3768cc72361SWai Yew CHAY for (i = 0; i < 8; i++) 3778cc72361SWai Yew CHAY hw_write_20kx(hw, SRCDN1Z+idx*0x100+i*0x4, 0); 3788cc72361SWai Yew CHAY 3798cc72361SWai Yew CHAY ctl->dirty.bf.czbfs = 0; 3808cc72361SWai Yew CHAY } 3818cc72361SWai Yew CHAY if (ctl->dirty.bf.mpr) { 3828cc72361SWai Yew CHAY /* Take the parameter mixer resource in the same group as that 3838cc72361SWai Yew CHAY * the idx src is in for simplicity. Unlike src, all conjugate 3848cc72361SWai Yew CHAY * parameter mixer resources must be programmed for 3858cc72361SWai Yew CHAY * corresponding conjugate src resources. */ 3868cc72361SWai Yew CHAY unsigned int pm_idx = src_param_pitch_mixer(idx); 3878cc72361SWai Yew CHAY hw_write_20kx(hw, PRING_LO_HI+4*pm_idx, ctl->mpr); 3888cc72361SWai Yew CHAY hw_write_20kx(hw, PMOPLO+8*pm_idx, 0x3); 3898cc72361SWai Yew CHAY hw_write_20kx(hw, PMOPHI+8*pm_idx, 0x0); 3908cc72361SWai Yew CHAY ctl->dirty.bf.mpr = 0; 3918cc72361SWai Yew CHAY } 3928cc72361SWai Yew CHAY if (ctl->dirty.bf.sa) { 3938cc72361SWai Yew CHAY hw_write_20kx(hw, SRCSA+idx*0x100, ctl->sa); 3948cc72361SWai Yew CHAY ctl->dirty.bf.sa = 0; 3958cc72361SWai Yew CHAY } 3968cc72361SWai Yew CHAY if (ctl->dirty.bf.la) { 3978cc72361SWai Yew CHAY hw_write_20kx(hw, SRCLA+idx*0x100, ctl->la); 3988cc72361SWai Yew CHAY ctl->dirty.bf.la = 0; 3998cc72361SWai Yew CHAY } 4008cc72361SWai Yew CHAY if (ctl->dirty.bf.ca) { 4018cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCA+idx*0x100, ctl->ca); 4028cc72361SWai Yew CHAY ctl->dirty.bf.ca = 0; 4038cc72361SWai Yew CHAY } 4048cc72361SWai Yew CHAY 4058cc72361SWai Yew CHAY /* Write srccf register */ 4068cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCF+idx*0x100, 0x0); 4078cc72361SWai Yew CHAY 4088cc72361SWai Yew CHAY if (ctl->dirty.bf.ccr) { 4098cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCCR+idx*0x100, ctl->ccr); 4108cc72361SWai Yew CHAY ctl->dirty.bf.ccr = 0; 4118cc72361SWai Yew CHAY } 4128cc72361SWai Yew CHAY if (ctl->dirty.bf.ctl) { 4138cc72361SWai Yew CHAY hw_write_20kx(hw, SRCCTL+idx*0x100, ctl->ctl); 4148cc72361SWai Yew CHAY ctl->dirty.bf.ctl = 0; 4158cc72361SWai Yew CHAY } 4168cc72361SWai Yew CHAY 4178cc72361SWai Yew CHAY return 0; 4188cc72361SWai Yew CHAY } 4198cc72361SWai Yew CHAY 4208cc72361SWai Yew CHAY static int src_get_ca(struct hw *hw, unsigned int idx, void *blk) 4218cc72361SWai Yew CHAY { 4228cc72361SWai Yew CHAY struct src_rsc_ctrl_blk *ctl = blk; 4238cc72361SWai Yew CHAY 4248cc72361SWai Yew CHAY ctl->ca = hw_read_20kx(hw, SRCCA+idx*0x100); 4258cc72361SWai Yew CHAY ctl->dirty.bf.ca = 0; 4268cc72361SWai Yew CHAY 4278cc72361SWai Yew CHAY return get_field(ctl->ca, SRCCA_CA); 4288cc72361SWai Yew CHAY } 4298cc72361SWai Yew CHAY 4308cc72361SWai Yew CHAY static unsigned int src_get_dirty(void *blk) 4318cc72361SWai Yew CHAY { 4328cc72361SWai Yew CHAY return ((struct src_rsc_ctrl_blk *)blk)->dirty.data; 4338cc72361SWai Yew CHAY } 4348cc72361SWai Yew CHAY 4358cc72361SWai Yew CHAY static unsigned int src_dirty_conj_mask(void) 4368cc72361SWai Yew CHAY { 4378cc72361SWai Yew CHAY return 0x20; 4388cc72361SWai Yew CHAY } 4398cc72361SWai Yew CHAY 4408cc72361SWai Yew CHAY static int src_mgr_enbs_src(void *blk, unsigned int idx) 4418cc72361SWai Yew CHAY { 4428cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enbsa = ~(0x0); 4438cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1; 4448cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 4458cc72361SWai Yew CHAY return 0; 4468cc72361SWai Yew CHAY } 4478cc72361SWai Yew CHAY 4488cc72361SWai Yew CHAY static int src_mgr_enb_src(void *blk, unsigned int idx) 4498cc72361SWai Yew CHAY { 4508cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 4518cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 4528cc72361SWai Yew CHAY return 0; 4538cc72361SWai Yew CHAY } 4548cc72361SWai Yew CHAY 4558cc72361SWai Yew CHAY static int src_mgr_dsb_src(void *blk, unsigned int idx) 4568cc72361SWai Yew CHAY { 4578cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32)); 4588cc72361SWai Yew CHAY ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 4598cc72361SWai Yew CHAY return 0; 4608cc72361SWai Yew CHAY } 4618cc72361SWai Yew CHAY 4628cc72361SWai Yew CHAY static int src_mgr_commit_write(struct hw *hw, void *blk) 4638cc72361SWai Yew CHAY { 4648cc72361SWai Yew CHAY struct src_mgr_ctrl_blk *ctl = blk; 465514eef9cSTakashi Iwai int i; 466514eef9cSTakashi Iwai unsigned int ret; 4678cc72361SWai Yew CHAY 4688cc72361SWai Yew CHAY if (ctl->dirty.bf.enbsa) { 4698cc72361SWai Yew CHAY do { 4708cc72361SWai Yew CHAY ret = hw_read_20kx(hw, SRCENBSTAT); 4718cc72361SWai Yew CHAY } while (ret & 0x1); 4728cc72361SWai Yew CHAY hw_write_20kx(hw, SRCENBS, ctl->enbsa); 4738cc72361SWai Yew CHAY ctl->dirty.bf.enbsa = 0; 4748cc72361SWai Yew CHAY } 4758cc72361SWai Yew CHAY for (i = 0; i < 8; i++) { 4768cc72361SWai Yew CHAY if ((ctl->dirty.data & (0x1 << i))) { 4778cc72361SWai Yew CHAY hw_write_20kx(hw, SRCENB+(i*0x100), ctl->enb[i]); 4788cc72361SWai Yew CHAY ctl->dirty.data &= ~(0x1 << i); 4798cc72361SWai Yew CHAY } 4808cc72361SWai Yew CHAY } 4818cc72361SWai Yew CHAY 4828cc72361SWai Yew CHAY return 0; 4838cc72361SWai Yew CHAY } 4848cc72361SWai Yew CHAY 4858cc72361SWai Yew CHAY static int src_mgr_get_ctrl_blk(void **rblk) 4868cc72361SWai Yew CHAY { 4878cc72361SWai Yew CHAY struct src_mgr_ctrl_blk *blk; 4888cc72361SWai Yew CHAY 4898cc72361SWai Yew CHAY *rblk = NULL; 4908cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 49135ebf6e7STakashi Iwai if (!blk) 4928cc72361SWai Yew CHAY return -ENOMEM; 4938cc72361SWai Yew CHAY 4948cc72361SWai Yew CHAY *rblk = blk; 4958cc72361SWai Yew CHAY 4968cc72361SWai Yew CHAY return 0; 4978cc72361SWai Yew CHAY } 4988cc72361SWai Yew CHAY 4998cc72361SWai Yew CHAY static int src_mgr_put_ctrl_blk(void *blk) 5008cc72361SWai Yew CHAY { 5018cc72361SWai Yew CHAY kfree((struct src_mgr_ctrl_blk *)blk); 5028cc72361SWai Yew CHAY 5038cc72361SWai Yew CHAY return 0; 5048cc72361SWai Yew CHAY } 5058cc72361SWai Yew CHAY 5068cc72361SWai Yew CHAY static int srcimp_mgr_get_ctrl_blk(void **rblk) 5078cc72361SWai Yew CHAY { 5088cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *blk; 5098cc72361SWai Yew CHAY 5108cc72361SWai Yew CHAY *rblk = NULL; 5118cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 51235ebf6e7STakashi Iwai if (!blk) 5138cc72361SWai Yew CHAY return -ENOMEM; 5148cc72361SWai Yew CHAY 5158cc72361SWai Yew CHAY *rblk = blk; 5168cc72361SWai Yew CHAY 5178cc72361SWai Yew CHAY return 0; 5188cc72361SWai Yew CHAY } 5198cc72361SWai Yew CHAY 5208cc72361SWai Yew CHAY static int srcimp_mgr_put_ctrl_blk(void *blk) 5218cc72361SWai Yew CHAY { 5228cc72361SWai Yew CHAY kfree((struct srcimp_mgr_ctrl_blk *)blk); 5238cc72361SWai Yew CHAY 5248cc72361SWai Yew CHAY return 0; 5258cc72361SWai Yew CHAY } 5268cc72361SWai Yew CHAY 5278cc72361SWai Yew CHAY static int srcimp_mgr_set_imaparc(void *blk, unsigned int slot) 5288cc72361SWai Yew CHAY { 5298cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5308cc72361SWai Yew CHAY 5318cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot); 5328cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5338cc72361SWai Yew CHAY return 0; 5348cc72361SWai Yew CHAY } 5358cc72361SWai Yew CHAY 5368cc72361SWai Yew CHAY static int srcimp_mgr_set_imapuser(void *blk, unsigned int user) 5378cc72361SWai Yew CHAY { 5388cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5398cc72361SWai Yew CHAY 5408cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user); 5418cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5428cc72361SWai Yew CHAY return 0; 5438cc72361SWai Yew CHAY } 5448cc72361SWai Yew CHAY 5458cc72361SWai Yew CHAY static int srcimp_mgr_set_imapnxt(void *blk, unsigned int next) 5468cc72361SWai Yew CHAY { 5478cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5488cc72361SWai Yew CHAY 5498cc72361SWai Yew CHAY set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next); 5508cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5518cc72361SWai Yew CHAY return 0; 5528cc72361SWai Yew CHAY } 5538cc72361SWai Yew CHAY 5548cc72361SWai Yew CHAY static int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr) 5558cc72361SWai Yew CHAY { 5568cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5578cc72361SWai Yew CHAY 5588cc72361SWai Yew CHAY ctl->srcimap.idx = addr; 5598cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 1; 5608cc72361SWai Yew CHAY return 0; 5618cc72361SWai Yew CHAY } 5628cc72361SWai Yew CHAY 5638cc72361SWai Yew CHAY static int srcimp_mgr_commit_write(struct hw *hw, void *blk) 5648cc72361SWai Yew CHAY { 5658cc72361SWai Yew CHAY struct srcimp_mgr_ctrl_blk *ctl = blk; 5668cc72361SWai Yew CHAY 5678cc72361SWai Yew CHAY if (ctl->dirty.bf.srcimap) { 5688cc72361SWai Yew CHAY hw_write_20kx(hw, SRCIMAP+ctl->srcimap.idx*0x100, 5698cc72361SWai Yew CHAY ctl->srcimap.srcaim); 5708cc72361SWai Yew CHAY ctl->dirty.bf.srcimap = 0; 5718cc72361SWai Yew CHAY } 5728cc72361SWai Yew CHAY 5738cc72361SWai Yew CHAY return 0; 5748cc72361SWai Yew CHAY } 5758cc72361SWai Yew CHAY 5768cc72361SWai Yew CHAY /* 5778cc72361SWai Yew CHAY * AMIXER control block definitions. 5788cc72361SWai Yew CHAY */ 5798cc72361SWai Yew CHAY 5808cc72361SWai Yew CHAY #define AMOPLO_M 0x00000003 5818cc72361SWai Yew CHAY #define AMOPLO_X 0x0003FFF0 5828cc72361SWai Yew CHAY #define AMOPLO_Y 0xFFFC0000 5838cc72361SWai Yew CHAY 5848cc72361SWai Yew CHAY #define AMOPHI_SADR 0x000000FF 5858cc72361SWai Yew CHAY #define AMOPHI_SE 0x80000000 5868cc72361SWai Yew CHAY 5878cc72361SWai Yew CHAY /* AMIXER resource register dirty flags */ 5888cc72361SWai Yew CHAY union amixer_dirty { 5898cc72361SWai Yew CHAY struct { 5908cc72361SWai Yew CHAY u16 amoplo:1; 5918cc72361SWai Yew CHAY u16 amophi:1; 5928cc72361SWai Yew CHAY u16 rsv:14; 5938cc72361SWai Yew CHAY } bf; 5948cc72361SWai Yew CHAY u16 data; 5958cc72361SWai Yew CHAY }; 5968cc72361SWai Yew CHAY 5978cc72361SWai Yew CHAY /* AMIXER resource control block */ 5988cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk { 5998cc72361SWai Yew CHAY unsigned int amoplo; 6008cc72361SWai Yew CHAY unsigned int amophi; 6018cc72361SWai Yew CHAY union amixer_dirty dirty; 6028cc72361SWai Yew CHAY }; 6038cc72361SWai Yew CHAY 6048cc72361SWai Yew CHAY static int amixer_set_mode(void *blk, unsigned int mode) 6058cc72361SWai Yew CHAY { 6068cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6078cc72361SWai Yew CHAY 6088cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_M, mode); 6098cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 6108cc72361SWai Yew CHAY return 0; 6118cc72361SWai Yew CHAY } 6128cc72361SWai Yew CHAY 6138cc72361SWai Yew CHAY static int amixer_set_iv(void *blk, unsigned int iv) 6148cc72361SWai Yew CHAY { 6158cc72361SWai Yew CHAY /* 20k1 amixer does not have this field */ 6168cc72361SWai Yew CHAY return 0; 6178cc72361SWai Yew CHAY } 6188cc72361SWai Yew CHAY 6198cc72361SWai Yew CHAY static int amixer_set_x(void *blk, unsigned int x) 6208cc72361SWai Yew CHAY { 6218cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6228cc72361SWai Yew CHAY 6238cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_X, x); 6248cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 6258cc72361SWai Yew CHAY return 0; 6268cc72361SWai Yew CHAY } 6278cc72361SWai Yew CHAY 6288cc72361SWai Yew CHAY static int amixer_set_y(void *blk, unsigned int y) 6298cc72361SWai Yew CHAY { 6308cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6318cc72361SWai Yew CHAY 6328cc72361SWai Yew CHAY set_field(&ctl->amoplo, AMOPLO_Y, y); 6338cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 1; 6348cc72361SWai Yew CHAY return 0; 6358cc72361SWai Yew CHAY } 6368cc72361SWai Yew CHAY 6378cc72361SWai Yew CHAY static int amixer_set_sadr(void *blk, unsigned int sadr) 6388cc72361SWai Yew CHAY { 6398cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6408cc72361SWai Yew CHAY 6418cc72361SWai Yew CHAY set_field(&ctl->amophi, AMOPHI_SADR, sadr); 6428cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 1; 6438cc72361SWai Yew CHAY return 0; 6448cc72361SWai Yew CHAY } 6458cc72361SWai Yew CHAY 6468cc72361SWai Yew CHAY static int amixer_set_se(void *blk, unsigned int se) 6478cc72361SWai Yew CHAY { 6488cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6498cc72361SWai Yew CHAY 6508cc72361SWai Yew CHAY set_field(&ctl->amophi, AMOPHI_SE, se); 6518cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 1; 6528cc72361SWai Yew CHAY return 0; 6538cc72361SWai Yew CHAY } 6548cc72361SWai Yew CHAY 6558cc72361SWai Yew CHAY static int amixer_set_dirty(void *blk, unsigned int flags) 6568cc72361SWai Yew CHAY { 6578cc72361SWai Yew CHAY ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 6588cc72361SWai Yew CHAY return 0; 6598cc72361SWai Yew CHAY } 6608cc72361SWai Yew CHAY 6618cc72361SWai Yew CHAY static int amixer_set_dirty_all(void *blk) 6628cc72361SWai Yew CHAY { 6638cc72361SWai Yew CHAY ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 6648cc72361SWai Yew CHAY return 0; 6658cc72361SWai Yew CHAY } 6668cc72361SWai Yew CHAY 6678cc72361SWai Yew CHAY static int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) 6688cc72361SWai Yew CHAY { 6698cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6708cc72361SWai Yew CHAY 6718cc72361SWai Yew CHAY if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { 6728cc72361SWai Yew CHAY hw_write_20kx(hw, AMOPLO+idx*8, ctl->amoplo); 6738cc72361SWai Yew CHAY ctl->dirty.bf.amoplo = 0; 6748cc72361SWai Yew CHAY hw_write_20kx(hw, AMOPHI+idx*8, ctl->amophi); 6758cc72361SWai Yew CHAY ctl->dirty.bf.amophi = 0; 6768cc72361SWai Yew CHAY } 6778cc72361SWai Yew CHAY 6788cc72361SWai Yew CHAY return 0; 6798cc72361SWai Yew CHAY } 6808cc72361SWai Yew CHAY 6818cc72361SWai Yew CHAY static int amixer_get_y(void *blk) 6828cc72361SWai Yew CHAY { 6838cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *ctl = blk; 6848cc72361SWai Yew CHAY 6858cc72361SWai Yew CHAY return get_field(ctl->amoplo, AMOPLO_Y); 6868cc72361SWai Yew CHAY } 6878cc72361SWai Yew CHAY 6888cc72361SWai Yew CHAY static unsigned int amixer_get_dirty(void *blk) 6898cc72361SWai Yew CHAY { 6908cc72361SWai Yew CHAY return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; 6918cc72361SWai Yew CHAY } 6928cc72361SWai Yew CHAY 6938cc72361SWai Yew CHAY static int amixer_rsc_get_ctrl_blk(void **rblk) 6948cc72361SWai Yew CHAY { 6958cc72361SWai Yew CHAY struct amixer_rsc_ctrl_blk *blk; 6968cc72361SWai Yew CHAY 6978cc72361SWai Yew CHAY *rblk = NULL; 6988cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 69935ebf6e7STakashi Iwai if (!blk) 7008cc72361SWai Yew CHAY return -ENOMEM; 7018cc72361SWai Yew CHAY 7028cc72361SWai Yew CHAY *rblk = blk; 7038cc72361SWai Yew CHAY 7048cc72361SWai Yew CHAY return 0; 7058cc72361SWai Yew CHAY } 7068cc72361SWai Yew CHAY 7078cc72361SWai Yew CHAY static int amixer_rsc_put_ctrl_blk(void *blk) 7088cc72361SWai Yew CHAY { 7098cc72361SWai Yew CHAY kfree((struct amixer_rsc_ctrl_blk *)blk); 7108cc72361SWai Yew CHAY 7118cc72361SWai Yew CHAY return 0; 7128cc72361SWai Yew CHAY } 7138cc72361SWai Yew CHAY 7148cc72361SWai Yew CHAY static int amixer_mgr_get_ctrl_blk(void **rblk) 7158cc72361SWai Yew CHAY { 7168cc72361SWai Yew CHAY /*amixer_mgr_ctrl_blk_t *blk;*/ 7178cc72361SWai Yew CHAY 7188cc72361SWai Yew CHAY *rblk = NULL; 7198cc72361SWai Yew CHAY /*blk = kzalloc(sizeof(*blk), GFP_KERNEL); 72035ebf6e7STakashi Iwai if (!blk) 7218cc72361SWai Yew CHAY return -ENOMEM; 7228cc72361SWai Yew CHAY 7238cc72361SWai Yew CHAY *rblk = blk;*/ 7248cc72361SWai Yew CHAY 7258cc72361SWai Yew CHAY return 0; 7268cc72361SWai Yew CHAY } 7278cc72361SWai Yew CHAY 7288cc72361SWai Yew CHAY static int amixer_mgr_put_ctrl_blk(void *blk) 7298cc72361SWai Yew CHAY { 7308cc72361SWai Yew CHAY /*kfree((amixer_mgr_ctrl_blk_t *)blk);*/ 7318cc72361SWai Yew CHAY 7328cc72361SWai Yew CHAY return 0; 7338cc72361SWai Yew CHAY } 7348cc72361SWai Yew CHAY 7358cc72361SWai Yew CHAY /* 7368cc72361SWai Yew CHAY * DAIO control block definitions. 7378cc72361SWai Yew CHAY */ 7388cc72361SWai Yew CHAY 7398cc72361SWai Yew CHAY /* Receiver Sample Rate Tracker Control register */ 7408cc72361SWai Yew CHAY #define SRTCTL_SRCR 0x000000FF 7418cc72361SWai Yew CHAY #define SRTCTL_SRCL 0x0000FF00 7428cc72361SWai Yew CHAY #define SRTCTL_RSR 0x00030000 7438cc72361SWai Yew CHAY #define SRTCTL_DRAT 0x000C0000 7448cc72361SWai Yew CHAY #define SRTCTL_RLE 0x10000000 7458cc72361SWai Yew CHAY #define SRTCTL_RLP 0x20000000 7468cc72361SWai Yew CHAY #define SRTCTL_EC 0x40000000 7478cc72361SWai Yew CHAY #define SRTCTL_ET 0x80000000 7488cc72361SWai Yew CHAY 7498cc72361SWai Yew CHAY /* DAIO Receiver register dirty flags */ 7508cc72361SWai Yew CHAY union dai_dirty { 7518cc72361SWai Yew CHAY struct { 7528cc72361SWai Yew CHAY u16 srtctl:1; 7538cc72361SWai Yew CHAY u16 rsv:15; 7548cc72361SWai Yew CHAY } bf; 7558cc72361SWai Yew CHAY u16 data; 7568cc72361SWai Yew CHAY }; 7578cc72361SWai Yew CHAY 7588cc72361SWai Yew CHAY /* DAIO Receiver control block */ 7598cc72361SWai Yew CHAY struct dai_ctrl_blk { 7608cc72361SWai Yew CHAY unsigned int srtctl; 7618cc72361SWai Yew CHAY union dai_dirty dirty; 7628cc72361SWai Yew CHAY }; 7638cc72361SWai Yew CHAY 7648cc72361SWai Yew CHAY /* S/PDIF Transmitter register dirty flags */ 7658cc72361SWai Yew CHAY union dao_dirty { 7668cc72361SWai Yew CHAY struct { 7678cc72361SWai Yew CHAY u16 spos:1; 7688cc72361SWai Yew CHAY u16 rsv:15; 7698cc72361SWai Yew CHAY } bf; 7708cc72361SWai Yew CHAY u16 data; 7718cc72361SWai Yew CHAY }; 7728cc72361SWai Yew CHAY 7738cc72361SWai Yew CHAY /* S/PDIF Transmitter control block */ 7748cc72361SWai Yew CHAY struct dao_ctrl_blk { 7758cc72361SWai Yew CHAY unsigned int spos; /* S/PDIF Output Channel Status Register */ 7768cc72361SWai Yew CHAY union dao_dirty dirty; 7778cc72361SWai Yew CHAY }; 7788cc72361SWai Yew CHAY 7798cc72361SWai Yew CHAY /* Audio Input Mapper RAM */ 7808cc72361SWai Yew CHAY #define AIM_ARC 0x00000FFF 7818cc72361SWai Yew CHAY #define AIM_NXT 0x007F0000 7828cc72361SWai Yew CHAY 7838cc72361SWai Yew CHAY struct daoimap { 7848cc72361SWai Yew CHAY unsigned int aim; 7858cc72361SWai Yew CHAY unsigned int idx; 7868cc72361SWai Yew CHAY }; 7878cc72361SWai Yew CHAY 7888cc72361SWai Yew CHAY /* I2S Transmitter/Receiver Control register */ 7898cc72361SWai Yew CHAY #define I2SCTL_EA 0x00000004 7908cc72361SWai Yew CHAY #define I2SCTL_EI 0x00000010 7918cc72361SWai Yew CHAY 7928cc72361SWai Yew CHAY /* S/PDIF Transmitter Control register */ 7938cc72361SWai Yew CHAY #define SPOCTL_OE 0x00000001 7948cc72361SWai Yew CHAY #define SPOCTL_OS 0x0000000E 7958cc72361SWai Yew CHAY #define SPOCTL_RIV 0x00000010 7968cc72361SWai Yew CHAY #define SPOCTL_LIV 0x00000020 7978cc72361SWai Yew CHAY #define SPOCTL_SR 0x000000C0 7988cc72361SWai Yew CHAY 7998cc72361SWai Yew CHAY /* S/PDIF Receiver Control register */ 8008cc72361SWai Yew CHAY #define SPICTL_EN 0x00000001 8018cc72361SWai Yew CHAY #define SPICTL_I24 0x00000002 8028cc72361SWai Yew CHAY #define SPICTL_IB 0x00000004 8038cc72361SWai Yew CHAY #define SPICTL_SM 0x00000008 8048cc72361SWai Yew CHAY #define SPICTL_VM 0x00000010 8058cc72361SWai Yew CHAY 8068cc72361SWai Yew CHAY /* DAIO manager register dirty flags */ 8078cc72361SWai Yew CHAY union daio_mgr_dirty { 8088cc72361SWai Yew CHAY struct { 8098cc72361SWai Yew CHAY u32 i2soctl:4; 8108cc72361SWai Yew CHAY u32 i2sictl:4; 8118cc72361SWai Yew CHAY u32 spoctl:4; 8128cc72361SWai Yew CHAY u32 spictl:4; 8138cc72361SWai Yew CHAY u32 daoimap:1; 8148cc72361SWai Yew CHAY u32 rsv:15; 8158cc72361SWai Yew CHAY } bf; 8168cc72361SWai Yew CHAY u32 data; 8178cc72361SWai Yew CHAY }; 8188cc72361SWai Yew CHAY 8198cc72361SWai Yew CHAY /* DAIO manager control block */ 8208cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk { 8218cc72361SWai Yew CHAY unsigned int i2sctl; 8228cc72361SWai Yew CHAY unsigned int spoctl; 8238cc72361SWai Yew CHAY unsigned int spictl; 8248cc72361SWai Yew CHAY struct daoimap daoimap; 8258cc72361SWai Yew CHAY union daio_mgr_dirty dirty; 8268cc72361SWai Yew CHAY }; 8278cc72361SWai Yew CHAY 8288cc72361SWai Yew CHAY static int dai_srt_set_srcr(void *blk, unsigned int src) 8298cc72361SWai Yew CHAY { 8308cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8318cc72361SWai Yew CHAY 8328cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_SRCR, src); 8338cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8348cc72361SWai Yew CHAY return 0; 8358cc72361SWai Yew CHAY } 8368cc72361SWai Yew CHAY 8378cc72361SWai Yew CHAY static int dai_srt_set_srcl(void *blk, unsigned int src) 8388cc72361SWai Yew CHAY { 8398cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8408cc72361SWai Yew CHAY 8418cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_SRCL, src); 8428cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8438cc72361SWai Yew CHAY return 0; 8448cc72361SWai Yew CHAY } 8458cc72361SWai Yew CHAY 8468cc72361SWai Yew CHAY static int dai_srt_set_rsr(void *blk, unsigned int rsr) 8478cc72361SWai Yew CHAY { 8488cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8498cc72361SWai Yew CHAY 8508cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_RSR, rsr); 8518cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8528cc72361SWai Yew CHAY return 0; 8538cc72361SWai Yew CHAY } 8548cc72361SWai Yew CHAY 8558cc72361SWai Yew CHAY static int dai_srt_set_drat(void *blk, unsigned int drat) 8568cc72361SWai Yew CHAY { 8578cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8588cc72361SWai Yew CHAY 8598cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_DRAT, drat); 8608cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8618cc72361SWai Yew CHAY return 0; 8628cc72361SWai Yew CHAY } 8638cc72361SWai Yew CHAY 8648cc72361SWai Yew CHAY static int dai_srt_set_ec(void *blk, unsigned int ec) 8658cc72361SWai Yew CHAY { 8668cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8678cc72361SWai Yew CHAY 8688cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_EC, ec ? 1 : 0); 8698cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8708cc72361SWai Yew CHAY return 0; 8718cc72361SWai Yew CHAY } 8728cc72361SWai Yew CHAY 8738cc72361SWai Yew CHAY static int dai_srt_set_et(void *blk, unsigned int et) 8748cc72361SWai Yew CHAY { 8758cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8768cc72361SWai Yew CHAY 8778cc72361SWai Yew CHAY set_field(&ctl->srtctl, SRTCTL_ET, et ? 1 : 0); 8788cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 1; 8798cc72361SWai Yew CHAY return 0; 8808cc72361SWai Yew CHAY } 8818cc72361SWai Yew CHAY 8828cc72361SWai Yew CHAY static int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) 8838cc72361SWai Yew CHAY { 8848cc72361SWai Yew CHAY struct dai_ctrl_blk *ctl = blk; 8858cc72361SWai Yew CHAY 8868cc72361SWai Yew CHAY if (ctl->dirty.bf.srtctl) { 8878cc72361SWai Yew CHAY if (idx < 4) { 8888cc72361SWai Yew CHAY /* S/PDIF SRTs */ 8898cc72361SWai Yew CHAY hw_write_20kx(hw, SRTSCTL+0x4*idx, ctl->srtctl); 8908cc72361SWai Yew CHAY } else { 8918cc72361SWai Yew CHAY /* I2S SRT */ 8928cc72361SWai Yew CHAY hw_write_20kx(hw, SRTICTL, ctl->srtctl); 8938cc72361SWai Yew CHAY } 8948cc72361SWai Yew CHAY ctl->dirty.bf.srtctl = 0; 8958cc72361SWai Yew CHAY } 8968cc72361SWai Yew CHAY 8978cc72361SWai Yew CHAY return 0; 8988cc72361SWai Yew CHAY } 8998cc72361SWai Yew CHAY 9008cc72361SWai Yew CHAY static int dai_get_ctrl_blk(void **rblk) 9018cc72361SWai Yew CHAY { 9028cc72361SWai Yew CHAY struct dai_ctrl_blk *blk; 9038cc72361SWai Yew CHAY 9048cc72361SWai Yew CHAY *rblk = NULL; 9058cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 90635ebf6e7STakashi Iwai if (!blk) 9078cc72361SWai Yew CHAY return -ENOMEM; 9088cc72361SWai Yew CHAY 9098cc72361SWai Yew CHAY *rblk = blk; 9108cc72361SWai Yew CHAY 9118cc72361SWai Yew CHAY return 0; 9128cc72361SWai Yew CHAY } 9138cc72361SWai Yew CHAY 9148cc72361SWai Yew CHAY static int dai_put_ctrl_blk(void *blk) 9158cc72361SWai Yew CHAY { 9168cc72361SWai Yew CHAY kfree((struct dai_ctrl_blk *)blk); 9178cc72361SWai Yew CHAY 9188cc72361SWai Yew CHAY return 0; 9198cc72361SWai Yew CHAY } 9208cc72361SWai Yew CHAY 9218cc72361SWai Yew CHAY static int dao_set_spos(void *blk, unsigned int spos) 9228cc72361SWai Yew CHAY { 9238cc72361SWai Yew CHAY ((struct dao_ctrl_blk *)blk)->spos = spos; 9248cc72361SWai Yew CHAY ((struct dao_ctrl_blk *)blk)->dirty.bf.spos = 1; 9258cc72361SWai Yew CHAY return 0; 9268cc72361SWai Yew CHAY } 9278cc72361SWai Yew CHAY 9288cc72361SWai Yew CHAY static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) 9298cc72361SWai Yew CHAY { 9308cc72361SWai Yew CHAY struct dao_ctrl_blk *ctl = blk; 9318cc72361SWai Yew CHAY 9328cc72361SWai Yew CHAY if (ctl->dirty.bf.spos) { 9338cc72361SWai Yew CHAY if (idx < 4) { 9348cc72361SWai Yew CHAY /* S/PDIF SPOSx */ 9358cc72361SWai Yew CHAY hw_write_20kx(hw, SPOS+0x4*idx, ctl->spos); 9368cc72361SWai Yew CHAY } 9378cc72361SWai Yew CHAY ctl->dirty.bf.spos = 0; 9388cc72361SWai Yew CHAY } 9398cc72361SWai Yew CHAY 9408cc72361SWai Yew CHAY return 0; 9418cc72361SWai Yew CHAY } 9428cc72361SWai Yew CHAY 9438cc72361SWai Yew CHAY static int dao_get_spos(void *blk, unsigned int *spos) 9448cc72361SWai Yew CHAY { 9458cc72361SWai Yew CHAY *spos = ((struct dao_ctrl_blk *)blk)->spos; 9468cc72361SWai Yew CHAY return 0; 9478cc72361SWai Yew CHAY } 9488cc72361SWai Yew CHAY 9498cc72361SWai Yew CHAY static int dao_get_ctrl_blk(void **rblk) 9508cc72361SWai Yew CHAY { 9518cc72361SWai Yew CHAY struct dao_ctrl_blk *blk; 9528cc72361SWai Yew CHAY 9538cc72361SWai Yew CHAY *rblk = NULL; 9548cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 95535ebf6e7STakashi Iwai if (!blk) 9568cc72361SWai Yew CHAY return -ENOMEM; 9578cc72361SWai Yew CHAY 9588cc72361SWai Yew CHAY *rblk = blk; 9598cc72361SWai Yew CHAY 9608cc72361SWai Yew CHAY return 0; 9618cc72361SWai Yew CHAY } 9628cc72361SWai Yew CHAY 9638cc72361SWai Yew CHAY static int dao_put_ctrl_blk(void *blk) 9648cc72361SWai Yew CHAY { 9658cc72361SWai Yew CHAY kfree((struct dao_ctrl_blk *)blk); 9668cc72361SWai Yew CHAY 9678cc72361SWai Yew CHAY return 0; 9688cc72361SWai Yew CHAY } 9698cc72361SWai Yew CHAY 9708cc72361SWai Yew CHAY static int daio_mgr_enb_dai(void *blk, unsigned int idx) 9718cc72361SWai Yew CHAY { 9728cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 9738cc72361SWai Yew CHAY 9748cc72361SWai Yew CHAY if (idx < 4) { 9758cc72361SWai Yew CHAY /* S/PDIF input */ 9768cc72361SWai Yew CHAY set_field(&ctl->spictl, SPICTL_EN << (idx*8), 1); 9778cc72361SWai Yew CHAY ctl->dirty.bf.spictl |= (0x1 << idx); 9788cc72361SWai Yew CHAY } else { 9798cc72361SWai Yew CHAY /* I2S input */ 9808cc72361SWai Yew CHAY idx %= 4; 9818cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 1); 9828cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl |= (0x1 << idx); 9838cc72361SWai Yew CHAY } 9848cc72361SWai Yew CHAY return 0; 9858cc72361SWai Yew CHAY } 9868cc72361SWai Yew CHAY 9878cc72361SWai Yew CHAY static int daio_mgr_dsb_dai(void *blk, unsigned int idx) 9888cc72361SWai Yew CHAY { 9898cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 9908cc72361SWai Yew CHAY 9918cc72361SWai Yew CHAY if (idx < 4) { 9928cc72361SWai Yew CHAY /* S/PDIF input */ 9938cc72361SWai Yew CHAY set_field(&ctl->spictl, SPICTL_EN << (idx*8), 0); 9948cc72361SWai Yew CHAY ctl->dirty.bf.spictl |= (0x1 << idx); 9958cc72361SWai Yew CHAY } else { 9968cc72361SWai Yew CHAY /* I2S input */ 9978cc72361SWai Yew CHAY idx %= 4; 9988cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 0); 9998cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl |= (0x1 << idx); 10008cc72361SWai Yew CHAY } 10018cc72361SWai Yew CHAY return 0; 10028cc72361SWai Yew CHAY } 10038cc72361SWai Yew CHAY 10048cc72361SWai Yew CHAY static int daio_mgr_enb_dao(void *blk, unsigned int idx) 10058cc72361SWai Yew CHAY { 10068cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10078cc72361SWai Yew CHAY 10088cc72361SWai Yew CHAY if (idx < 4) { 10098cc72361SWai Yew CHAY /* S/PDIF output */ 10108cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 1); 10118cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 10128cc72361SWai Yew CHAY } else { 10138cc72361SWai Yew CHAY /* I2S output */ 10148cc72361SWai Yew CHAY idx %= 4; 10158cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 1); 10168cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl |= (0x1 << idx); 10178cc72361SWai Yew CHAY } 10188cc72361SWai Yew CHAY return 0; 10198cc72361SWai Yew CHAY } 10208cc72361SWai Yew CHAY 10218cc72361SWai Yew CHAY static int daio_mgr_dsb_dao(void *blk, unsigned int idx) 10228cc72361SWai Yew CHAY { 10238cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10248cc72361SWai Yew CHAY 10258cc72361SWai Yew CHAY if (idx < 4) { 10268cc72361SWai Yew CHAY /* S/PDIF output */ 10278cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 0); 10288cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 10298cc72361SWai Yew CHAY } else { 10308cc72361SWai Yew CHAY /* I2S output */ 10318cc72361SWai Yew CHAY idx %= 4; 10328cc72361SWai Yew CHAY set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 0); 10338cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl |= (0x1 << idx); 10348cc72361SWai Yew CHAY } 10358cc72361SWai Yew CHAY return 0; 10368cc72361SWai Yew CHAY } 10378cc72361SWai Yew CHAY 10388cc72361SWai Yew CHAY static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) 10398cc72361SWai Yew CHAY { 10408cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10418cc72361SWai Yew CHAY 10428cc72361SWai Yew CHAY if (idx < 4) { 10438cc72361SWai Yew CHAY /* S/PDIF output */ 10448cc72361SWai Yew CHAY switch ((conf & 0x7)) { 10458cc72361SWai Yew CHAY case 0: 10468cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 3); 10478cc72361SWai Yew CHAY break; /* CDIF */ 10488cc72361SWai Yew CHAY case 1: 10498cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 0); 10508cc72361SWai Yew CHAY break; 10518cc72361SWai Yew CHAY case 2: 10528cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 1); 10538cc72361SWai Yew CHAY break; 10548cc72361SWai Yew CHAY case 4: 10558cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 2); 10568cc72361SWai Yew CHAY break; 10578cc72361SWai Yew CHAY default: 10588cc72361SWai Yew CHAY break; 10598cc72361SWai Yew CHAY } 10608cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_LIV << (idx*8), 10618cc72361SWai Yew CHAY (conf >> 4) & 0x1); /* Non-audio */ 10628cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_RIV << (idx*8), 10638cc72361SWai Yew CHAY (conf >> 4) & 0x1); /* Non-audio */ 10648cc72361SWai Yew CHAY set_field(&ctl->spoctl, SPOCTL_OS << (idx*8), 10658cc72361SWai Yew CHAY ((conf >> 3) & 0x1) ? 2 : 2); /* Raw */ 10668cc72361SWai Yew CHAY 10678cc72361SWai Yew CHAY ctl->dirty.bf.spoctl |= (0x1 << idx); 10688cc72361SWai Yew CHAY } else { 10698cc72361SWai Yew CHAY /* I2S output */ 10708cc72361SWai Yew CHAY /*idx %= 4; */ 10718cc72361SWai Yew CHAY } 10728cc72361SWai Yew CHAY return 0; 10738cc72361SWai Yew CHAY } 10748cc72361SWai Yew CHAY 10758cc72361SWai Yew CHAY static int daio_mgr_set_imaparc(void *blk, unsigned int slot) 10768cc72361SWai Yew CHAY { 10778cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10788cc72361SWai Yew CHAY 10798cc72361SWai Yew CHAY set_field(&ctl->daoimap.aim, AIM_ARC, slot); 10808cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 10818cc72361SWai Yew CHAY return 0; 10828cc72361SWai Yew CHAY } 10838cc72361SWai Yew CHAY 10848cc72361SWai Yew CHAY static int daio_mgr_set_imapnxt(void *blk, unsigned int next) 10858cc72361SWai Yew CHAY { 10868cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10878cc72361SWai Yew CHAY 10888cc72361SWai Yew CHAY set_field(&ctl->daoimap.aim, AIM_NXT, next); 10898cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 10908cc72361SWai Yew CHAY return 0; 10918cc72361SWai Yew CHAY } 10928cc72361SWai Yew CHAY 10938cc72361SWai Yew CHAY static int daio_mgr_set_imapaddr(void *blk, unsigned int addr) 10948cc72361SWai Yew CHAY { 10958cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 10968cc72361SWai Yew CHAY 10978cc72361SWai Yew CHAY ctl->daoimap.idx = addr; 10988cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 1; 10998cc72361SWai Yew CHAY return 0; 11008cc72361SWai Yew CHAY } 11018cc72361SWai Yew CHAY 11028cc72361SWai Yew CHAY static int daio_mgr_commit_write(struct hw *hw, void *blk) 11038cc72361SWai Yew CHAY { 11048cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *ctl = blk; 1105514eef9cSTakashi Iwai int i; 11068cc72361SWai Yew CHAY 11078cc72361SWai Yew CHAY if (ctl->dirty.bf.i2sictl || ctl->dirty.bf.i2soctl) { 11088cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 11098cc72361SWai Yew CHAY if ((ctl->dirty.bf.i2sictl & (0x1 << i))) 11108cc72361SWai Yew CHAY ctl->dirty.bf.i2sictl &= ~(0x1 << i); 11118cc72361SWai Yew CHAY 11128cc72361SWai Yew CHAY if ((ctl->dirty.bf.i2soctl & (0x1 << i))) 11138cc72361SWai Yew CHAY ctl->dirty.bf.i2soctl &= ~(0x1 << i); 11148cc72361SWai Yew CHAY } 11158cc72361SWai Yew CHAY hw_write_20kx(hw, I2SCTL, ctl->i2sctl); 11168cc72361SWai Yew CHAY mdelay(1); 11178cc72361SWai Yew CHAY } 11188cc72361SWai Yew CHAY if (ctl->dirty.bf.spoctl) { 11198cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 11208cc72361SWai Yew CHAY if ((ctl->dirty.bf.spoctl & (0x1 << i))) 11218cc72361SWai Yew CHAY ctl->dirty.bf.spoctl &= ~(0x1 << i); 11228cc72361SWai Yew CHAY } 11238cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, ctl->spoctl); 11248cc72361SWai Yew CHAY mdelay(1); 11258cc72361SWai Yew CHAY } 11268cc72361SWai Yew CHAY if (ctl->dirty.bf.spictl) { 11278cc72361SWai Yew CHAY for (i = 0; i < 4; i++) { 11288cc72361SWai Yew CHAY if ((ctl->dirty.bf.spictl & (0x1 << i))) 11298cc72361SWai Yew CHAY ctl->dirty.bf.spictl &= ~(0x1 << i); 11308cc72361SWai Yew CHAY } 11318cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, ctl->spictl); 11328cc72361SWai Yew CHAY mdelay(1); 11338cc72361SWai Yew CHAY } 11348cc72361SWai Yew CHAY if (ctl->dirty.bf.daoimap) { 11358cc72361SWai Yew CHAY hw_write_20kx(hw, DAOIMAP+ctl->daoimap.idx*4, 11368cc72361SWai Yew CHAY ctl->daoimap.aim); 11378cc72361SWai Yew CHAY ctl->dirty.bf.daoimap = 0; 11388cc72361SWai Yew CHAY } 11398cc72361SWai Yew CHAY 11408cc72361SWai Yew CHAY return 0; 11418cc72361SWai Yew CHAY } 11428cc72361SWai Yew CHAY 11438cc72361SWai Yew CHAY static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) 11448cc72361SWai Yew CHAY { 11458cc72361SWai Yew CHAY struct daio_mgr_ctrl_blk *blk; 11468cc72361SWai Yew CHAY 11478cc72361SWai Yew CHAY *rblk = NULL; 11488cc72361SWai Yew CHAY blk = kzalloc(sizeof(*blk), GFP_KERNEL); 114935ebf6e7STakashi Iwai if (!blk) 11508cc72361SWai Yew CHAY return -ENOMEM; 11518cc72361SWai Yew CHAY 11528cc72361SWai Yew CHAY blk->i2sctl = hw_read_20kx(hw, I2SCTL); 11538cc72361SWai Yew CHAY blk->spoctl = hw_read_20kx(hw, SPOCTL); 11548cc72361SWai Yew CHAY blk->spictl = hw_read_20kx(hw, SPICTL); 11558cc72361SWai Yew CHAY 11568cc72361SWai Yew CHAY *rblk = blk; 11578cc72361SWai Yew CHAY 11588cc72361SWai Yew CHAY return 0; 11598cc72361SWai Yew CHAY } 11608cc72361SWai Yew CHAY 11618cc72361SWai Yew CHAY static int daio_mgr_put_ctrl_blk(void *blk) 11628cc72361SWai Yew CHAY { 11638cc72361SWai Yew CHAY kfree((struct daio_mgr_ctrl_blk *)blk); 11648cc72361SWai Yew CHAY 11658cc72361SWai Yew CHAY return 0; 11668cc72361SWai Yew CHAY } 11678cc72361SWai Yew CHAY 1168b7bbf876STakashi Iwai /* Timer interrupt */ 1169b7bbf876STakashi Iwai static int set_timer_irq(struct hw *hw, int enable) 1170b7bbf876STakashi Iwai { 1171b7bbf876STakashi Iwai hw_write_20kx(hw, GIE, enable ? IT_INT : 0); 1172b7bbf876STakashi Iwai return 0; 1173b7bbf876STakashi Iwai } 1174b7bbf876STakashi Iwai 1175b7bbf876STakashi Iwai static int set_timer_tick(struct hw *hw, unsigned int ticks) 1176b7bbf876STakashi Iwai { 1177b7bbf876STakashi Iwai if (ticks) 1178b7bbf876STakashi Iwai ticks |= TIMR_IE | TIMR_IP; 1179b7bbf876STakashi Iwai hw_write_20kx(hw, TIMR, ticks); 1180b7bbf876STakashi Iwai return 0; 1181b7bbf876STakashi Iwai } 1182b7bbf876STakashi Iwai 118354de6bc8STakashi Iwai static unsigned int get_wc(struct hw *hw) 118454de6bc8STakashi Iwai { 118554de6bc8STakashi Iwai return hw_read_20kx(hw, WC); 118654de6bc8STakashi Iwai } 118754de6bc8STakashi Iwai 11888cc72361SWai Yew CHAY /* Card hardware initialization block */ 11898cc72361SWai Yew CHAY struct dac_conf { 11908cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 11918cc72361SWai Yew CHAY }; 11928cc72361SWai Yew CHAY 11938cc72361SWai Yew CHAY struct adc_conf { 11948cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 11958cc72361SWai Yew CHAY unsigned char input; /* the input source of ADC */ 11968cc72361SWai Yew CHAY unsigned char mic20db; /* boost mic by 20db if input is microphone */ 11978cc72361SWai Yew CHAY }; 11988cc72361SWai Yew CHAY 11998cc72361SWai Yew CHAY struct daio_conf { 12008cc72361SWai Yew CHAY unsigned int msr; /* master sample rate in rsrs */ 12018cc72361SWai Yew CHAY }; 12028cc72361SWai Yew CHAY 12038cc72361SWai Yew CHAY struct trn_conf { 12048cc72361SWai Yew CHAY unsigned long vm_pgt_phys; 12058cc72361SWai Yew CHAY }; 12068cc72361SWai Yew CHAY 12078cc72361SWai Yew CHAY static int hw_daio_init(struct hw *hw, const struct daio_conf *info) 12088cc72361SWai Yew CHAY { 1209514eef9cSTakashi Iwai u32 i2sorg; 1210514eef9cSTakashi Iwai u32 spdorg; 12118cc72361SWai Yew CHAY 12128cc72361SWai Yew CHAY /* Read I2S CTL. Keep original value. */ 12138cc72361SWai Yew CHAY /*i2sorg = hw_read_20kx(hw, I2SCTL);*/ 12148cc72361SWai Yew CHAY i2sorg = 0x94040404; /* enable all audio out and I2S-D input */ 12158cc72361SWai Yew CHAY /* Program I2S with proper master sample rate and enable 12168cc72361SWai Yew CHAY * the correct I2S channel. */ 12178cc72361SWai Yew CHAY i2sorg &= 0xfffffffc; 12188cc72361SWai Yew CHAY 12198cc72361SWai Yew CHAY /* Enable S/PDIF-out-A in fixed 24-bit data 12208cc72361SWai Yew CHAY * format and default to 48kHz. */ 12218cc72361SWai Yew CHAY /* Disable all before doing any changes. */ 12228cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, 0x0); 12238cc72361SWai Yew CHAY spdorg = 0x05; 12248cc72361SWai Yew CHAY 12258cc72361SWai Yew CHAY switch (info->msr) { 12268cc72361SWai Yew CHAY case 1: 12278cc72361SWai Yew CHAY i2sorg |= 1; 12288cc72361SWai Yew CHAY spdorg |= (0x0 << 6); 12298cc72361SWai Yew CHAY break; 12308cc72361SWai Yew CHAY case 2: 12318cc72361SWai Yew CHAY i2sorg |= 2; 12328cc72361SWai Yew CHAY spdorg |= (0x1 << 6); 12338cc72361SWai Yew CHAY break; 12348cc72361SWai Yew CHAY case 4: 12358cc72361SWai Yew CHAY i2sorg |= 3; 12368cc72361SWai Yew CHAY spdorg |= (0x2 << 6); 12378cc72361SWai Yew CHAY break; 12388cc72361SWai Yew CHAY default: 12398cc72361SWai Yew CHAY i2sorg |= 1; 12408cc72361SWai Yew CHAY break; 12418cc72361SWai Yew CHAY } 12428cc72361SWai Yew CHAY 12438cc72361SWai Yew CHAY hw_write_20kx(hw, I2SCTL, i2sorg); 12448cc72361SWai Yew CHAY hw_write_20kx(hw, SPOCTL, spdorg); 12458cc72361SWai Yew CHAY 12468cc72361SWai Yew CHAY /* Enable S/PDIF-in-A in fixed 24-bit data format. */ 12478cc72361SWai Yew CHAY /* Disable all before doing any changes. */ 12488cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, 0x0); 12498cc72361SWai Yew CHAY mdelay(1); 12508cc72361SWai Yew CHAY spdorg = 0x0a0a0a0a; 12518cc72361SWai Yew CHAY hw_write_20kx(hw, SPICTL, spdorg); 12528cc72361SWai Yew CHAY mdelay(1); 12538cc72361SWai Yew CHAY 12548cc72361SWai Yew CHAY return 0; 12558cc72361SWai Yew CHAY } 12568cc72361SWai Yew CHAY 12578cc72361SWai Yew CHAY /* TRANSPORT operations */ 12588cc72361SWai Yew CHAY static int hw_trn_init(struct hw *hw, const struct trn_conf *info) 12598cc72361SWai Yew CHAY { 1260514eef9cSTakashi Iwai u32 trnctl; 1261514eef9cSTakashi Iwai u32 ptp_phys_low, ptp_phys_high; 12628cc72361SWai Yew CHAY 12638cc72361SWai Yew CHAY /* Set up device page table */ 12648cc72361SWai Yew CHAY if ((~0UL) == info->vm_pgt_phys) { 12650cae90a9SSudip Mukherjee dev_err(hw->card->dev, 12660cae90a9SSudip Mukherjee "Wrong device page table page address!\n"); 12678cc72361SWai Yew CHAY return -1; 12688cc72361SWai Yew CHAY } 12698cc72361SWai Yew CHAY 12708cc72361SWai Yew CHAY trnctl = 0x13; /* 32-bit, 4k-size page */ 1271cd391e20STakashi Iwai ptp_phys_low = (u32)info->vm_pgt_phys; 1272cd391e20STakashi Iwai ptp_phys_high = upper_32_bits(info->vm_pgt_phys); 1273cd391e20STakashi Iwai if (sizeof(void *) == 8) /* 64bit address */ 12748cc72361SWai Yew CHAY trnctl |= (1 << 2); 1275cd391e20STakashi Iwai #if 0 /* Only 4k h/w pages for simplicitiy */ 12768cc72361SWai Yew CHAY #if PAGE_SIZE == 8192 12778cc72361SWai Yew CHAY trnctl |= (1<<5); 12788cc72361SWai Yew CHAY #endif 1279cd391e20STakashi Iwai #endif 12808cc72361SWai Yew CHAY hw_write_20kx(hw, PTPALX, ptp_phys_low); 12818cc72361SWai Yew CHAY hw_write_20kx(hw, PTPAHX, ptp_phys_high); 12828cc72361SWai Yew CHAY hw_write_20kx(hw, TRNCTL, trnctl); 128325985edcSLucas De Marchi hw_write_20kx(hw, TRNIS, 0x200c01); /* really needed? */ 12848cc72361SWai Yew CHAY 12858cc72361SWai Yew CHAY return 0; 12868cc72361SWai Yew CHAY } 12878cc72361SWai Yew CHAY 12888cc72361SWai Yew CHAY /* Card initialization */ 12898cc72361SWai Yew CHAY #define GCTL_EAC 0x00000001 12908cc72361SWai Yew CHAY #define GCTL_EAI 0x00000002 12918cc72361SWai Yew CHAY #define GCTL_BEP 0x00000004 12928cc72361SWai Yew CHAY #define GCTL_BES 0x00000008 12938cc72361SWai Yew CHAY #define GCTL_DSP 0x00000010 12948cc72361SWai Yew CHAY #define GCTL_DBP 0x00000020 12958cc72361SWai Yew CHAY #define GCTL_ABP 0x00000040 12968cc72361SWai Yew CHAY #define GCTL_TBP 0x00000080 12978cc72361SWai Yew CHAY #define GCTL_SBP 0x00000100 12988cc72361SWai Yew CHAY #define GCTL_FBP 0x00000200 12998cc72361SWai Yew CHAY #define GCTL_XA 0x00000400 13008cc72361SWai Yew CHAY #define GCTL_ET 0x00000800 13018cc72361SWai Yew CHAY #define GCTL_PR 0x00001000 13028cc72361SWai Yew CHAY #define GCTL_MRL 0x00002000 13038cc72361SWai Yew CHAY #define GCTL_SDE 0x00004000 13048cc72361SWai Yew CHAY #define GCTL_SDI 0x00008000 13058cc72361SWai Yew CHAY #define GCTL_SM 0x00010000 13068cc72361SWai Yew CHAY #define GCTL_SR 0x00020000 13078cc72361SWai Yew CHAY #define GCTL_SD 0x00040000 13088cc72361SWai Yew CHAY #define GCTL_SE 0x00080000 13098cc72361SWai Yew CHAY #define GCTL_AID 0x00100000 13108cc72361SWai Yew CHAY 13118cc72361SWai Yew CHAY static int hw_pll_init(struct hw *hw, unsigned int rsr) 13128cc72361SWai Yew CHAY { 13138cc72361SWai Yew CHAY unsigned int pllctl; 1314514eef9cSTakashi Iwai int i; 13158cc72361SWai Yew CHAY 13168cc72361SWai Yew CHAY pllctl = (48000 == rsr) ? 0x1480a001 : 0x1480a731; 13178cc72361SWai Yew CHAY for (i = 0; i < 3; i++) { 13188cc72361SWai Yew CHAY if (hw_read_20kx(hw, PLLCTL) == pllctl) 13198cc72361SWai Yew CHAY break; 13208cc72361SWai Yew CHAY 13218cc72361SWai Yew CHAY hw_write_20kx(hw, PLLCTL, pllctl); 13228cc72361SWai Yew CHAY mdelay(40); 13238cc72361SWai Yew CHAY } 13248cc72361SWai Yew CHAY if (i >= 3) { 13250cae90a9SSudip Mukherjee dev_alert(hw->card->dev, "PLL initialization failed!!!\n"); 13268cc72361SWai Yew CHAY return -EBUSY; 13278cc72361SWai Yew CHAY } 13288cc72361SWai Yew CHAY 13298cc72361SWai Yew CHAY return 0; 13308cc72361SWai Yew CHAY } 13318cc72361SWai Yew CHAY 13328cc72361SWai Yew CHAY static int hw_auto_init(struct hw *hw) 13338cc72361SWai Yew CHAY { 13348cc72361SWai Yew CHAY unsigned int gctl; 13358cc72361SWai Yew CHAY int i; 13368cc72361SWai Yew CHAY 13378cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 13388cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAI, 0); 13398cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 13408cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAI, 1); 13418cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 13428cc72361SWai Yew CHAY mdelay(10); 13438cc72361SWai Yew CHAY for (i = 0; i < 400000; i++) { 13448cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 13458cc72361SWai Yew CHAY if (get_field(gctl, GCTL_AID)) 13468cc72361SWai Yew CHAY break; 13478cc72361SWai Yew CHAY } 13488cc72361SWai Yew CHAY if (!get_field(gctl, GCTL_AID)) { 13490cae90a9SSudip Mukherjee dev_alert(hw->card->dev, "Card Auto-init failed!!!\n"); 13508cc72361SWai Yew CHAY return -EBUSY; 13518cc72361SWai Yew CHAY } 13528cc72361SWai Yew CHAY 13538cc72361SWai Yew CHAY return 0; 13548cc72361SWai Yew CHAY } 13558cc72361SWai Yew CHAY 13568cc72361SWai Yew CHAY static int i2c_unlock(struct hw *hw) 13578cc72361SWai Yew CHAY { 13588cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13598cc72361SWai Yew CHAY return 0; 13608cc72361SWai Yew CHAY 13618cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x8c); 13628cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x0e); 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, 0xee); 13678cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0xaa); 13688cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13698cc72361SWai Yew CHAY return 0; 13708cc72361SWai Yew CHAY 13718cc72361SWai Yew CHAY return -1; 13728cc72361SWai Yew CHAY } 13738cc72361SWai Yew CHAY 13748cc72361SWai Yew CHAY static void i2c_lock(struct hw *hw) 13758cc72361SWai Yew CHAY { 13768cc72361SWai Yew CHAY if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 13778cc72361SWai Yew CHAY hw_write_pci(hw, 0xcc, 0x00); 13788cc72361SWai Yew CHAY } 13798cc72361SWai Yew CHAY 13808cc72361SWai Yew CHAY static void i2c_write(struct hw *hw, u32 device, u32 addr, u32 data) 13818cc72361SWai Yew CHAY { 1382514eef9cSTakashi Iwai unsigned int ret; 13838cc72361SWai Yew CHAY 13848cc72361SWai Yew CHAY do { 13858cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 13868cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 13878cc72361SWai Yew CHAY hw_write_pci(hw, 0xE0, device); 13888cc72361SWai Yew CHAY hw_write_pci(hw, 0xE4, (data << 8) | (addr & 0xff)); 13898cc72361SWai Yew CHAY } 13908cc72361SWai Yew CHAY 13918cc72361SWai Yew CHAY /* DAC operations */ 13928cc72361SWai Yew CHAY 13938cc72361SWai Yew CHAY static int hw_reset_dac(struct hw *hw) 13948cc72361SWai Yew CHAY { 1395514eef9cSTakashi Iwai u32 i; 1396514eef9cSTakashi Iwai u16 gpioorg; 1397514eef9cSTakashi Iwai unsigned int ret; 13988cc72361SWai Yew CHAY 13998cc72361SWai Yew CHAY if (i2c_unlock(hw)) 14008cc72361SWai Yew CHAY return -1; 14018cc72361SWai Yew CHAY 14028cc72361SWai Yew CHAY do { 14038cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 14048cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 14058cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 14068cc72361SWai Yew CHAY 14078cc72361SWai Yew CHAY /* To be effective, need to reset the DAC twice. */ 14088cc72361SWai Yew CHAY for (i = 0; i < 2; i++) { 14098cc72361SWai Yew CHAY /* set gpio */ 14108cc72361SWai Yew CHAY mdelay(100); 14118cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14128cc72361SWai Yew CHAY gpioorg &= 0xfffd; 14138cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14148cc72361SWai Yew CHAY mdelay(1); 14158cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg | 0x2); 14168cc72361SWai Yew CHAY } 14178cc72361SWai Yew CHAY 14188cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x01, 0x80); 14198cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x02, 0x10); 14208cc72361SWai Yew CHAY 14218cc72361SWai Yew CHAY i2c_lock(hw); 14228cc72361SWai Yew CHAY 14238cc72361SWai Yew CHAY return 0; 14248cc72361SWai Yew CHAY } 14258cc72361SWai Yew CHAY 14268cc72361SWai Yew CHAY static int hw_dac_init(struct hw *hw, const struct dac_conf *info) 14278cc72361SWai Yew CHAY { 1428514eef9cSTakashi Iwai u32 data; 1429514eef9cSTakashi Iwai u16 gpioorg; 1430514eef9cSTakashi Iwai unsigned int ret; 14318cc72361SWai Yew CHAY 14329470195aSTakashi Iwai if (hw->model == CTSB055X) { 14338cc72361SWai Yew CHAY /* SB055x, unmute outputs */ 14348cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14358cc72361SWai Yew CHAY gpioorg &= 0xffbf; /* set GPIO6 to low */ 14368cc72361SWai Yew CHAY gpioorg |= 2; /* set GPIO1 to high */ 14378cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14388cc72361SWai Yew CHAY return 0; 14398cc72361SWai Yew CHAY } 14408cc72361SWai Yew CHAY 14418cc72361SWai Yew CHAY /* mute outputs */ 14428cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14438cc72361SWai Yew CHAY gpioorg &= 0xffbf; 14448cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14458cc72361SWai Yew CHAY 14468cc72361SWai Yew CHAY hw_reset_dac(hw); 14478cc72361SWai Yew CHAY 14488cc72361SWai Yew CHAY if (i2c_unlock(hw)) 14498cc72361SWai Yew CHAY return -1; 14508cc72361SWai Yew CHAY 14518cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 14528cc72361SWai Yew CHAY do { 14538cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 14548cc72361SWai Yew CHAY } while (!(ret & 0x800000)); 14558cc72361SWai Yew CHAY 14568cc72361SWai Yew CHAY switch (info->msr) { 14578cc72361SWai Yew CHAY case 1: 14588cc72361SWai Yew CHAY data = 0x24; 14598cc72361SWai Yew CHAY break; 14608cc72361SWai Yew CHAY case 2: 14618cc72361SWai Yew CHAY data = 0x25; 14628cc72361SWai Yew CHAY break; 14638cc72361SWai Yew CHAY case 4: 14648cc72361SWai Yew CHAY data = 0x26; 14658cc72361SWai Yew CHAY break; 14668cc72361SWai Yew CHAY default: 14678cc72361SWai Yew CHAY data = 0x24; 14688cc72361SWai Yew CHAY break; 14698cc72361SWai Yew CHAY } 14708cc72361SWai Yew CHAY 14718cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x06, data); 14728cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x09, data); 14738cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x0c, data); 14748cc72361SWai Yew CHAY i2c_write(hw, 0x00180080, 0x0f, data); 14758cc72361SWai Yew CHAY 14768cc72361SWai Yew CHAY i2c_lock(hw); 14778cc72361SWai Yew CHAY 14788cc72361SWai Yew CHAY /* unmute outputs */ 14798cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 14808cc72361SWai Yew CHAY gpioorg = gpioorg | 0x40; 14818cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 14828cc72361SWai Yew CHAY 14838cc72361SWai Yew CHAY return 0; 14848cc72361SWai Yew CHAY } 14858cc72361SWai Yew CHAY 14868cc72361SWai Yew CHAY /* ADC operations */ 14878cc72361SWai Yew CHAY 14888cc72361SWai Yew CHAY static int is_adc_input_selected_SB055x(struct hw *hw, enum ADCSRC type) 14898cc72361SWai Yew CHAY { 1490514eef9cSTakashi Iwai return 0; 14918cc72361SWai Yew CHAY } 14928cc72361SWai Yew CHAY 14938cc72361SWai Yew CHAY static int is_adc_input_selected_SBx(struct hw *hw, enum ADCSRC type) 14948cc72361SWai Yew CHAY { 1495514eef9cSTakashi Iwai u32 data; 14968cc72361SWai Yew CHAY 14978cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 14988cc72361SWai Yew CHAY switch (type) { 14998cc72361SWai Yew CHAY case ADC_MICIN: 15008cc72361SWai Yew CHAY data = ((data & (0x1<<7)) && (data & (0x1<<8))); 15018cc72361SWai Yew CHAY break; 15028cc72361SWai Yew CHAY case ADC_LINEIN: 15038cc72361SWai Yew CHAY data = (!(data & (0x1<<7)) && (data & (0x1<<8))); 15048cc72361SWai Yew CHAY break; 15058cc72361SWai Yew CHAY case ADC_NONE: /* Digital I/O */ 15068cc72361SWai Yew CHAY data = (!(data & (0x1<<8))); 15078cc72361SWai Yew CHAY break; 15088cc72361SWai Yew CHAY default: 15098cc72361SWai Yew CHAY data = 0; 15108cc72361SWai Yew CHAY } 15118cc72361SWai Yew CHAY return data; 15128cc72361SWai Yew CHAY } 15138cc72361SWai Yew CHAY 15148cc72361SWai Yew CHAY static int is_adc_input_selected_hendrix(struct hw *hw, enum ADCSRC type) 15158cc72361SWai Yew CHAY { 1516514eef9cSTakashi Iwai u32 data; 15178cc72361SWai Yew CHAY 15188cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 15198cc72361SWai Yew CHAY switch (type) { 15208cc72361SWai Yew CHAY case ADC_MICIN: 15218cc72361SWai Yew CHAY data = (data & (0x1 << 7)) ? 1 : 0; 15228cc72361SWai Yew CHAY break; 15238cc72361SWai Yew CHAY case ADC_LINEIN: 15248cc72361SWai Yew CHAY data = (data & (0x1 << 7)) ? 0 : 1; 15258cc72361SWai Yew CHAY break; 15268cc72361SWai Yew CHAY default: 15278cc72361SWai Yew CHAY data = 0; 15288cc72361SWai Yew CHAY } 15298cc72361SWai Yew CHAY return data; 15308cc72361SWai Yew CHAY } 15318cc72361SWai Yew CHAY 15328cc72361SWai Yew CHAY static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) 15338cc72361SWai Yew CHAY { 15349470195aSTakashi Iwai switch (hw->model) { 15359470195aSTakashi Iwai case CTSB055X: 15368cc72361SWai Yew CHAY return is_adc_input_selected_SB055x(hw, type); 15379470195aSTakashi Iwai case CTSB073X: 15388cc72361SWai Yew CHAY return is_adc_input_selected_hendrix(hw, type); 153909521d2eSTakashi Iwai case CTUAA: 15408cc72361SWai Yew CHAY return is_adc_input_selected_hendrix(hw, type); 15419470195aSTakashi Iwai default: 15428cc72361SWai Yew CHAY return is_adc_input_selected_SBx(hw, type); 15438cc72361SWai Yew CHAY } 15448cc72361SWai Yew CHAY } 15458cc72361SWai Yew CHAY 15468cc72361SWai Yew CHAY static int 15478cc72361SWai Yew CHAY adc_input_select_SB055x(struct hw *hw, enum ADCSRC type, unsigned char boost) 15488cc72361SWai Yew CHAY { 1549514eef9cSTakashi Iwai u32 data; 15508cc72361SWai Yew CHAY 15518cc72361SWai Yew CHAY /* 15528cc72361SWai Yew CHAY * check and set the following GPIO bits accordingly 15538cc72361SWai Yew CHAY * ADC_Gain = GPIO2 15548cc72361SWai Yew CHAY * DRM_off = GPIO3 15558cc72361SWai Yew CHAY * Mic_Pwr_on = GPIO7 15568cc72361SWai Yew CHAY * Digital_IO_Sel = GPIO8 15578cc72361SWai Yew CHAY * Mic_Sw = GPIO9 15588cc72361SWai Yew CHAY * Aux/MicLine_Sw = GPIO12 15598cc72361SWai Yew CHAY */ 15608cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 15618cc72361SWai Yew CHAY data &= 0xec73; 15628cc72361SWai Yew CHAY switch (type) { 15638cc72361SWai Yew CHAY case ADC_MICIN: 15648cc72361SWai Yew CHAY data |= (0x1<<7) | (0x1<<8) | (0x1<<9) ; 15658cc72361SWai Yew CHAY data |= boost ? (0x1<<2) : 0; 15668cc72361SWai Yew CHAY break; 15678cc72361SWai Yew CHAY case ADC_LINEIN: 15688cc72361SWai Yew CHAY data |= (0x1<<8); 15698cc72361SWai Yew CHAY break; 15708cc72361SWai Yew CHAY case ADC_AUX: 15718cc72361SWai Yew CHAY data |= (0x1<<8) | (0x1<<12); 15728cc72361SWai Yew CHAY break; 15738cc72361SWai Yew CHAY case ADC_NONE: 15748cc72361SWai Yew CHAY data |= (0x1<<12); /* set to digital */ 15758cc72361SWai Yew CHAY break; 15768cc72361SWai Yew CHAY default: 15778cc72361SWai Yew CHAY return -1; 15788cc72361SWai Yew CHAY } 15798cc72361SWai Yew CHAY 15808cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 15818cc72361SWai Yew CHAY 15828cc72361SWai Yew CHAY return 0; 15838cc72361SWai Yew CHAY } 15848cc72361SWai Yew CHAY 15858cc72361SWai Yew CHAY 15868cc72361SWai Yew CHAY static int 15878cc72361SWai Yew CHAY adc_input_select_SBx(struct hw *hw, enum ADCSRC type, unsigned char boost) 15888cc72361SWai Yew CHAY { 1589514eef9cSTakashi Iwai u32 data; 1590514eef9cSTakashi Iwai u32 i2c_data; 1591514eef9cSTakashi Iwai unsigned int ret; 15928cc72361SWai Yew CHAY 15938cc72361SWai Yew CHAY if (i2c_unlock(hw)) 15948cc72361SWai Yew CHAY return -1; 15958cc72361SWai Yew CHAY 15968cc72361SWai Yew CHAY do { 15978cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 15988cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 15998cc72361SWai Yew CHAY /* set i2c access mode as Direct Control */ 16008cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); 16018cc72361SWai Yew CHAY 16028cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 16038cc72361SWai Yew CHAY switch (type) { 16048cc72361SWai Yew CHAY case ADC_MICIN: 16058cc72361SWai Yew CHAY data |= ((0x1 << 7) | (0x1 << 8)); 16068cc72361SWai Yew CHAY i2c_data = 0x1; /* Mic-in */ 16078cc72361SWai Yew CHAY break; 16088cc72361SWai Yew CHAY case ADC_LINEIN: 16098cc72361SWai Yew CHAY data &= ~(0x1 << 7); 16108cc72361SWai Yew CHAY data |= (0x1 << 8); 16118cc72361SWai Yew CHAY i2c_data = 0x2; /* Line-in */ 16128cc72361SWai Yew CHAY break; 16138cc72361SWai Yew CHAY case ADC_NONE: 16148cc72361SWai Yew CHAY data &= ~(0x1 << 8); 16158cc72361SWai Yew CHAY i2c_data = 0x0; /* set to Digital */ 16168cc72361SWai Yew CHAY break; 16178cc72361SWai Yew CHAY default: 16188cc72361SWai Yew CHAY i2c_lock(hw); 16198cc72361SWai Yew CHAY return -1; 16208cc72361SWai Yew CHAY } 16218cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 16228cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 16238cc72361SWai Yew CHAY if (boost) { 16248cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 16258cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 16268cc72361SWai Yew CHAY } else { 16278cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 16288cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 16298cc72361SWai Yew CHAY } 16308cc72361SWai Yew CHAY 16318cc72361SWai Yew CHAY i2c_lock(hw); 16328cc72361SWai Yew CHAY 16338cc72361SWai Yew CHAY return 0; 16348cc72361SWai Yew CHAY } 16358cc72361SWai Yew CHAY 16368cc72361SWai Yew CHAY static int 16378cc72361SWai Yew CHAY adc_input_select_hendrix(struct hw *hw, enum ADCSRC type, unsigned char boost) 16388cc72361SWai Yew CHAY { 1639514eef9cSTakashi Iwai u32 data; 1640514eef9cSTakashi Iwai u32 i2c_data; 1641514eef9cSTakashi Iwai unsigned int ret; 16428cc72361SWai Yew CHAY 16438cc72361SWai Yew CHAY if (i2c_unlock(hw)) 16448cc72361SWai Yew CHAY return -1; 16458cc72361SWai Yew CHAY 16468cc72361SWai Yew CHAY do { 16478cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 16488cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 16498cc72361SWai Yew CHAY /* set i2c access mode as Direct Control */ 16508cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); 16518cc72361SWai Yew CHAY 16528cc72361SWai Yew CHAY data = hw_read_20kx(hw, GPIO); 16538cc72361SWai Yew CHAY switch (type) { 16548cc72361SWai Yew CHAY case ADC_MICIN: 16558cc72361SWai Yew CHAY data |= (0x1 << 7); 16568cc72361SWai Yew CHAY i2c_data = 0x1; /* Mic-in */ 16578cc72361SWai Yew CHAY break; 16588cc72361SWai Yew CHAY case ADC_LINEIN: 16598cc72361SWai Yew CHAY data &= ~(0x1 << 7); 16608cc72361SWai Yew CHAY i2c_data = 0x2; /* Line-in */ 16618cc72361SWai Yew CHAY break; 16628cc72361SWai Yew CHAY default: 16638cc72361SWai Yew CHAY i2c_lock(hw); 16648cc72361SWai Yew CHAY return -1; 16658cc72361SWai Yew CHAY } 16668cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, data); 16678cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 16688cc72361SWai Yew CHAY if (boost) { 16698cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 16708cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 16718cc72361SWai Yew CHAY } else { 16728cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 16738cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 16748cc72361SWai Yew CHAY } 16758cc72361SWai Yew CHAY 16768cc72361SWai Yew CHAY i2c_lock(hw); 16778cc72361SWai Yew CHAY 16788cc72361SWai Yew CHAY return 0; 16798cc72361SWai Yew CHAY } 16808cc72361SWai Yew CHAY 16818cc72361SWai Yew CHAY static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) 16828cc72361SWai Yew CHAY { 16839470195aSTakashi Iwai int state = type == ADC_MICIN; 16848cc72361SWai Yew CHAY 16859470195aSTakashi Iwai switch (hw->model) { 16869470195aSTakashi Iwai case CTSB055X: 16879470195aSTakashi Iwai return adc_input_select_SB055x(hw, type, state); 16889470195aSTakashi Iwai case CTSB073X: 16899470195aSTakashi Iwai return adc_input_select_hendrix(hw, type, state); 169009521d2eSTakashi Iwai case CTUAA: 16919470195aSTakashi Iwai return adc_input_select_hendrix(hw, type, state); 16929470195aSTakashi Iwai default: 16939470195aSTakashi Iwai return adc_input_select_SBx(hw, type, state); 16948cc72361SWai Yew CHAY } 16958cc72361SWai Yew CHAY } 16968cc72361SWai Yew CHAY 16978cc72361SWai Yew CHAY static int adc_init_SB055x(struct hw *hw, int input, int mic20db) 16988cc72361SWai Yew CHAY { 16998cc72361SWai Yew CHAY return adc_input_select_SB055x(hw, input, mic20db); 17008cc72361SWai Yew CHAY } 17018cc72361SWai Yew CHAY 17028cc72361SWai Yew CHAY static int adc_init_SBx(struct hw *hw, int input, int mic20db) 17038cc72361SWai Yew CHAY { 17048cc72361SWai Yew CHAY u16 gpioorg; 17058cc72361SWai Yew CHAY u16 input_source; 1706514eef9cSTakashi Iwai u32 adcdata; 1707514eef9cSTakashi Iwai unsigned int ret; 17088cc72361SWai Yew CHAY 17098cc72361SWai Yew CHAY input_source = 0x100; /* default to analog */ 17108cc72361SWai Yew CHAY switch (input) { 17118cc72361SWai Yew CHAY case ADC_MICIN: 17128cc72361SWai Yew CHAY adcdata = 0x1; 17138cc72361SWai Yew CHAY input_source = 0x180; /* set GPIO7 to select Mic */ 17148cc72361SWai Yew CHAY break; 17158cc72361SWai Yew CHAY case ADC_LINEIN: 17168cc72361SWai Yew CHAY adcdata = 0x2; 17178cc72361SWai Yew CHAY break; 17188cc72361SWai Yew CHAY case ADC_VIDEO: 17198cc72361SWai Yew CHAY adcdata = 0x4; 17208cc72361SWai Yew CHAY break; 17218cc72361SWai Yew CHAY case ADC_AUX: 17228cc72361SWai Yew CHAY adcdata = 0x8; 17238cc72361SWai Yew CHAY break; 17248cc72361SWai Yew CHAY case ADC_NONE: 17258cc72361SWai Yew CHAY adcdata = 0x0; 17268cc72361SWai Yew CHAY input_source = 0x0; /* set to Digital */ 17278cc72361SWai Yew CHAY break; 17288cc72361SWai Yew CHAY default: 1729514eef9cSTakashi Iwai adcdata = 0x0; 17308cc72361SWai Yew CHAY break; 17318cc72361SWai Yew CHAY } 17328cc72361SWai Yew CHAY 17338cc72361SWai Yew CHAY if (i2c_unlock(hw)) 17348cc72361SWai Yew CHAY return -1; 17358cc72361SWai Yew CHAY 17368cc72361SWai Yew CHAY do { 17378cc72361SWai Yew CHAY ret = hw_read_pci(hw, 0xEC); 17388cc72361SWai Yew CHAY } while (!(ret & 0x800000)); /* i2c ready poll */ 17398cc72361SWai Yew CHAY hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 17408cc72361SWai Yew CHAY 17418cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x0e, 0x08); 17428cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x18, 0x0a); 17438cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x28, 0x86); 17448cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x2a, adcdata); 17458cc72361SWai Yew CHAY 17468cc72361SWai Yew CHAY if (mic20db) { 17478cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xf7); 17488cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xf7); 17498cc72361SWai Yew CHAY } else { 17508cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1c, 0xcf); 17518cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x1e, 0xcf); 17528cc72361SWai Yew CHAY } 17538cc72361SWai Yew CHAY 17548cc72361SWai Yew CHAY if (!(hw_read_20kx(hw, ID0) & 0x100)) 17558cc72361SWai Yew CHAY i2c_write(hw, 0x001a0080, 0x16, 0x26); 17568cc72361SWai Yew CHAY 17578cc72361SWai Yew CHAY i2c_lock(hw); 17588cc72361SWai Yew CHAY 17598cc72361SWai Yew CHAY gpioorg = (u16)hw_read_20kx(hw, GPIO); 17608cc72361SWai Yew CHAY gpioorg &= 0xfe7f; 17618cc72361SWai Yew CHAY gpioorg |= input_source; 17628cc72361SWai Yew CHAY hw_write_20kx(hw, GPIO, gpioorg); 17638cc72361SWai Yew CHAY 17648cc72361SWai Yew CHAY return 0; 17658cc72361SWai Yew CHAY } 17668cc72361SWai Yew CHAY 17678cc72361SWai Yew CHAY static int hw_adc_init(struct hw *hw, const struct adc_conf *info) 17688cc72361SWai Yew CHAY { 17699470195aSTakashi Iwai if (hw->model == CTSB055X) 17709470195aSTakashi Iwai return adc_init_SB055x(hw, info->input, info->mic20db); 17719470195aSTakashi Iwai else 17729470195aSTakashi Iwai return adc_init_SBx(hw, info->input, info->mic20db); 17738cc72361SWai Yew CHAY } 17748cc72361SWai Yew CHAY 1775b028b818SHarry Butterworth static struct capabilities hw_capabilities(struct hw *hw) 17768cc72361SWai Yew CHAY { 1777b028b818SHarry Butterworth struct capabilities cap; 1778b028b818SHarry Butterworth 17798cc72361SWai Yew CHAY /* SB073x and Vista compatible cards have no digit IO switch */ 1780b028b818SHarry Butterworth cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); 1781b028b818SHarry Butterworth cap.dedicated_mic = 0; 1782b028b818SHarry Butterworth cap.output_switch = 0; 1783b028b818SHarry Butterworth cap.mic_source_switch = 0; 17848cc72361SWai Yew CHAY 1785b028b818SHarry Butterworth return cap; 178655309216SHarry Butterworth } 178755309216SHarry Butterworth 178842a0b318STakashi Iwai #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) 178942a0b318STakashi Iwai 17908cc72361SWai Yew CHAY #define UAA_CFG_PWRSTATUS 0x44 17918cc72361SWai Yew CHAY #define UAA_CFG_SPACE_FLAG 0xA0 17928cc72361SWai Yew CHAY #define UAA_CORE_CHANGE 0x3FFC 17938cc72361SWai Yew CHAY static int uaa_to_xfi(struct pci_dev *pci) 17948cc72361SWai Yew CHAY { 17958cc72361SWai Yew CHAY unsigned int bar0, bar1, bar2, bar3, bar4, bar5; 17968cc72361SWai Yew CHAY unsigned int cmd, irq, cl_size, l_timer, pwr; 1797514eef9cSTakashi Iwai unsigned int is_uaa; 17988cc72361SWai Yew CHAY unsigned int data[4] = {0}; 17998cc72361SWai Yew CHAY unsigned int io_base; 18007a7686bdSSudip Mukherjee void __iomem *mem_base; 1801514eef9cSTakashi Iwai int i; 180242a0b318STakashi Iwai const u32 CTLX = CTLBITS('C', 'T', 'L', 'X'); 180342a0b318STakashi Iwai const u32 CTL_ = CTLBITS('C', 'T', 'L', '-'); 180442a0b318STakashi Iwai const u32 CTLF = CTLBITS('C', 'T', 'L', 'F'); 180542a0b318STakashi Iwai const u32 CTLi = CTLBITS('C', 'T', 'L', 'i'); 180642a0b318STakashi Iwai const u32 CTLA = CTLBITS('C', 'T', 'L', 'A'); 180742a0b318STakashi Iwai const u32 CTLZ = CTLBITS('C', 'T', 'L', 'Z'); 180842a0b318STakashi Iwai const u32 CTLL = CTLBITS('C', 'T', 'L', 'L'); 18098cc72361SWai Yew CHAY 18108cc72361SWai Yew CHAY /* By default, Hendrix card UAA Bar0 should be using memory... */ 18118cc72361SWai Yew CHAY io_base = pci_resource_start(pci, 0); 18128cc72361SWai Yew CHAY mem_base = ioremap(io_base, pci_resource_len(pci, 0)); 181335ebf6e7STakashi Iwai if (!mem_base) 18148cc72361SWai Yew CHAY return -ENOENT; 18158cc72361SWai Yew CHAY 18168cc72361SWai Yew CHAY /* Read current mode from Mode Change Register */ 18178cc72361SWai Yew CHAY for (i = 0; i < 4; i++) 18188cc72361SWai Yew CHAY data[i] = readl(mem_base + UAA_CORE_CHANGE); 18198cc72361SWai Yew CHAY 18208cc72361SWai Yew CHAY /* Determine current mode... */ 18218cc72361SWai Yew CHAY if (data[0] == CTLA) { 18228cc72361SWai Yew CHAY is_uaa = ((data[1] == CTLZ && data[2] == CTLL 18238cc72361SWai Yew CHAY && data[3] == CTLA) || (data[1] == CTLA 18248cc72361SWai Yew CHAY && data[2] == CTLZ && data[3] == CTLL)); 18258cc72361SWai Yew CHAY } else if (data[0] == CTLZ) { 18268cc72361SWai Yew CHAY is_uaa = (data[1] == CTLL 18278cc72361SWai Yew CHAY && data[2] == CTLA && data[3] == CTLA); 18288cc72361SWai Yew CHAY } else if (data[0] == CTLL) { 18298cc72361SWai Yew CHAY is_uaa = (data[1] == CTLA 18308cc72361SWai Yew CHAY && data[2] == CTLA && data[3] == CTLZ); 18318cc72361SWai Yew CHAY } else { 18328cc72361SWai Yew CHAY is_uaa = 0; 18338cc72361SWai Yew CHAY } 18348cc72361SWai Yew CHAY 18358cc72361SWai Yew CHAY if (!is_uaa) { 18368cc72361SWai Yew CHAY /* Not in UAA mode currently. Return directly. */ 18378cc72361SWai Yew CHAY iounmap(mem_base); 18388cc72361SWai Yew CHAY return 0; 18398cc72361SWai Yew CHAY } 18408cc72361SWai Yew CHAY 18418cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_0, &bar0); 18428cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_1, &bar1); 18438cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_2, &bar2); 18448cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_3, &bar3); 18458cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_4, &bar4); 18468cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_BASE_ADDRESS_5, &bar5); 18478cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_INTERRUPT_LINE, &irq); 18488cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_CACHE_LINE_SIZE, &cl_size); 18498cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_LATENCY_TIMER, &l_timer); 18508cc72361SWai Yew CHAY pci_read_config_dword(pci, UAA_CFG_PWRSTATUS, &pwr); 18518cc72361SWai Yew CHAY pci_read_config_dword(pci, PCI_COMMAND, &cmd); 18528cc72361SWai Yew CHAY 18538cc72361SWai Yew CHAY /* Set up X-Fi core PCI configuration space. */ 18548cc72361SWai Yew CHAY /* Switch to X-Fi config space with BAR0 exposed. */ 18558cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x87654321); 18568cc72361SWai Yew CHAY /* Copy UAA's BAR5 into X-Fi BAR0 */ 18578cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_0, bar5); 18588cc72361SWai Yew CHAY /* Switch to X-Fi config space without BAR0 exposed. */ 18598cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x12345678); 18608cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, bar1); 18618cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_2, bar2); 18628cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_3, bar3); 18638cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_BASE_ADDRESS_4, bar4); 18648cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_INTERRUPT_LINE, irq); 18658cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_CACHE_LINE_SIZE, cl_size); 18668cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_LATENCY_TIMER, l_timer); 18678cc72361SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_PWRSTATUS, pwr); 18688cc72361SWai Yew CHAY pci_write_config_dword(pci, PCI_COMMAND, cmd); 18698cc72361SWai Yew CHAY 18708cc72361SWai Yew CHAY /* Switch to X-Fi mode */ 18718cc72361SWai Yew CHAY writel(CTLX, (mem_base + UAA_CORE_CHANGE)); 18728cc72361SWai Yew CHAY writel(CTL_, (mem_base + UAA_CORE_CHANGE)); 18738cc72361SWai Yew CHAY writel(CTLF, (mem_base + UAA_CORE_CHANGE)); 18748cc72361SWai Yew CHAY writel(CTLi, (mem_base + UAA_CORE_CHANGE)); 18758cc72361SWai Yew CHAY 18768cc72361SWai Yew CHAY iounmap(mem_base); 18778cc72361SWai Yew CHAY 18788cc72361SWai Yew CHAY return 0; 18798cc72361SWai Yew CHAY } 18808cc72361SWai Yew CHAY 1881b7bbf876STakashi Iwai static irqreturn_t ct_20k1_interrupt(int irq, void *dev_id) 1882b7bbf876STakashi Iwai { 1883b7bbf876STakashi Iwai struct hw *hw = dev_id; 1884b7bbf876STakashi Iwai unsigned int status; 1885b7bbf876STakashi Iwai 1886b7bbf876STakashi Iwai status = hw_read_20kx(hw, GIP); 1887b7bbf876STakashi Iwai if (!status) 1888b7bbf876STakashi Iwai return IRQ_NONE; 1889b7bbf876STakashi Iwai 1890b7bbf876STakashi Iwai if (hw->irq_callback) 1891b7bbf876STakashi Iwai hw->irq_callback(hw->irq_callback_data, status); 1892b7bbf876STakashi Iwai 1893b7bbf876STakashi Iwai hw_write_20kx(hw, GIP, status); 1894b7bbf876STakashi Iwai return IRQ_HANDLED; 1895b7bbf876STakashi Iwai } 1896b7bbf876STakashi Iwai 18978cc72361SWai Yew CHAY static int hw_card_start(struct hw *hw) 18988cc72361SWai Yew CHAY { 1899514eef9cSTakashi Iwai int err; 19008cc72361SWai Yew CHAY struct pci_dev *pci = hw->pci; 190115c75b09STakashi Iwai const unsigned int dma_bits = BITS_PER_LONG; 19028cc72361SWai Yew CHAY 19038cc72361SWai Yew CHAY err = pci_enable_device(pci); 19048cc72361SWai Yew CHAY if (err < 0) 19058cc72361SWai Yew CHAY return err; 19068cc72361SWai Yew CHAY 19078cc72361SWai Yew CHAY /* Set DMA transfer mask */ 1908*f363a066STakashi Iwai if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { 190915c75b09STakashi Iwai dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); 191015c75b09STakashi Iwai } else { 191115c75b09STakashi Iwai dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); 191215c75b09STakashi Iwai dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); 19138cc72361SWai Yew CHAY } 19148cc72361SWai Yew CHAY 191529959a09SWai Yew CHAY if (!hw->io_base) { 19168cc72361SWai Yew CHAY err = pci_request_regions(pci, "XFi"); 19178cc72361SWai Yew CHAY if (err < 0) 19188cc72361SWai Yew CHAY goto error1; 19198cc72361SWai Yew CHAY 192029959a09SWai Yew CHAY if (hw->model == CTUAA) 192129959a09SWai Yew CHAY hw->io_base = pci_resource_start(pci, 5); 192229959a09SWai Yew CHAY else 192329959a09SWai Yew CHAY hw->io_base = pci_resource_start(pci, 0); 192429959a09SWai Yew CHAY 192529959a09SWai Yew CHAY } 192629959a09SWai Yew CHAY 19278cc72361SWai Yew CHAY /* Switch to X-Fi mode from UAA mode if neeeded */ 192809521d2eSTakashi Iwai if (hw->model == CTUAA) { 19298cc72361SWai Yew CHAY err = uaa_to_xfi(pci); 19308cc72361SWai Yew CHAY if (err) 19318cc72361SWai Yew CHAY goto error2; 19328cc72361SWai Yew CHAY 19338cc72361SWai Yew CHAY } 19348cc72361SWai Yew CHAY 193529959a09SWai Yew CHAY if (hw->irq < 0) { 1936b7bbf876STakashi Iwai err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, 1937934c2b6dSTakashi Iwai KBUILD_MODNAME, hw); 1938b7bbf876STakashi Iwai if (err < 0) { 19390cae90a9SSudip Mukherjee dev_err(hw->card->dev, 19400cae90a9SSudip Mukherjee "XFi: Cannot get irq %d\n", pci->irq); 19418cc72361SWai Yew CHAY goto error2; 19428cc72361SWai Yew CHAY } 19438cc72361SWai Yew CHAY hw->irq = pci->irq; 194429959a09SWai Yew CHAY } 19458cc72361SWai Yew CHAY 19468cc72361SWai Yew CHAY pci_set_master(pci); 19478cc72361SWai Yew CHAY 19488cc72361SWai Yew CHAY return 0; 19498cc72361SWai Yew CHAY 19508cc72361SWai Yew CHAY error2: 19518cc72361SWai Yew CHAY pci_release_regions(pci); 19528cc72361SWai Yew CHAY hw->io_base = 0; 19538cc72361SWai Yew CHAY error1: 19548cc72361SWai Yew CHAY pci_disable_device(pci); 19558cc72361SWai Yew CHAY return err; 19568cc72361SWai Yew CHAY } 19578cc72361SWai Yew CHAY 19588cc72361SWai Yew CHAY static int hw_card_stop(struct hw *hw) 19598cc72361SWai Yew CHAY { 196029959a09SWai Yew CHAY unsigned int data; 196129959a09SWai Yew CHAY 196229959a09SWai Yew CHAY /* disable transport bus master and queueing of request */ 196329959a09SWai Yew CHAY hw_write_20kx(hw, TRNCTL, 0x00); 196429959a09SWai Yew CHAY 196529959a09SWai Yew CHAY /* disable pll */ 196629959a09SWai Yew CHAY data = hw_read_20kx(hw, PLLCTL); 196729959a09SWai Yew CHAY hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12)))); 196829959a09SWai Yew CHAY 19698cc72361SWai Yew CHAY /* TODO: Disable interrupt and so on... */ 1970b7bbf876STakashi Iwai if (hw->irq >= 0) 1971b7bbf876STakashi Iwai synchronize_irq(hw->irq); 19728cc72361SWai Yew CHAY return 0; 19738cc72361SWai Yew CHAY } 19748cc72361SWai Yew CHAY 19758cc72361SWai Yew CHAY static int hw_card_shutdown(struct hw *hw) 19768cc72361SWai Yew CHAY { 19778cc72361SWai Yew CHAY if (hw->irq >= 0) 19788cc72361SWai Yew CHAY free_irq(hw->irq, hw); 19798cc72361SWai Yew CHAY 19808cc72361SWai Yew CHAY hw->irq = -1; 19817a7686bdSSudip Mukherjee iounmap(hw->mem_base); 19827a7686bdSSudip Mukherjee hw->mem_base = NULL; 19838cc72361SWai Yew CHAY 19848cc72361SWai Yew CHAY if (hw->io_base) 19858cc72361SWai Yew CHAY pci_release_regions(hw->pci); 19868cc72361SWai Yew CHAY 19878cc72361SWai Yew CHAY hw->io_base = 0; 19888cc72361SWai Yew CHAY 19898cc72361SWai Yew CHAY pci_disable_device(hw->pci); 19908cc72361SWai Yew CHAY 19918cc72361SWai Yew CHAY return 0; 19928cc72361SWai Yew CHAY } 19938cc72361SWai Yew CHAY 19948cc72361SWai Yew CHAY static int hw_card_init(struct hw *hw, struct card_conf *info) 19958cc72361SWai Yew CHAY { 19968cc72361SWai Yew CHAY int err; 19978cc72361SWai Yew CHAY unsigned int gctl; 1998514eef9cSTakashi Iwai u32 data; 19998cc72361SWai Yew CHAY struct dac_conf dac_info = {0}; 20008cc72361SWai Yew CHAY struct adc_conf adc_info = {0}; 20018cc72361SWai Yew CHAY struct daio_conf daio_info = {0}; 20028cc72361SWai Yew CHAY struct trn_conf trn_info = {0}; 20038cc72361SWai Yew CHAY 20048cc72361SWai Yew CHAY /* Get PCI io port base address and do Hendrix switch if needed. */ 20058cc72361SWai Yew CHAY err = hw_card_start(hw); 20068cc72361SWai Yew CHAY if (err) 20078cc72361SWai Yew CHAY return err; 20088cc72361SWai Yew CHAY 20098cc72361SWai Yew CHAY /* PLL init */ 20108cc72361SWai Yew CHAY err = hw_pll_init(hw, info->rsr); 20118cc72361SWai Yew CHAY if (err < 0) 20128cc72361SWai Yew CHAY return err; 20138cc72361SWai Yew CHAY 20148cc72361SWai Yew CHAY /* kick off auto-init */ 20158cc72361SWai Yew CHAY err = hw_auto_init(hw); 20168cc72361SWai Yew CHAY if (err < 0) 20178cc72361SWai Yew CHAY return err; 20188cc72361SWai Yew CHAY 20198cc72361SWai Yew CHAY /* Enable audio ring */ 20208cc72361SWai Yew CHAY gctl = hw_read_20kx(hw, GCTL); 20218cc72361SWai Yew CHAY set_field(&gctl, GCTL_EAC, 1); 20228cc72361SWai Yew CHAY set_field(&gctl, GCTL_DBP, 1); 20238cc72361SWai Yew CHAY set_field(&gctl, GCTL_TBP, 1); 20248cc72361SWai Yew CHAY set_field(&gctl, GCTL_FBP, 1); 20258cc72361SWai Yew CHAY set_field(&gctl, GCTL_ET, 1); 20268cc72361SWai Yew CHAY hw_write_20kx(hw, GCTL, gctl); 20278cc72361SWai Yew CHAY mdelay(10); 20288cc72361SWai Yew CHAY 20298cc72361SWai Yew CHAY /* Reset all global pending interrupts */ 20308cc72361SWai Yew CHAY hw_write_20kx(hw, GIE, 0); 20318cc72361SWai Yew CHAY /* Reset all SRC pending interrupts */ 20328cc72361SWai Yew CHAY hw_write_20kx(hw, SRCIP, 0); 20338cc72361SWai Yew CHAY mdelay(30); 20348cc72361SWai Yew CHAY 20358cc72361SWai Yew CHAY /* Detect the card ID and configure GPIO accordingly. */ 20369470195aSTakashi Iwai switch (hw->model) { 20379470195aSTakashi Iwai case CTSB055X: 20388cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x13fe); 20399470195aSTakashi Iwai break; 20409470195aSTakashi Iwai case CTSB073X: 20418cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x00e6); 20429470195aSTakashi Iwai break; 204309521d2eSTakashi Iwai case CTUAA: 20448cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x00c2); 20459470195aSTakashi Iwai break; 20469470195aSTakashi Iwai default: 20478cc72361SWai Yew CHAY hw_write_20kx(hw, GPIOCTL, 0x01e6); 20489470195aSTakashi Iwai break; 20498cc72361SWai Yew CHAY } 20508cc72361SWai Yew CHAY 20518cc72361SWai Yew CHAY trn_info.vm_pgt_phys = info->vm_pgt_phys; 20528cc72361SWai Yew CHAY err = hw_trn_init(hw, &trn_info); 20538cc72361SWai Yew CHAY if (err < 0) 20548cc72361SWai Yew CHAY return err; 20558cc72361SWai Yew CHAY 20568cc72361SWai Yew CHAY daio_info.msr = info->msr; 20578cc72361SWai Yew CHAY err = hw_daio_init(hw, &daio_info); 20588cc72361SWai Yew CHAY if (err < 0) 20598cc72361SWai Yew CHAY return err; 20608cc72361SWai Yew CHAY 20618cc72361SWai Yew CHAY dac_info.msr = info->msr; 20628cc72361SWai Yew CHAY err = hw_dac_init(hw, &dac_info); 20638cc72361SWai Yew CHAY if (err < 0) 20648cc72361SWai Yew CHAY return err; 20658cc72361SWai Yew CHAY 20668cc72361SWai Yew CHAY adc_info.msr = info->msr; 20678cc72361SWai Yew CHAY adc_info.input = ADC_LINEIN; 20688cc72361SWai Yew CHAY adc_info.mic20db = 0; 20698cc72361SWai Yew CHAY err = hw_adc_init(hw, &adc_info); 20708cc72361SWai Yew CHAY if (err < 0) 20718cc72361SWai Yew CHAY return err; 20728cc72361SWai Yew CHAY 20738cc72361SWai Yew CHAY data = hw_read_20kx(hw, SRCMCTL); 20748cc72361SWai Yew CHAY data |= 0x1; /* Enables input from the audio ring */ 20758cc72361SWai Yew CHAY hw_write_20kx(hw, SRCMCTL, data); 20768cc72361SWai Yew CHAY 20778cc72361SWai Yew CHAY return 0; 20788cc72361SWai Yew CHAY } 20798cc72361SWai Yew CHAY 2080c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP 208168cb2b55STakashi Iwai static int hw_suspend(struct hw *hw) 208229959a09SWai Yew CHAY { 208329959a09SWai Yew CHAY struct pci_dev *pci = hw->pci; 208429959a09SWai Yew CHAY 208529959a09SWai Yew CHAY hw_card_stop(hw); 208629959a09SWai Yew CHAY 208729959a09SWai Yew CHAY if (hw->model == CTUAA) { 208829959a09SWai Yew CHAY /* Switch to UAA config space. */ 208929959a09SWai Yew CHAY pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); 209029959a09SWai Yew CHAY } 209129959a09SWai Yew CHAY 209229959a09SWai Yew CHAY return 0; 209329959a09SWai Yew CHAY } 209429959a09SWai Yew CHAY 209529959a09SWai Yew CHAY static int hw_resume(struct hw *hw, struct card_conf *info) 209629959a09SWai Yew CHAY { 209729959a09SWai Yew CHAY /* Re-initialize card hardware. */ 209829959a09SWai Yew CHAY return hw_card_init(hw, info); 209929959a09SWai Yew CHAY } 210029959a09SWai Yew CHAY #endif 210129959a09SWai Yew CHAY 21028cc72361SWai Yew CHAY static u32 hw_read_20kx(struct hw *hw, u32 reg) 21038cc72361SWai Yew CHAY { 21048cc72361SWai Yew CHAY u32 value; 21058cc72361SWai Yew CHAY unsigned long flags; 21068cc72361SWai Yew CHAY 21078cc72361SWai Yew CHAY spin_lock_irqsave( 21088cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21098cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x0); 21108cc72361SWai Yew CHAY value = inl(hw->io_base + 0x4); 21118cc72361SWai Yew CHAY spin_unlock_irqrestore( 21128cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21138cc72361SWai Yew CHAY 21148cc72361SWai Yew CHAY return value; 21158cc72361SWai Yew CHAY } 21168cc72361SWai Yew CHAY 21178cc72361SWai Yew CHAY static void hw_write_20kx(struct hw *hw, u32 reg, u32 data) 21188cc72361SWai Yew CHAY { 21198cc72361SWai Yew CHAY unsigned long flags; 21208cc72361SWai Yew CHAY 21218cc72361SWai Yew CHAY spin_lock_irqsave( 21228cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21238cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x0); 21248cc72361SWai Yew CHAY outl(data, hw->io_base + 0x4); 21258cc72361SWai Yew CHAY spin_unlock_irqrestore( 21268cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 21278cc72361SWai Yew CHAY 21288cc72361SWai Yew CHAY } 21298cc72361SWai Yew CHAY 21308cc72361SWai Yew CHAY static u32 hw_read_pci(struct hw *hw, u32 reg) 21318cc72361SWai Yew CHAY { 21328cc72361SWai Yew CHAY u32 value; 21338cc72361SWai Yew CHAY unsigned long flags; 21348cc72361SWai Yew CHAY 21358cc72361SWai Yew CHAY spin_lock_irqsave( 21368cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21378cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x10); 21388cc72361SWai Yew CHAY value = inl(hw->io_base + 0x14); 21398cc72361SWai Yew CHAY spin_unlock_irqrestore( 21408cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21418cc72361SWai Yew CHAY 21428cc72361SWai Yew CHAY return value; 21438cc72361SWai Yew CHAY } 21448cc72361SWai Yew CHAY 21458cc72361SWai Yew CHAY static void hw_write_pci(struct hw *hw, u32 reg, u32 data) 21468cc72361SWai Yew CHAY { 21478cc72361SWai Yew CHAY unsigned long flags; 21488cc72361SWai Yew CHAY 21498cc72361SWai Yew CHAY spin_lock_irqsave( 21508cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21518cc72361SWai Yew CHAY outl(reg, hw->io_base + 0x10); 21528cc72361SWai Yew CHAY outl(data, hw->io_base + 0x14); 21538cc72361SWai Yew CHAY spin_unlock_irqrestore( 21548cc72361SWai Yew CHAY &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 21558cc72361SWai Yew CHAY } 21568cc72361SWai Yew CHAY 2157e23e7a14SBill Pemberton static struct hw ct20k1_preset = { 21582a36f67fSTakashi Iwai .irq = -1, 21592a36f67fSTakashi Iwai 21602a36f67fSTakashi Iwai .card_init = hw_card_init, 21612a36f67fSTakashi Iwai .card_stop = hw_card_stop, 21622a36f67fSTakashi Iwai .pll_init = hw_pll_init, 21632a36f67fSTakashi Iwai .is_adc_source_selected = hw_is_adc_input_selected, 21642a36f67fSTakashi Iwai .select_adc_source = hw_adc_input_select, 2165b028b818SHarry Butterworth .capabilities = hw_capabilities, 2166c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP 216729959a09SWai Yew CHAY .suspend = hw_suspend, 216829959a09SWai Yew CHAY .resume = hw_resume, 216929959a09SWai Yew CHAY #endif 21702a36f67fSTakashi Iwai 21712a36f67fSTakashi Iwai .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, 21722a36f67fSTakashi Iwai .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, 21732a36f67fSTakashi Iwai .src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk, 21742a36f67fSTakashi Iwai .src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk, 21752a36f67fSTakashi Iwai .src_set_state = src_set_state, 21762a36f67fSTakashi Iwai .src_set_bm = src_set_bm, 21772a36f67fSTakashi Iwai .src_set_rsr = src_set_rsr, 21782a36f67fSTakashi Iwai .src_set_sf = src_set_sf, 21792a36f67fSTakashi Iwai .src_set_wr = src_set_wr, 21802a36f67fSTakashi Iwai .src_set_pm = src_set_pm, 21812a36f67fSTakashi Iwai .src_set_rom = src_set_rom, 21822a36f67fSTakashi Iwai .src_set_vo = src_set_vo, 21832a36f67fSTakashi Iwai .src_set_st = src_set_st, 21842a36f67fSTakashi Iwai .src_set_ie = src_set_ie, 21852a36f67fSTakashi Iwai .src_set_ilsz = src_set_ilsz, 21862a36f67fSTakashi Iwai .src_set_bp = src_set_bp, 21872a36f67fSTakashi Iwai .src_set_cisz = src_set_cisz, 21882a36f67fSTakashi Iwai .src_set_ca = src_set_ca, 21892a36f67fSTakashi Iwai .src_set_sa = src_set_sa, 21902a36f67fSTakashi Iwai .src_set_la = src_set_la, 21912a36f67fSTakashi Iwai .src_set_pitch = src_set_pitch, 21922a36f67fSTakashi Iwai .src_set_dirty = src_set_dirty, 21932a36f67fSTakashi Iwai .src_set_clear_zbufs = src_set_clear_zbufs, 21942a36f67fSTakashi Iwai .src_set_dirty_all = src_set_dirty_all, 21952a36f67fSTakashi Iwai .src_commit_write = src_commit_write, 21962a36f67fSTakashi Iwai .src_get_ca = src_get_ca, 21972a36f67fSTakashi Iwai .src_get_dirty = src_get_dirty, 21982a36f67fSTakashi Iwai .src_dirty_conj_mask = src_dirty_conj_mask, 21992a36f67fSTakashi Iwai .src_mgr_enbs_src = src_mgr_enbs_src, 22002a36f67fSTakashi Iwai .src_mgr_enb_src = src_mgr_enb_src, 22012a36f67fSTakashi Iwai .src_mgr_dsb_src = src_mgr_dsb_src, 22022a36f67fSTakashi Iwai .src_mgr_commit_write = src_mgr_commit_write, 22032a36f67fSTakashi Iwai 22042a36f67fSTakashi Iwai .srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk, 22052a36f67fSTakashi Iwai .srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk, 22062a36f67fSTakashi Iwai .srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc, 22072a36f67fSTakashi Iwai .srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser, 22082a36f67fSTakashi Iwai .srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt, 22092a36f67fSTakashi Iwai .srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr, 22102a36f67fSTakashi Iwai .srcimp_mgr_commit_write = srcimp_mgr_commit_write, 22112a36f67fSTakashi Iwai 22122a36f67fSTakashi Iwai .amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk, 22132a36f67fSTakashi Iwai .amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk, 22142a36f67fSTakashi Iwai .amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk, 22152a36f67fSTakashi Iwai .amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk, 22162a36f67fSTakashi Iwai .amixer_set_mode = amixer_set_mode, 22172a36f67fSTakashi Iwai .amixer_set_iv = amixer_set_iv, 22182a36f67fSTakashi Iwai .amixer_set_x = amixer_set_x, 22192a36f67fSTakashi Iwai .amixer_set_y = amixer_set_y, 22202a36f67fSTakashi Iwai .amixer_set_sadr = amixer_set_sadr, 22212a36f67fSTakashi Iwai .amixer_set_se = amixer_set_se, 22222a36f67fSTakashi Iwai .amixer_set_dirty = amixer_set_dirty, 22232a36f67fSTakashi Iwai .amixer_set_dirty_all = amixer_set_dirty_all, 22242a36f67fSTakashi Iwai .amixer_commit_write = amixer_commit_write, 22252a36f67fSTakashi Iwai .amixer_get_y = amixer_get_y, 22262a36f67fSTakashi Iwai .amixer_get_dirty = amixer_get_dirty, 22272a36f67fSTakashi Iwai 22282a36f67fSTakashi Iwai .dai_get_ctrl_blk = dai_get_ctrl_blk, 22292a36f67fSTakashi Iwai .dai_put_ctrl_blk = dai_put_ctrl_blk, 22302a36f67fSTakashi Iwai .dai_srt_set_srco = dai_srt_set_srcr, 22312a36f67fSTakashi Iwai .dai_srt_set_srcm = dai_srt_set_srcl, 22322a36f67fSTakashi Iwai .dai_srt_set_rsr = dai_srt_set_rsr, 22332a36f67fSTakashi Iwai .dai_srt_set_drat = dai_srt_set_drat, 22342a36f67fSTakashi Iwai .dai_srt_set_ec = dai_srt_set_ec, 22352a36f67fSTakashi Iwai .dai_srt_set_et = dai_srt_set_et, 22362a36f67fSTakashi Iwai .dai_commit_write = dai_commit_write, 22372a36f67fSTakashi Iwai 22382a36f67fSTakashi Iwai .dao_get_ctrl_blk = dao_get_ctrl_blk, 22392a36f67fSTakashi Iwai .dao_put_ctrl_blk = dao_put_ctrl_blk, 22402a36f67fSTakashi Iwai .dao_set_spos = dao_set_spos, 22412a36f67fSTakashi Iwai .dao_commit_write = dao_commit_write, 22422a36f67fSTakashi Iwai .dao_get_spos = dao_get_spos, 22432a36f67fSTakashi Iwai 22442a36f67fSTakashi Iwai .daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk, 22452a36f67fSTakashi Iwai .daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk, 22462a36f67fSTakashi Iwai .daio_mgr_enb_dai = daio_mgr_enb_dai, 22472a36f67fSTakashi Iwai .daio_mgr_dsb_dai = daio_mgr_dsb_dai, 22482a36f67fSTakashi Iwai .daio_mgr_enb_dao = daio_mgr_enb_dao, 22492a36f67fSTakashi Iwai .daio_mgr_dsb_dao = daio_mgr_dsb_dao, 22502a36f67fSTakashi Iwai .daio_mgr_dao_init = daio_mgr_dao_init, 22512a36f67fSTakashi Iwai .daio_mgr_set_imaparc = daio_mgr_set_imaparc, 22522a36f67fSTakashi Iwai .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, 22532a36f67fSTakashi Iwai .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, 22542a36f67fSTakashi Iwai .daio_mgr_commit_write = daio_mgr_commit_write, 22552a36f67fSTakashi Iwai 22562a36f67fSTakashi Iwai .set_timer_irq = set_timer_irq, 22572a36f67fSTakashi Iwai .set_timer_tick = set_timer_tick, 225854de6bc8STakashi Iwai .get_wc = get_wc, 22592a36f67fSTakashi Iwai }; 22602a36f67fSTakashi Iwai 2261e23e7a14SBill Pemberton int create_20k1_hw_obj(struct hw **rhw) 22628cc72361SWai Yew CHAY { 22638cc72361SWai Yew CHAY struct hw20k1 *hw20k1; 22648cc72361SWai Yew CHAY 22658cc72361SWai Yew CHAY *rhw = NULL; 22668cc72361SWai Yew CHAY hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL); 226735ebf6e7STakashi Iwai if (!hw20k1) 22688cc72361SWai Yew CHAY return -ENOMEM; 22698cc72361SWai Yew CHAY 22708cc72361SWai Yew CHAY spin_lock_init(&hw20k1->reg_20k1_lock); 22718cc72361SWai Yew CHAY spin_lock_init(&hw20k1->reg_pci_lock); 22728cc72361SWai Yew CHAY 22732a36f67fSTakashi Iwai hw20k1->hw = ct20k1_preset; 22748cc72361SWai Yew CHAY 22752a36f67fSTakashi Iwai *rhw = &hw20k1->hw; 22768cc72361SWai Yew CHAY 22778cc72361SWai Yew CHAY return 0; 22788cc72361SWai Yew CHAY } 22798cc72361SWai Yew CHAY 22808cc72361SWai Yew CHAY int destroy_20k1_hw_obj(struct hw *hw) 22818cc72361SWai Yew CHAY { 22828cc72361SWai Yew CHAY if (hw->io_base) 22838cc72361SWai Yew CHAY hw_card_shutdown(hw); 22848cc72361SWai Yew CHAY 22858cc72361SWai Yew CHAY kfree(container_of(hw, struct hw20k1, hw)); 22868cc72361SWai Yew CHAY return 0; 22878cc72361SWai Yew CHAY } 2288