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