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