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 cthw20k2.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * @Brief 88c2ecf20Sopenharmony_ci * This file contains the implementation of hardware access method for 20k2. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * @Author Liu Chun 118c2ecf20Sopenharmony_ci * @Date May 14 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/kernel.h> 208c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 218c2ecf20Sopenharmony_ci#include <linux/delay.h> 228c2ecf20Sopenharmony_ci#include "cthw20k2.h" 238c2ecf20Sopenharmony_ci#include "ct20k2reg.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct hw20k2 { 268c2ecf20Sopenharmony_ci struct hw hw; 278c2ecf20Sopenharmony_ci /* for i2c */ 288c2ecf20Sopenharmony_ci unsigned char dev_id; 298c2ecf20Sopenharmony_ci unsigned char addr_size; 308c2ecf20Sopenharmony_ci unsigned char data_size; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci int mic_source; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic u32 hw_read_20kx(struct hw *hw, u32 reg); 368c2ecf20Sopenharmony_cistatic void hw_write_20kx(struct hw *hw, u32 reg, u32 data); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * Type definition block. 408c2ecf20Sopenharmony_ci * The layout of control structures can be directly applied on 20k2 chip. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * SRC control block definitions. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* SRC resource control block */ 488c2ecf20Sopenharmony_ci#define SRCCTL_STATE 0x00000007 498c2ecf20Sopenharmony_ci#define SRCCTL_BM 0x00000008 508c2ecf20Sopenharmony_ci#define SRCCTL_RSR 0x00000030 518c2ecf20Sopenharmony_ci#define SRCCTL_SF 0x000001C0 528c2ecf20Sopenharmony_ci#define SRCCTL_WR 0x00000200 538c2ecf20Sopenharmony_ci#define SRCCTL_PM 0x00000400 548c2ecf20Sopenharmony_ci#define SRCCTL_ROM 0x00001800 558c2ecf20Sopenharmony_ci#define SRCCTL_VO 0x00002000 568c2ecf20Sopenharmony_ci#define SRCCTL_ST 0x00004000 578c2ecf20Sopenharmony_ci#define SRCCTL_IE 0x00008000 588c2ecf20Sopenharmony_ci#define SRCCTL_ILSZ 0x000F0000 598c2ecf20Sopenharmony_ci#define SRCCTL_BP 0x00100000 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define SRCCCR_CISZ 0x000007FF 628c2ecf20Sopenharmony_ci#define SRCCCR_CWA 0x001FF800 638c2ecf20Sopenharmony_ci#define SRCCCR_D 0x00200000 648c2ecf20Sopenharmony_ci#define SRCCCR_RS 0x01C00000 658c2ecf20Sopenharmony_ci#define SRCCCR_NAL 0x3E000000 668c2ecf20Sopenharmony_ci#define SRCCCR_RA 0xC0000000 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define SRCCA_CA 0x0FFFFFFF 698c2ecf20Sopenharmony_ci#define SRCCA_RS 0xE0000000 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#define SRCSA_SA 0x0FFFFFFF 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define SRCLA_LA 0x0FFFFFFF 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, SRC_UPZ+idx*0x100+i*0x4, 0); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 3708c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_DN0Z+idx*0x100+i*0x4, 0); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 3738c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_DN1Z+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, MIXER_PRING_LO_HI+4*pm_idx, ctl->mpr); 3848c2ecf20Sopenharmony_ci hw_write_20kx(hw, MIXER_PMOPLO+8*pm_idx, 0x3); 3858c2ecf20Sopenharmony_ci hw_write_20kx(hw, MIXER_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, SRC_SA+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, SRC_LA+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, SRC_CA+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, SRC_CF+idx*0x100, 0x0); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci if (ctl->dirty.bf.ccr) { 4058c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_CCR+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, SRC_CTL+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, SRC_CA+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 |= (0x1 << ((idx%128)/4)); 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, SRC_ENBSTAT); 4678c2ecf20Sopenharmony_ci } while (ret & 0x1); 4688c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_ENBSA, 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, SRC_ENB+(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 *)blk)->srcimap.idx = addr; 5538c2ecf20Sopenharmony_ci ((struct srcimp_mgr_ctrl_blk *)blk)->dirty.bf.srcimap = 1; 5548c2ecf20Sopenharmony_ci return 0; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic int srcimp_mgr_commit_write(struct hw *hw, void *blk) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci struct srcimp_mgr_ctrl_blk *ctl = blk; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci if (ctl->dirty.bf.srcimap) { 5628c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_IMAP+ctl->srcimap.idx*0x100, 5638c2ecf20Sopenharmony_ci ctl->srcimap.srcaim); 5648c2ecf20Sopenharmony_ci ctl->dirty.bf.srcimap = 0; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci return 0; 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci/* 5718c2ecf20Sopenharmony_ci * AMIXER control block definitions. 5728c2ecf20Sopenharmony_ci */ 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci#define AMOPLO_M 0x00000003 5758c2ecf20Sopenharmony_ci#define AMOPLO_IV 0x00000004 5768c2ecf20Sopenharmony_ci#define AMOPLO_X 0x0003FFF0 5778c2ecf20Sopenharmony_ci#define AMOPLO_Y 0xFFFC0000 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci#define AMOPHI_SADR 0x000000FF 5808c2ecf20Sopenharmony_ci#define AMOPHI_SE 0x80000000 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci/* AMIXER resource register dirty flags */ 5838c2ecf20Sopenharmony_ciunion amixer_dirty { 5848c2ecf20Sopenharmony_ci struct { 5858c2ecf20Sopenharmony_ci u16 amoplo:1; 5868c2ecf20Sopenharmony_ci u16 amophi:1; 5878c2ecf20Sopenharmony_ci u16 rsv:14; 5888c2ecf20Sopenharmony_ci } bf; 5898c2ecf20Sopenharmony_ci u16 data; 5908c2ecf20Sopenharmony_ci}; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci/* AMIXER resource control block */ 5938c2ecf20Sopenharmony_cistruct amixer_rsc_ctrl_blk { 5948c2ecf20Sopenharmony_ci unsigned int amoplo; 5958c2ecf20Sopenharmony_ci unsigned int amophi; 5968c2ecf20Sopenharmony_ci union amixer_dirty dirty; 5978c2ecf20Sopenharmony_ci}; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistatic int amixer_set_mode(void *blk, unsigned int mode) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_M, mode); 6048c2ecf20Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 6058c2ecf20Sopenharmony_ci return 0; 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic int amixer_set_iv(void *blk, unsigned int iv) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_IV, iv); 6138c2ecf20Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic int amixer_set_x(void *blk, unsigned int x) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_X, x); 6228c2ecf20Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 6238c2ecf20Sopenharmony_ci return 0; 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cistatic int amixer_set_y(void *blk, unsigned int y) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_Y, y); 6318c2ecf20Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 6328c2ecf20Sopenharmony_ci return 0; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_cistatic int amixer_set_sadr(void *blk, unsigned int sadr) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci set_field(&ctl->amophi, AMOPHI_SADR, sadr); 6408c2ecf20Sopenharmony_ci ctl->dirty.bf.amophi = 1; 6418c2ecf20Sopenharmony_ci return 0; 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic int amixer_set_se(void *blk, unsigned int se) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci set_field(&ctl->amophi, AMOPHI_SE, se); 6498c2ecf20Sopenharmony_ci ctl->dirty.bf.amophi = 1; 6508c2ecf20Sopenharmony_ci return 0; 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic int amixer_set_dirty(void *blk, unsigned int flags) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 6568c2ecf20Sopenharmony_ci return 0; 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic int amixer_set_dirty_all(void *blk) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 6628c2ecf20Sopenharmony_ci return 0; 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_cistatic int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { 6708c2ecf20Sopenharmony_ci hw_write_20kx(hw, MIXER_AMOPLO+idx*8, ctl->amoplo); 6718c2ecf20Sopenharmony_ci ctl->dirty.bf.amoplo = 0; 6728c2ecf20Sopenharmony_ci hw_write_20kx(hw, MIXER_AMOPHI+idx*8, ctl->amophi); 6738c2ecf20Sopenharmony_ci ctl->dirty.bf.amophi = 0; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return 0; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic int amixer_get_y(void *blk) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci return get_field(ctl->amoplo, AMOPLO_Y); 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic unsigned int amixer_get_dirty(void *blk) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic int amixer_rsc_get_ctrl_blk(void **rblk) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci struct amixer_rsc_ctrl_blk *blk; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci *rblk = NULL; 6968c2ecf20Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 6978c2ecf20Sopenharmony_ci if (!blk) 6988c2ecf20Sopenharmony_ci return -ENOMEM; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci *rblk = blk; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci return 0; 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_cistatic int amixer_rsc_put_ctrl_blk(void *blk) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci kfree(blk); 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci return 0; 7108c2ecf20Sopenharmony_ci} 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic int amixer_mgr_get_ctrl_blk(void **rblk) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci *rblk = NULL; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci return 0; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic int amixer_mgr_put_ctrl_blk(void *blk) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci return 0; 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci/* 7258c2ecf20Sopenharmony_ci * DAIO control block definitions. 7268c2ecf20Sopenharmony_ci */ 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci/* Receiver Sample Rate Tracker Control register */ 7298c2ecf20Sopenharmony_ci#define SRTCTL_SRCO 0x000000FF 7308c2ecf20Sopenharmony_ci#define SRTCTL_SRCM 0x0000FF00 7318c2ecf20Sopenharmony_ci#define SRTCTL_RSR 0x00030000 7328c2ecf20Sopenharmony_ci#define SRTCTL_DRAT 0x00300000 7338c2ecf20Sopenharmony_ci#define SRTCTL_EC 0x01000000 7348c2ecf20Sopenharmony_ci#define SRTCTL_ET 0x10000000 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci/* DAIO Receiver register dirty flags */ 7378c2ecf20Sopenharmony_ciunion dai_dirty { 7388c2ecf20Sopenharmony_ci struct { 7398c2ecf20Sopenharmony_ci u16 srt:1; 7408c2ecf20Sopenharmony_ci u16 rsv:15; 7418c2ecf20Sopenharmony_ci } bf; 7428c2ecf20Sopenharmony_ci u16 data; 7438c2ecf20Sopenharmony_ci}; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci/* DAIO Receiver control block */ 7468c2ecf20Sopenharmony_cistruct dai_ctrl_blk { 7478c2ecf20Sopenharmony_ci unsigned int srt; 7488c2ecf20Sopenharmony_ci union dai_dirty dirty; 7498c2ecf20Sopenharmony_ci}; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci/* Audio Input Mapper RAM */ 7528c2ecf20Sopenharmony_ci#define AIM_ARC 0x00000FFF 7538c2ecf20Sopenharmony_ci#define AIM_NXT 0x007F0000 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistruct daoimap { 7568c2ecf20Sopenharmony_ci unsigned int aim; 7578c2ecf20Sopenharmony_ci unsigned int idx; 7588c2ecf20Sopenharmony_ci}; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci/* Audio Transmitter Control and Status register */ 7618c2ecf20Sopenharmony_ci#define ATXCTL_EN 0x00000001 7628c2ecf20Sopenharmony_ci#define ATXCTL_MODE 0x00000010 7638c2ecf20Sopenharmony_ci#define ATXCTL_CD 0x00000020 7648c2ecf20Sopenharmony_ci#define ATXCTL_RAW 0x00000100 7658c2ecf20Sopenharmony_ci#define ATXCTL_MT 0x00000200 7668c2ecf20Sopenharmony_ci#define ATXCTL_NUC 0x00003000 7678c2ecf20Sopenharmony_ci#define ATXCTL_BEN 0x00010000 7688c2ecf20Sopenharmony_ci#define ATXCTL_BMUX 0x00700000 7698c2ecf20Sopenharmony_ci#define ATXCTL_B24 0x01000000 7708c2ecf20Sopenharmony_ci#define ATXCTL_CPF 0x02000000 7718c2ecf20Sopenharmony_ci#define ATXCTL_RIV 0x10000000 7728c2ecf20Sopenharmony_ci#define ATXCTL_LIV 0x20000000 7738c2ecf20Sopenharmony_ci#define ATXCTL_RSAT 0x40000000 7748c2ecf20Sopenharmony_ci#define ATXCTL_LSAT 0x80000000 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci/* XDIF Transmitter register dirty flags */ 7778c2ecf20Sopenharmony_ciunion dao_dirty { 7788c2ecf20Sopenharmony_ci struct { 7798c2ecf20Sopenharmony_ci u16 atxcsl:1; 7808c2ecf20Sopenharmony_ci u16 rsv:15; 7818c2ecf20Sopenharmony_ci } bf; 7828c2ecf20Sopenharmony_ci u16 data; 7838c2ecf20Sopenharmony_ci}; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci/* XDIF Transmitter control block */ 7868c2ecf20Sopenharmony_cistruct dao_ctrl_blk { 7878c2ecf20Sopenharmony_ci /* XDIF Transmitter Channel Status Low Register */ 7888c2ecf20Sopenharmony_ci unsigned int atxcsl; 7898c2ecf20Sopenharmony_ci union dao_dirty dirty; 7908c2ecf20Sopenharmony_ci}; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci/* Audio Receiver Control register */ 7938c2ecf20Sopenharmony_ci#define ARXCTL_EN 0x00000001 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci/* DAIO manager register dirty flags */ 7968c2ecf20Sopenharmony_ciunion daio_mgr_dirty { 7978c2ecf20Sopenharmony_ci struct { 7988c2ecf20Sopenharmony_ci u32 atxctl:8; 7998c2ecf20Sopenharmony_ci u32 arxctl:8; 8008c2ecf20Sopenharmony_ci u32 daoimap:1; 8018c2ecf20Sopenharmony_ci u32 rsv:15; 8028c2ecf20Sopenharmony_ci } bf; 8038c2ecf20Sopenharmony_ci u32 data; 8048c2ecf20Sopenharmony_ci}; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci/* DAIO manager control block */ 8078c2ecf20Sopenharmony_cistruct daio_mgr_ctrl_blk { 8088c2ecf20Sopenharmony_ci struct daoimap daoimap; 8098c2ecf20Sopenharmony_ci unsigned int txctl[8]; 8108c2ecf20Sopenharmony_ci unsigned int rxctl[8]; 8118c2ecf20Sopenharmony_ci union daio_mgr_dirty dirty; 8128c2ecf20Sopenharmony_ci}; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cistatic int dai_srt_set_srco(void *blk, unsigned int src) 8158c2ecf20Sopenharmony_ci{ 8168c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci set_field(&ctl->srt, SRTCTL_SRCO, src); 8198c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 1; 8208c2ecf20Sopenharmony_ci return 0; 8218c2ecf20Sopenharmony_ci} 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_cistatic int dai_srt_set_srcm(void *blk, unsigned int src) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci set_field(&ctl->srt, SRTCTL_SRCM, src); 8288c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 1; 8298c2ecf20Sopenharmony_ci return 0; 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_cistatic int dai_srt_set_rsr(void *blk, unsigned int rsr) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci set_field(&ctl->srt, SRTCTL_RSR, rsr); 8378c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 1; 8388c2ecf20Sopenharmony_ci return 0; 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_cistatic int dai_srt_set_drat(void *blk, unsigned int drat) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci set_field(&ctl->srt, SRTCTL_DRAT, drat); 8468c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 1; 8478c2ecf20Sopenharmony_ci return 0; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic int dai_srt_set_ec(void *blk, unsigned int ec) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci set_field(&ctl->srt, SRTCTL_EC, ec ? 1 : 0); 8558c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 1; 8568c2ecf20Sopenharmony_ci return 0; 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_cistatic int dai_srt_set_et(void *blk, unsigned int et) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci set_field(&ctl->srt, SRTCTL_ET, et ? 1 : 0); 8648c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 1; 8658c2ecf20Sopenharmony_ci return 0; 8668c2ecf20Sopenharmony_ci} 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_cistatic int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) 8698c2ecf20Sopenharmony_ci{ 8708c2ecf20Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci if (ctl->dirty.bf.srt) { 8738c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_RX_SRT_CTL+0x40*idx, ctl->srt); 8748c2ecf20Sopenharmony_ci ctl->dirty.bf.srt = 0; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci return 0; 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic int dai_get_ctrl_blk(void **rblk) 8818c2ecf20Sopenharmony_ci{ 8828c2ecf20Sopenharmony_ci struct dai_ctrl_blk *blk; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci *rblk = NULL; 8858c2ecf20Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 8868c2ecf20Sopenharmony_ci if (!blk) 8878c2ecf20Sopenharmony_ci return -ENOMEM; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci *rblk = blk; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci return 0; 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_cistatic int dai_put_ctrl_blk(void *blk) 8958c2ecf20Sopenharmony_ci{ 8968c2ecf20Sopenharmony_ci kfree(blk); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci return 0; 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_cistatic int dao_set_spos(void *blk, unsigned int spos) 9028c2ecf20Sopenharmony_ci{ 9038c2ecf20Sopenharmony_ci ((struct dao_ctrl_blk *)blk)->atxcsl = spos; 9048c2ecf20Sopenharmony_ci ((struct dao_ctrl_blk *)blk)->dirty.bf.atxcsl = 1; 9058c2ecf20Sopenharmony_ci return 0; 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_cistatic int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci struct dao_ctrl_blk *ctl = blk; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci if (ctl->dirty.bf.atxcsl) { 9138c2ecf20Sopenharmony_ci if (idx < 4) { 9148c2ecf20Sopenharmony_ci /* S/PDIF SPOSx */ 9158c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+0x40*idx, 9168c2ecf20Sopenharmony_ci ctl->atxcsl); 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci ctl->dirty.bf.atxcsl = 0; 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci return 0; 9228c2ecf20Sopenharmony_ci} 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_cistatic int dao_get_spos(void *blk, unsigned int *spos) 9258c2ecf20Sopenharmony_ci{ 9268c2ecf20Sopenharmony_ci *spos = ((struct dao_ctrl_blk *)blk)->atxcsl; 9278c2ecf20Sopenharmony_ci return 0; 9288c2ecf20Sopenharmony_ci} 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_cistatic int dao_get_ctrl_blk(void **rblk) 9318c2ecf20Sopenharmony_ci{ 9328c2ecf20Sopenharmony_ci struct dao_ctrl_blk *blk; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci *rblk = NULL; 9358c2ecf20Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 9368c2ecf20Sopenharmony_ci if (!blk) 9378c2ecf20Sopenharmony_ci return -ENOMEM; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci *rblk = blk; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return 0; 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_cistatic int dao_put_ctrl_blk(void *blk) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci kfree(blk); 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci return 0; 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_cistatic int daio_mgr_enb_dai(void *blk, unsigned int idx) 9528c2ecf20Sopenharmony_ci{ 9538c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci set_field(&ctl->rxctl[idx], ARXCTL_EN, 1); 9568c2ecf20Sopenharmony_ci ctl->dirty.bf.arxctl |= (0x1 << idx); 9578c2ecf20Sopenharmony_ci return 0; 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic int daio_mgr_dsb_dai(void *blk, unsigned int idx) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci set_field(&ctl->rxctl[idx], ARXCTL_EN, 0); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci ctl->dirty.bf.arxctl |= (0x1 << idx); 9678c2ecf20Sopenharmony_ci return 0; 9688c2ecf20Sopenharmony_ci} 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_cistatic int daio_mgr_enb_dao(void *blk, unsigned int idx) 9718c2ecf20Sopenharmony_ci{ 9728c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_EN, 1); 9758c2ecf20Sopenharmony_ci ctl->dirty.bf.atxctl |= (0x1 << idx); 9768c2ecf20Sopenharmony_ci return 0; 9778c2ecf20Sopenharmony_ci} 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cistatic int daio_mgr_dsb_dao(void *blk, unsigned int idx) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_EN, 0); 9848c2ecf20Sopenharmony_ci ctl->dirty.bf.atxctl |= (0x1 << idx); 9858c2ecf20Sopenharmony_ci return 0; 9868c2ecf20Sopenharmony_ci} 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_cistatic int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) 9898c2ecf20Sopenharmony_ci{ 9908c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci if (idx < 4) { 9938c2ecf20Sopenharmony_ci /* S/PDIF output */ 9948c2ecf20Sopenharmony_ci switch ((conf & 0xf)) { 9958c2ecf20Sopenharmony_ci case 1: 9968c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_NUC, 0); 9978c2ecf20Sopenharmony_ci break; 9988c2ecf20Sopenharmony_ci case 2: 9998c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_NUC, 1); 10008c2ecf20Sopenharmony_ci break; 10018c2ecf20Sopenharmony_ci case 4: 10028c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_NUC, 2); 10038c2ecf20Sopenharmony_ci break; 10048c2ecf20Sopenharmony_ci case 8: 10058c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_NUC, 3); 10068c2ecf20Sopenharmony_ci break; 10078c2ecf20Sopenharmony_ci default: 10088c2ecf20Sopenharmony_ci break; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci /* CDIF */ 10118c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_CD, (!(conf & 0x7))); 10128c2ecf20Sopenharmony_ci /* Non-audio */ 10138c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_LIV, (conf >> 4) & 0x1); 10148c2ecf20Sopenharmony_ci /* Non-audio */ 10158c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_RIV, (conf >> 4) & 0x1); 10168c2ecf20Sopenharmony_ci set_field(&ctl->txctl[idx], ATXCTL_RAW, 10178c2ecf20Sopenharmony_ci ((conf >> 3) & 0x1) ? 0 : 0); 10188c2ecf20Sopenharmony_ci ctl->dirty.bf.atxctl |= (0x1 << idx); 10198c2ecf20Sopenharmony_ci } else { 10208c2ecf20Sopenharmony_ci /* I2S output */ 10218c2ecf20Sopenharmony_ci /*idx %= 4; */ 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci return 0; 10248c2ecf20Sopenharmony_ci} 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic int daio_mgr_set_imaparc(void *blk, unsigned int slot) 10278c2ecf20Sopenharmony_ci{ 10288c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci set_field(&ctl->daoimap.aim, AIM_ARC, slot); 10318c2ecf20Sopenharmony_ci ctl->dirty.bf.daoimap = 1; 10328c2ecf20Sopenharmony_ci return 0; 10338c2ecf20Sopenharmony_ci} 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_cistatic int daio_mgr_set_imapnxt(void *blk, unsigned int next) 10368c2ecf20Sopenharmony_ci{ 10378c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci set_field(&ctl->daoimap.aim, AIM_NXT, next); 10408c2ecf20Sopenharmony_ci ctl->dirty.bf.daoimap = 1; 10418c2ecf20Sopenharmony_ci return 0; 10428c2ecf20Sopenharmony_ci} 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_cistatic int daio_mgr_set_imapaddr(void *blk, unsigned int addr) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci ((struct daio_mgr_ctrl_blk *)blk)->daoimap.idx = addr; 10478c2ecf20Sopenharmony_ci ((struct daio_mgr_ctrl_blk *)blk)->dirty.bf.daoimap = 1; 10488c2ecf20Sopenharmony_ci return 0; 10498c2ecf20Sopenharmony_ci} 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_cistatic int daio_mgr_commit_write(struct hw *hw, void *blk) 10528c2ecf20Sopenharmony_ci{ 10538c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 10548c2ecf20Sopenharmony_ci unsigned int data; 10558c2ecf20Sopenharmony_ci int i; 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 10588c2ecf20Sopenharmony_ci if ((ctl->dirty.bf.atxctl & (0x1 << i))) { 10598c2ecf20Sopenharmony_ci data = ctl->txctl[i]; 10608c2ecf20Sopenharmony_ci hw_write_20kx(hw, (AUDIO_IO_TX_CTL+(0x40*i)), data); 10618c2ecf20Sopenharmony_ci ctl->dirty.bf.atxctl &= ~(0x1 << i); 10628c2ecf20Sopenharmony_ci mdelay(1); 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci if ((ctl->dirty.bf.arxctl & (0x1 << i))) { 10658c2ecf20Sopenharmony_ci data = ctl->rxctl[i]; 10668c2ecf20Sopenharmony_ci hw_write_20kx(hw, (AUDIO_IO_RX_CTL+(0x40*i)), data); 10678c2ecf20Sopenharmony_ci ctl->dirty.bf.arxctl &= ~(0x1 << i); 10688c2ecf20Sopenharmony_ci mdelay(1); 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci if (ctl->dirty.bf.daoimap) { 10728c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_AIM+ctl->daoimap.idx*4, 10738c2ecf20Sopenharmony_ci ctl->daoimap.aim); 10748c2ecf20Sopenharmony_ci ctl->dirty.bf.daoimap = 0; 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci return 0; 10788c2ecf20Sopenharmony_ci} 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_cistatic int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) 10818c2ecf20Sopenharmony_ci{ 10828c2ecf20Sopenharmony_ci struct daio_mgr_ctrl_blk *blk; 10838c2ecf20Sopenharmony_ci int i; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci *rblk = NULL; 10868c2ecf20Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 10878c2ecf20Sopenharmony_ci if (!blk) 10888c2ecf20Sopenharmony_ci return -ENOMEM; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 10918c2ecf20Sopenharmony_ci blk->txctl[i] = hw_read_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i)); 10928c2ecf20Sopenharmony_ci blk->rxctl[i] = hw_read_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i)); 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci *rblk = blk; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci return 0; 10988c2ecf20Sopenharmony_ci} 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_cistatic int daio_mgr_put_ctrl_blk(void *blk) 11018c2ecf20Sopenharmony_ci{ 11028c2ecf20Sopenharmony_ci kfree(blk); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci return 0; 11058c2ecf20Sopenharmony_ci} 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci/* Timer interrupt */ 11088c2ecf20Sopenharmony_cistatic int set_timer_irq(struct hw *hw, int enable) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci hw_write_20kx(hw, GIE, enable ? IT_INT : 0); 11118c2ecf20Sopenharmony_ci return 0; 11128c2ecf20Sopenharmony_ci} 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_cistatic int set_timer_tick(struct hw *hw, unsigned int ticks) 11158c2ecf20Sopenharmony_ci{ 11168c2ecf20Sopenharmony_ci if (ticks) 11178c2ecf20Sopenharmony_ci ticks |= TIMR_IE | TIMR_IP; 11188c2ecf20Sopenharmony_ci hw_write_20kx(hw, TIMR, ticks); 11198c2ecf20Sopenharmony_ci return 0; 11208c2ecf20Sopenharmony_ci} 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_cistatic unsigned int get_wc(struct hw *hw) 11238c2ecf20Sopenharmony_ci{ 11248c2ecf20Sopenharmony_ci return hw_read_20kx(hw, WC); 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci/* Card hardware initialization block */ 11288c2ecf20Sopenharmony_cistruct dac_conf { 11298c2ecf20Sopenharmony_ci unsigned int msr; /* master sample rate in rsrs */ 11308c2ecf20Sopenharmony_ci}; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_cistruct adc_conf { 11338c2ecf20Sopenharmony_ci unsigned int msr; /* master sample rate in rsrs */ 11348c2ecf20Sopenharmony_ci unsigned char input; /* the input source of ADC */ 11358c2ecf20Sopenharmony_ci unsigned char mic20db; /* boost mic by 20db if input is microphone */ 11368c2ecf20Sopenharmony_ci}; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_cistruct daio_conf { 11398c2ecf20Sopenharmony_ci unsigned int msr; /* master sample rate in rsrs */ 11408c2ecf20Sopenharmony_ci}; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistruct trn_conf { 11438c2ecf20Sopenharmony_ci unsigned long vm_pgt_phys; 11448c2ecf20Sopenharmony_ci}; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_cistatic int hw_daio_init(struct hw *hw, const struct daio_conf *info) 11478c2ecf20Sopenharmony_ci{ 11488c2ecf20Sopenharmony_ci u32 data; 11498c2ecf20Sopenharmony_ci int i; 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* Program I2S with proper sample rate and enable the correct I2S 11528c2ecf20Sopenharmony_ci * channel. ED(0/8/16/24): Enable all I2S/I2X master clock output */ 11538c2ecf20Sopenharmony_ci if (1 == info->msr) { 11548c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_MCLK, 0x01010101); 11558c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); 11568c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); 11578c2ecf20Sopenharmony_ci } else if (2 == info->msr) { 11588c2ecf20Sopenharmony_ci if (hw->model != CTSB1270) { 11598c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); 11608c2ecf20Sopenharmony_ci } else { 11618c2ecf20Sopenharmony_ci /* PCM4220 on Titanium HD is different. */ 11628c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111); 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci /* Specify all playing 96khz 11658c2ecf20Sopenharmony_ci * EA [0] - Enabled 11668c2ecf20Sopenharmony_ci * RTA [4:5] - 96kHz 11678c2ecf20Sopenharmony_ci * EB [8] - Enabled 11688c2ecf20Sopenharmony_ci * RTB [12:13] - 96kHz 11698c2ecf20Sopenharmony_ci * EC [16] - Enabled 11708c2ecf20Sopenharmony_ci * RTC [20:21] - 96kHz 11718c2ecf20Sopenharmony_ci * ED [24] - Enabled 11728c2ecf20Sopenharmony_ci * RTD [28:29] - 96kHz */ 11738c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); 11748c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); 11758c2ecf20Sopenharmony_ci } else if ((4 == info->msr) && (hw->model == CTSB1270)) { 11768c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); 11778c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); 11788c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); 11798c2ecf20Sopenharmony_ci } else { 11808c2ecf20Sopenharmony_ci dev_alert(hw->card->dev, 11818c2ecf20Sopenharmony_ci "ERROR!!! Invalid sampling rate!!!\n"); 11828c2ecf20Sopenharmony_ci return -EINVAL; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 11868c2ecf20Sopenharmony_ci if (i <= 3) { 11878c2ecf20Sopenharmony_ci /* This comment looks wrong since loop is over 4 */ 11888c2ecf20Sopenharmony_ci /* channels and emu20k2 supports 4 spdif IOs. */ 11898c2ecf20Sopenharmony_ci /* 1st 3 channels are SPDIFs (SB0960) */ 11908c2ecf20Sopenharmony_ci if (i == 3) 11918c2ecf20Sopenharmony_ci data = 0x1001001; 11928c2ecf20Sopenharmony_ci else 11938c2ecf20Sopenharmony_ci data = 0x1000001; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci hw_write_20kx(hw, (AUDIO_IO_TX_CTL+(0x40*i)), data); 11968c2ecf20Sopenharmony_ci hw_write_20kx(hw, (AUDIO_IO_RX_CTL+(0x40*i)), data); 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci /* Initialize the SPDIF Out Channel status registers. 11998c2ecf20Sopenharmony_ci * The value specified here is based on the typical 12008c2ecf20Sopenharmony_ci * values provided in the specification, namely: Clock 12018c2ecf20Sopenharmony_ci * Accuracy of 1000ppm, Sample Rate of 48KHz, 12028c2ecf20Sopenharmony_ci * unspecified source number, Generation status = 1, 12038c2ecf20Sopenharmony_ci * Category code = 0x12 (Digital Signal Mixer), 12048c2ecf20Sopenharmony_ci * Mode = 0, Emph = 0, Copy Permitted, AN = 0 12058c2ecf20Sopenharmony_ci * (indicating that we're transmitting digital audio, 12068c2ecf20Sopenharmony_ci * and the Professional Use bit is 0. */ 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+(0x40*i), 12098c2ecf20Sopenharmony_ci 0x02109204); /* Default to 48kHz */ 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); 12128c2ecf20Sopenharmony_ci } else { 12138c2ecf20Sopenharmony_ci /* Again, loop is over 4 channels not 5. */ 12148c2ecf20Sopenharmony_ci /* Next 5 channels are I2S (SB0960) */ 12158c2ecf20Sopenharmony_ci data = 0x11; 12168c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); 12178c2ecf20Sopenharmony_ci if (2 == info->msr) { 12188c2ecf20Sopenharmony_ci /* Four channels per sample period */ 12198c2ecf20Sopenharmony_ci data |= 0x1000; 12208c2ecf20Sopenharmony_ci } else if (4 == info->msr) { 12218c2ecf20Sopenharmony_ci /* FIXME: check this against the chip spec */ 12228c2ecf20Sopenharmony_ci data |= 0x2000; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci return 0; 12298c2ecf20Sopenharmony_ci} 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci/* TRANSPORT operations */ 12328c2ecf20Sopenharmony_cistatic int hw_trn_init(struct hw *hw, const struct trn_conf *info) 12338c2ecf20Sopenharmony_ci{ 12348c2ecf20Sopenharmony_ci u32 vmctl, data; 12358c2ecf20Sopenharmony_ci u32 ptp_phys_low, ptp_phys_high; 12368c2ecf20Sopenharmony_ci int i; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* Set up device page table */ 12398c2ecf20Sopenharmony_ci if ((~0UL) == info->vm_pgt_phys) { 12408c2ecf20Sopenharmony_ci dev_alert(hw->card->dev, 12418c2ecf20Sopenharmony_ci "Wrong device page table page address!!!\n"); 12428c2ecf20Sopenharmony_ci return -1; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci vmctl = 0x80000C0F; /* 32-bit, 4k-size page */ 12468c2ecf20Sopenharmony_ci ptp_phys_low = (u32)info->vm_pgt_phys; 12478c2ecf20Sopenharmony_ci ptp_phys_high = upper_32_bits(info->vm_pgt_phys); 12488c2ecf20Sopenharmony_ci if (sizeof(void *) == 8) /* 64bit address */ 12498c2ecf20Sopenharmony_ci vmctl |= (3 << 8); 12508c2ecf20Sopenharmony_ci /* Write page table physical address to all PTPAL registers */ 12518c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 12528c2ecf20Sopenharmony_ci hw_write_20kx(hw, VMEM_PTPAL+(16*i), ptp_phys_low); 12538c2ecf20Sopenharmony_ci hw_write_20kx(hw, VMEM_PTPAH+(16*i), ptp_phys_high); 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci /* Enable virtual memory transfer */ 12568c2ecf20Sopenharmony_ci hw_write_20kx(hw, VMEM_CTL, vmctl); 12578c2ecf20Sopenharmony_ci /* Enable transport bus master and queueing of request */ 12588c2ecf20Sopenharmony_ci hw_write_20kx(hw, TRANSPORT_CTL, 0x03); 12598c2ecf20Sopenharmony_ci hw_write_20kx(hw, TRANSPORT_INT, 0x200c01); 12608c2ecf20Sopenharmony_ci /* Enable transport ring */ 12618c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, TRANSPORT_ENB); 12628c2ecf20Sopenharmony_ci hw_write_20kx(hw, TRANSPORT_ENB, (data | 0x03)); 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci return 0; 12658c2ecf20Sopenharmony_ci} 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci/* Card initialization */ 12688c2ecf20Sopenharmony_ci#define GCTL_AIE 0x00000001 12698c2ecf20Sopenharmony_ci#define GCTL_UAA 0x00000002 12708c2ecf20Sopenharmony_ci#define GCTL_DPC 0x00000004 12718c2ecf20Sopenharmony_ci#define GCTL_DBP 0x00000008 12728c2ecf20Sopenharmony_ci#define GCTL_ABP 0x00000010 12738c2ecf20Sopenharmony_ci#define GCTL_TBP 0x00000020 12748c2ecf20Sopenharmony_ci#define GCTL_SBP 0x00000040 12758c2ecf20Sopenharmony_ci#define GCTL_FBP 0x00000080 12768c2ecf20Sopenharmony_ci#define GCTL_ME 0x00000100 12778c2ecf20Sopenharmony_ci#define GCTL_AID 0x00001000 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci#define PLLCTL_SRC 0x00000007 12808c2ecf20Sopenharmony_ci#define PLLCTL_SPE 0x00000008 12818c2ecf20Sopenharmony_ci#define PLLCTL_RD 0x000000F0 12828c2ecf20Sopenharmony_ci#define PLLCTL_FD 0x0001FF00 12838c2ecf20Sopenharmony_ci#define PLLCTL_OD 0x00060000 12848c2ecf20Sopenharmony_ci#define PLLCTL_B 0x00080000 12858c2ecf20Sopenharmony_ci#define PLLCTL_AS 0x00100000 12868c2ecf20Sopenharmony_ci#define PLLCTL_LF 0x03E00000 12878c2ecf20Sopenharmony_ci#define PLLCTL_SPS 0x1C000000 12888c2ecf20Sopenharmony_ci#define PLLCTL_AD 0x60000000 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci#define PLLSTAT_CCS 0x00000007 12918c2ecf20Sopenharmony_ci#define PLLSTAT_SPL 0x00000008 12928c2ecf20Sopenharmony_ci#define PLLSTAT_CRD 0x000000F0 12938c2ecf20Sopenharmony_ci#define PLLSTAT_CFD 0x0001FF00 12948c2ecf20Sopenharmony_ci#define PLLSTAT_SL 0x00020000 12958c2ecf20Sopenharmony_ci#define PLLSTAT_FAS 0x00040000 12968c2ecf20Sopenharmony_ci#define PLLSTAT_B 0x00080000 12978c2ecf20Sopenharmony_ci#define PLLSTAT_PD 0x00100000 12988c2ecf20Sopenharmony_ci#define PLLSTAT_OCA 0x00200000 12998c2ecf20Sopenharmony_ci#define PLLSTAT_NCA 0x00400000 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_cistatic int hw_pll_init(struct hw *hw, unsigned int rsr) 13028c2ecf20Sopenharmony_ci{ 13038c2ecf20Sopenharmony_ci unsigned int pllenb; 13048c2ecf20Sopenharmony_ci unsigned int pllctl; 13058c2ecf20Sopenharmony_ci unsigned int pllstat; 13068c2ecf20Sopenharmony_ci int i; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci pllenb = 0xB; 13098c2ecf20Sopenharmony_ci hw_write_20kx(hw, PLL_ENB, pllenb); 13108c2ecf20Sopenharmony_ci pllctl = 0x20C00000; 13118c2ecf20Sopenharmony_ci set_field(&pllctl, PLLCTL_B, 0); 13128c2ecf20Sopenharmony_ci set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4); 13138c2ecf20Sopenharmony_ci set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1); 13148c2ecf20Sopenharmony_ci hw_write_20kx(hw, PLL_CTL, pllctl); 13158c2ecf20Sopenharmony_ci msleep(40); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci pllctl = hw_read_20kx(hw, PLL_CTL); 13188c2ecf20Sopenharmony_ci set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2); 13198c2ecf20Sopenharmony_ci hw_write_20kx(hw, PLL_CTL, pllctl); 13208c2ecf20Sopenharmony_ci msleep(40); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci for (i = 0; i < 1000; i++) { 13238c2ecf20Sopenharmony_ci pllstat = hw_read_20kx(hw, PLL_STAT); 13248c2ecf20Sopenharmony_ci if (get_field(pllstat, PLLSTAT_PD)) 13258c2ecf20Sopenharmony_ci continue; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci if (get_field(pllstat, PLLSTAT_B) != 13288c2ecf20Sopenharmony_ci get_field(pllctl, PLLCTL_B)) 13298c2ecf20Sopenharmony_ci continue; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (get_field(pllstat, PLLSTAT_CCS) != 13328c2ecf20Sopenharmony_ci get_field(pllctl, PLLCTL_SRC)) 13338c2ecf20Sopenharmony_ci continue; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci if (get_field(pllstat, PLLSTAT_CRD) != 13368c2ecf20Sopenharmony_ci get_field(pllctl, PLLCTL_RD)) 13378c2ecf20Sopenharmony_ci continue; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci if (get_field(pllstat, PLLSTAT_CFD) != 13408c2ecf20Sopenharmony_ci get_field(pllctl, PLLCTL_FD)) 13418c2ecf20Sopenharmony_ci continue; 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci break; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci if (i >= 1000) { 13468c2ecf20Sopenharmony_ci dev_alert(hw->card->dev, 13478c2ecf20Sopenharmony_ci "PLL initialization failed!!!\n"); 13488c2ecf20Sopenharmony_ci return -EBUSY; 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci return 0; 13528c2ecf20Sopenharmony_ci} 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_cistatic int hw_auto_init(struct hw *hw) 13558c2ecf20Sopenharmony_ci{ 13568c2ecf20Sopenharmony_ci unsigned int gctl; 13578c2ecf20Sopenharmony_ci int i; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); 13608c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_AIE, 0); 13618c2ecf20Sopenharmony_ci hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); 13628c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_AIE, 1); 13638c2ecf20Sopenharmony_ci hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); 13648c2ecf20Sopenharmony_ci mdelay(10); 13658c2ecf20Sopenharmony_ci for (i = 0; i < 400000; i++) { 13668c2ecf20Sopenharmony_ci gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); 13678c2ecf20Sopenharmony_ci if (get_field(gctl, GCTL_AID)) 13688c2ecf20Sopenharmony_ci break; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci if (!get_field(gctl, GCTL_AID)) { 13718c2ecf20Sopenharmony_ci dev_alert(hw->card->dev, "Card Auto-init failed!!!\n"); 13728c2ecf20Sopenharmony_ci return -EBUSY; 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci return 0; 13768c2ecf20Sopenharmony_ci} 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci/* DAC operations */ 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci#define CS4382_MC1 0x1 13818c2ecf20Sopenharmony_ci#define CS4382_MC2 0x2 13828c2ecf20Sopenharmony_ci#define CS4382_MC3 0x3 13838c2ecf20Sopenharmony_ci#define CS4382_FC 0x4 13848c2ecf20Sopenharmony_ci#define CS4382_IC 0x5 13858c2ecf20Sopenharmony_ci#define CS4382_XC1 0x6 13868c2ecf20Sopenharmony_ci#define CS4382_VCA1 0x7 13878c2ecf20Sopenharmony_ci#define CS4382_VCB1 0x8 13888c2ecf20Sopenharmony_ci#define CS4382_XC2 0x9 13898c2ecf20Sopenharmony_ci#define CS4382_VCA2 0xA 13908c2ecf20Sopenharmony_ci#define CS4382_VCB2 0xB 13918c2ecf20Sopenharmony_ci#define CS4382_XC3 0xC 13928c2ecf20Sopenharmony_ci#define CS4382_VCA3 0xD 13938c2ecf20Sopenharmony_ci#define CS4382_VCB3 0xE 13948c2ecf20Sopenharmony_ci#define CS4382_XC4 0xF 13958c2ecf20Sopenharmony_ci#define CS4382_VCA4 0x10 13968c2ecf20Sopenharmony_ci#define CS4382_VCB4 0x11 13978c2ecf20Sopenharmony_ci#define CS4382_CREV 0x12 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci/* I2C status */ 14008c2ecf20Sopenharmony_ci#define STATE_LOCKED 0x00 14018c2ecf20Sopenharmony_ci#define STATE_UNLOCKED 0xAA 14028c2ecf20Sopenharmony_ci#define DATA_READY 0x800000 /* Used with I2C_IF_STATUS */ 14038c2ecf20Sopenharmony_ci#define DATA_ABORT 0x10000 /* Used with I2C_IF_STATUS */ 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci#define I2C_STATUS_DCM 0x00000001 14068c2ecf20Sopenharmony_ci#define I2C_STATUS_BC 0x00000006 14078c2ecf20Sopenharmony_ci#define I2C_STATUS_APD 0x00000008 14088c2ecf20Sopenharmony_ci#define I2C_STATUS_AB 0x00010000 14098c2ecf20Sopenharmony_ci#define I2C_STATUS_DR 0x00800000 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci#define I2C_ADDRESS_PTAD 0x0000FFFF 14128c2ecf20Sopenharmony_ci#define I2C_ADDRESS_SLAD 0x007F0000 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_cistruct regs_cs4382 { 14158c2ecf20Sopenharmony_ci u32 mode_control_1; 14168c2ecf20Sopenharmony_ci u32 mode_control_2; 14178c2ecf20Sopenharmony_ci u32 mode_control_3; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci u32 filter_control; 14208c2ecf20Sopenharmony_ci u32 invert_control; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci u32 mix_control_P1; 14238c2ecf20Sopenharmony_ci u32 vol_control_A1; 14248c2ecf20Sopenharmony_ci u32 vol_control_B1; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci u32 mix_control_P2; 14278c2ecf20Sopenharmony_ci u32 vol_control_A2; 14288c2ecf20Sopenharmony_ci u32 vol_control_B2; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci u32 mix_control_P3; 14318c2ecf20Sopenharmony_ci u32 vol_control_A3; 14328c2ecf20Sopenharmony_ci u32 vol_control_B3; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci u32 mix_control_P4; 14358c2ecf20Sopenharmony_ci u32 vol_control_A4; 14368c2ecf20Sopenharmony_ci u32 vol_control_B4; 14378c2ecf20Sopenharmony_ci}; 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_cistatic int hw20k2_i2c_unlock_full_access(struct hw *hw) 14408c2ecf20Sopenharmony_ci{ 14418c2ecf20Sopenharmony_ci u8 UnlockKeySequence_FLASH_FULLACCESS_MODE[2] = {0xB3, 0xD4}; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci /* Send keys for forced BIOS mode */ 14448c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WLOCK, 14458c2ecf20Sopenharmony_ci UnlockKeySequence_FLASH_FULLACCESS_MODE[0]); 14468c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WLOCK, 14478c2ecf20Sopenharmony_ci UnlockKeySequence_FLASH_FULLACCESS_MODE[1]); 14488c2ecf20Sopenharmony_ci /* Check whether the chip is unlocked */ 14498c2ecf20Sopenharmony_ci if (hw_read_20kx(hw, I2C_IF_WLOCK) == STATE_UNLOCKED) 14508c2ecf20Sopenharmony_ci return 0; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci return -1; 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_cistatic int hw20k2_i2c_lock_chip(struct hw *hw) 14568c2ecf20Sopenharmony_ci{ 14578c2ecf20Sopenharmony_ci /* Write twice */ 14588c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WLOCK, STATE_LOCKED); 14598c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WLOCK, STATE_LOCKED); 14608c2ecf20Sopenharmony_ci if (hw_read_20kx(hw, I2C_IF_WLOCK) == STATE_LOCKED) 14618c2ecf20Sopenharmony_ci return 0; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci return -1; 14648c2ecf20Sopenharmony_ci} 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_cistatic int hw20k2_i2c_init(struct hw *hw, u8 dev_id, u8 addr_size, u8 data_size) 14678c2ecf20Sopenharmony_ci{ 14688c2ecf20Sopenharmony_ci struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; 14698c2ecf20Sopenharmony_ci int err; 14708c2ecf20Sopenharmony_ci unsigned int i2c_status; 14718c2ecf20Sopenharmony_ci unsigned int i2c_addr; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci err = hw20k2_i2c_unlock_full_access(hw); 14748c2ecf20Sopenharmony_ci if (err < 0) 14758c2ecf20Sopenharmony_ci return err; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci hw20k2->addr_size = addr_size; 14788c2ecf20Sopenharmony_ci hw20k2->data_size = data_size; 14798c2ecf20Sopenharmony_ci hw20k2->dev_id = dev_id; 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci i2c_addr = 0; 14828c2ecf20Sopenharmony_ci set_field(&i2c_addr, I2C_ADDRESS_SLAD, dev_id); 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_ADDRESS, i2c_addr); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci set_field(&i2c_status, I2C_STATUS_DCM, 1); /* Direct control mode */ 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci return 0; 14938c2ecf20Sopenharmony_ci} 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_cistatic int hw20k2_i2c_uninit(struct hw *hw) 14968c2ecf20Sopenharmony_ci{ 14978c2ecf20Sopenharmony_ci unsigned int i2c_status; 14988c2ecf20Sopenharmony_ci unsigned int i2c_addr; 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci i2c_addr = 0; 15018c2ecf20Sopenharmony_ci set_field(&i2c_addr, I2C_ADDRESS_SLAD, 0x57); /* I2C id */ 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_ADDRESS, i2c_addr); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci set_field(&i2c_status, I2C_STATUS_DCM, 0); /* I2C mode */ 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci return hw20k2_i2c_lock_chip(hw); 15128c2ecf20Sopenharmony_ci} 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_cistatic int hw20k2_i2c_wait_data_ready(struct hw *hw) 15158c2ecf20Sopenharmony_ci{ 15168c2ecf20Sopenharmony_ci int i = 0x400000; 15178c2ecf20Sopenharmony_ci unsigned int ret; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci do { 15208c2ecf20Sopenharmony_ci ret = hw_read_20kx(hw, I2C_IF_STATUS); 15218c2ecf20Sopenharmony_ci } while ((!(ret & DATA_READY)) && --i); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci return i; 15248c2ecf20Sopenharmony_ci} 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_cistatic int hw20k2_i2c_read(struct hw *hw, u16 addr, u32 *datap) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; 15298c2ecf20Sopenharmony_ci unsigned int i2c_status; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); 15328c2ecf20Sopenharmony_ci set_field(&i2c_status, I2C_STATUS_BC, 15338c2ecf20Sopenharmony_ci (4 == hw20k2->addr_size) ? 0 : hw20k2->addr_size); 15348c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); 15358c2ecf20Sopenharmony_ci if (!hw20k2_i2c_wait_data_ready(hw)) 15368c2ecf20Sopenharmony_ci return -1; 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WDATA, addr); 15398c2ecf20Sopenharmony_ci if (!hw20k2_i2c_wait_data_ready(hw)) 15408c2ecf20Sopenharmony_ci return -1; 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci /* Force a read operation */ 15438c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_RDATA, 0); 15448c2ecf20Sopenharmony_ci if (!hw20k2_i2c_wait_data_ready(hw)) 15458c2ecf20Sopenharmony_ci return -1; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci *datap = hw_read_20kx(hw, I2C_IF_RDATA); 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci return 0; 15508c2ecf20Sopenharmony_ci} 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_cistatic int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) 15538c2ecf20Sopenharmony_ci{ 15548c2ecf20Sopenharmony_ci struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; 15558c2ecf20Sopenharmony_ci unsigned int i2c_data = (data << (hw20k2->addr_size * 8)) | addr; 15568c2ecf20Sopenharmony_ci unsigned int i2c_status; 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci i2c_status = hw_read_20kx(hw, I2C_IF_STATUS); 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci set_field(&i2c_status, I2C_STATUS_BC, 15618c2ecf20Sopenharmony_ci (4 == (hw20k2->addr_size + hw20k2->data_size)) ? 15628c2ecf20Sopenharmony_ci 0 : (hw20k2->addr_size + hw20k2->data_size)); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); 15658c2ecf20Sopenharmony_ci hw20k2_i2c_wait_data_ready(hw); 15668c2ecf20Sopenharmony_ci /* Dummy write to trigger the write operation */ 15678c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WDATA, 0); 15688c2ecf20Sopenharmony_ci hw20k2_i2c_wait_data_ready(hw); 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci /* This is the real data */ 15718c2ecf20Sopenharmony_ci hw_write_20kx(hw, I2C_IF_WDATA, i2c_data); 15728c2ecf20Sopenharmony_ci hw20k2_i2c_wait_data_ready(hw); 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci return 0; 15758c2ecf20Sopenharmony_ci} 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_cistatic void hw_dac_stop(struct hw *hw) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci u32 data; 15808c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 15818c2ecf20Sopenharmony_ci data &= 0xFFFFFFFD; 15828c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 15838c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 15848c2ecf20Sopenharmony_ci} 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_cistatic void hw_dac_start(struct hw *hw) 15878c2ecf20Sopenharmony_ci{ 15888c2ecf20Sopenharmony_ci u32 data; 15898c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 15908c2ecf20Sopenharmony_ci data |= 0x2; 15918c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 15928c2ecf20Sopenharmony_ci msleep(50); 15938c2ecf20Sopenharmony_ci} 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_cistatic void hw_dac_reset(struct hw *hw) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci hw_dac_stop(hw); 15988c2ecf20Sopenharmony_ci hw_dac_start(hw); 15998c2ecf20Sopenharmony_ci} 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_cistatic int hw_dac_init(struct hw *hw, const struct dac_conf *info) 16028c2ecf20Sopenharmony_ci{ 16038c2ecf20Sopenharmony_ci int err; 16048c2ecf20Sopenharmony_ci u32 data; 16058c2ecf20Sopenharmony_ci int i; 16068c2ecf20Sopenharmony_ci struct regs_cs4382 cs_read = {0}; 16078c2ecf20Sopenharmony_ci struct regs_cs4382 cs_def = { 16088c2ecf20Sopenharmony_ci .mode_control_1 = 0x00000001, /* Mode Control 1 */ 16098c2ecf20Sopenharmony_ci .mode_control_2 = 0x00000000, /* Mode Control 2 */ 16108c2ecf20Sopenharmony_ci .mode_control_3 = 0x00000084, /* Mode Control 3 */ 16118c2ecf20Sopenharmony_ci .filter_control = 0x00000000, /* Filter Control */ 16128c2ecf20Sopenharmony_ci .invert_control = 0x00000000, /* Invert Control */ 16138c2ecf20Sopenharmony_ci .mix_control_P1 = 0x00000024, /* Mixing Control Pair 1 */ 16148c2ecf20Sopenharmony_ci .vol_control_A1 = 0x00000000, /* Vol Control A1 */ 16158c2ecf20Sopenharmony_ci .vol_control_B1 = 0x00000000, /* Vol Control B1 */ 16168c2ecf20Sopenharmony_ci .mix_control_P2 = 0x00000024, /* Mixing Control Pair 2 */ 16178c2ecf20Sopenharmony_ci .vol_control_A2 = 0x00000000, /* Vol Control A2 */ 16188c2ecf20Sopenharmony_ci .vol_control_B2 = 0x00000000, /* Vol Control B2 */ 16198c2ecf20Sopenharmony_ci .mix_control_P3 = 0x00000024, /* Mixing Control Pair 3 */ 16208c2ecf20Sopenharmony_ci .vol_control_A3 = 0x00000000, /* Vol Control A3 */ 16218c2ecf20Sopenharmony_ci .vol_control_B3 = 0x00000000, /* Vol Control B3 */ 16228c2ecf20Sopenharmony_ci .mix_control_P4 = 0x00000024, /* Mixing Control Pair 4 */ 16238c2ecf20Sopenharmony_ci .vol_control_A4 = 0x00000000, /* Vol Control A4 */ 16248c2ecf20Sopenharmony_ci .vol_control_B4 = 0x00000000 /* Vol Control B4 */ 16258c2ecf20Sopenharmony_ci }; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci if (hw->model == CTSB1270) { 16288c2ecf20Sopenharmony_ci hw_dac_stop(hw); 16298c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 16308c2ecf20Sopenharmony_ci data &= ~0x0600; 16318c2ecf20Sopenharmony_ci if (1 == info->msr) 16328c2ecf20Sopenharmony_ci data |= 0x0000; /* Single Speed Mode 0-50kHz */ 16338c2ecf20Sopenharmony_ci else if (2 == info->msr) 16348c2ecf20Sopenharmony_ci data |= 0x0200; /* Double Speed Mode 50-100kHz */ 16358c2ecf20Sopenharmony_ci else 16368c2ecf20Sopenharmony_ci data |= 0x0600; /* Quad Speed Mode 100-200kHz */ 16378c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 16388c2ecf20Sopenharmony_ci hw_dac_start(hw); 16398c2ecf20Sopenharmony_ci return 0; 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci /* Set DAC reset bit as output */ 16438c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_CTRL); 16448c2ecf20Sopenharmony_ci data |= 0x02; 16458c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_CTRL, data); 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci err = hw20k2_i2c_init(hw, 0x18, 1, 1); 16488c2ecf20Sopenharmony_ci if (err < 0) 16498c2ecf20Sopenharmony_ci goto End; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 16528c2ecf20Sopenharmony_ci /* Reset DAC twice just in-case the chip 16538c2ecf20Sopenharmony_ci * didn't initialized properly */ 16548c2ecf20Sopenharmony_ci hw_dac_reset(hw); 16558c2ecf20Sopenharmony_ci hw_dac_reset(hw); 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) 16588c2ecf20Sopenharmony_ci continue; 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_MC2, &cs_read.mode_control_2)) 16618c2ecf20Sopenharmony_ci continue; 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_MC3, &cs_read.mode_control_3)) 16648c2ecf20Sopenharmony_ci continue; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_FC, &cs_read.filter_control)) 16678c2ecf20Sopenharmony_ci continue; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_IC, &cs_read.invert_control)) 16708c2ecf20Sopenharmony_ci continue; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_XC1, &cs_read.mix_control_P1)) 16738c2ecf20Sopenharmony_ci continue; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCA1, &cs_read.vol_control_A1)) 16768c2ecf20Sopenharmony_ci continue; 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCB1, &cs_read.vol_control_B1)) 16798c2ecf20Sopenharmony_ci continue; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_XC2, &cs_read.mix_control_P2)) 16828c2ecf20Sopenharmony_ci continue; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCA2, &cs_read.vol_control_A2)) 16858c2ecf20Sopenharmony_ci continue; 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCB2, &cs_read.vol_control_B2)) 16888c2ecf20Sopenharmony_ci continue; 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_XC3, &cs_read.mix_control_P3)) 16918c2ecf20Sopenharmony_ci continue; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCA3, &cs_read.vol_control_A3)) 16948c2ecf20Sopenharmony_ci continue; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCB3, &cs_read.vol_control_B3)) 16978c2ecf20Sopenharmony_ci continue; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_XC4, &cs_read.mix_control_P4)) 17008c2ecf20Sopenharmony_ci continue; 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCA4, &cs_read.vol_control_A4)) 17038c2ecf20Sopenharmony_ci continue; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci if (hw20k2_i2c_read(hw, CS4382_VCB4, &cs_read.vol_control_B4)) 17068c2ecf20Sopenharmony_ci continue; 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci if (memcmp(&cs_read, &cs_def, sizeof(cs_read))) 17098c2ecf20Sopenharmony_ci continue; 17108c2ecf20Sopenharmony_ci else 17118c2ecf20Sopenharmony_ci break; 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci if (i >= 2) 17158c2ecf20Sopenharmony_ci goto End; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci /* Note: Every I2C write must have some delay. 17188c2ecf20Sopenharmony_ci * This is not a requirement but the delay works here... */ 17198c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_MC1, 0x80); 17208c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_MC2, 0x10); 17218c2ecf20Sopenharmony_ci if (1 == info->msr) { 17228c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC1, 0x24); 17238c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC2, 0x24); 17248c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC3, 0x24); 17258c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC4, 0x24); 17268c2ecf20Sopenharmony_ci } else if (2 == info->msr) { 17278c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC1, 0x25); 17288c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC2, 0x25); 17298c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC3, 0x25); 17308c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC4, 0x25); 17318c2ecf20Sopenharmony_ci } else { 17328c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC1, 0x26); 17338c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC2, 0x26); 17348c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC3, 0x26); 17358c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, CS4382_XC4, 0x26); 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci return 0; 17398c2ecf20Sopenharmony_ciEnd: 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci hw20k2_i2c_uninit(hw); 17428c2ecf20Sopenharmony_ci return -1; 17438c2ecf20Sopenharmony_ci} 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci/* ADC operations */ 17468c2ecf20Sopenharmony_ci#define MAKE_WM8775_ADDR(addr, data) (u32)(((addr<<1)&0xFE)|((data>>8)&0x1)) 17478c2ecf20Sopenharmony_ci#define MAKE_WM8775_DATA(data) (u32)(data&0xFF) 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci#define WM8775_IC 0x0B 17508c2ecf20Sopenharmony_ci#define WM8775_MMC 0x0C 17518c2ecf20Sopenharmony_ci#define WM8775_AADCL 0x0E 17528c2ecf20Sopenharmony_ci#define WM8775_AADCR 0x0F 17538c2ecf20Sopenharmony_ci#define WM8775_ADCMC 0x15 17548c2ecf20Sopenharmony_ci#define WM8775_RESET 0x17 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_cistatic int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) 17578c2ecf20Sopenharmony_ci{ 17588c2ecf20Sopenharmony_ci u32 data; 17598c2ecf20Sopenharmony_ci if (hw->model == CTSB1270) { 17608c2ecf20Sopenharmony_ci /* Titanium HD has two ADC chips, one for line in and one */ 17618c2ecf20Sopenharmony_ci /* for MIC. We don't need to switch the ADC input. */ 17628c2ecf20Sopenharmony_ci return 1; 17638c2ecf20Sopenharmony_ci } 17648c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 17658c2ecf20Sopenharmony_ci switch (type) { 17668c2ecf20Sopenharmony_ci case ADC_MICIN: 17678c2ecf20Sopenharmony_ci data = (data & (0x1 << 14)) ? 1 : 0; 17688c2ecf20Sopenharmony_ci break; 17698c2ecf20Sopenharmony_ci case ADC_LINEIN: 17708c2ecf20Sopenharmony_ci data = (data & (0x1 << 14)) ? 0 : 1; 17718c2ecf20Sopenharmony_ci break; 17728c2ecf20Sopenharmony_ci default: 17738c2ecf20Sopenharmony_ci data = 0; 17748c2ecf20Sopenharmony_ci } 17758c2ecf20Sopenharmony_ci return data; 17768c2ecf20Sopenharmony_ci} 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci#define MIC_BOOST_0DB 0xCF 17798c2ecf20Sopenharmony_ci#define MIC_BOOST_STEPS_PER_DB 2 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_cistatic void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db) 17828c2ecf20Sopenharmony_ci{ 17838c2ecf20Sopenharmony_ci u32 adcmc, gain; 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci if (input > 3) 17868c2ecf20Sopenharmony_ci input = 3; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */ 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc), 17918c2ecf20Sopenharmony_ci MAKE_WM8775_DATA(adcmc)); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci if (gain_in_db < -103) 17948c2ecf20Sopenharmony_ci gain_in_db = -103; 17958c2ecf20Sopenharmony_ci if (gain_in_db > 24) 17968c2ecf20Sopenharmony_ci gain_in_db = 24; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain), 18018c2ecf20Sopenharmony_ci MAKE_WM8775_DATA(gain)); 18028c2ecf20Sopenharmony_ci /* ...so there should be no need for the following. */ 18038c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain), 18048c2ecf20Sopenharmony_ci MAKE_WM8775_DATA(gain)); 18058c2ecf20Sopenharmony_ci} 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_cistatic int hw_adc_input_select(struct hw *hw, enum ADCSRC type) 18088c2ecf20Sopenharmony_ci{ 18098c2ecf20Sopenharmony_ci u32 data; 18108c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 18118c2ecf20Sopenharmony_ci switch (type) { 18128c2ecf20Sopenharmony_ci case ADC_MICIN: 18138c2ecf20Sopenharmony_ci data |= (0x1 << 14); 18148c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 18158c2ecf20Sopenharmony_ci hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */ 18168c2ecf20Sopenharmony_ci break; 18178c2ecf20Sopenharmony_ci case ADC_LINEIN: 18188c2ecf20Sopenharmony_ci data &= ~(0x1 << 14); 18198c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 18208c2ecf20Sopenharmony_ci hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */ 18218c2ecf20Sopenharmony_ci break; 18228c2ecf20Sopenharmony_ci default: 18238c2ecf20Sopenharmony_ci break; 18248c2ecf20Sopenharmony_ci } 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci return 0; 18278c2ecf20Sopenharmony_ci} 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_cistatic int hw_adc_init(struct hw *hw, const struct adc_conf *info) 18308c2ecf20Sopenharmony_ci{ 18318c2ecf20Sopenharmony_ci int err; 18328c2ecf20Sopenharmony_ci u32 data, ctl; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci /* Set ADC reset bit as output */ 18358c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_CTRL); 18368c2ecf20Sopenharmony_ci data |= (0x1 << 15); 18378c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_CTRL, data); 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci /* Initialize I2C */ 18408c2ecf20Sopenharmony_ci err = hw20k2_i2c_init(hw, 0x1A, 1, 1); 18418c2ecf20Sopenharmony_ci if (err < 0) { 18428c2ecf20Sopenharmony_ci dev_alert(hw->card->dev, "Failure to acquire I2C!!!\n"); 18438c2ecf20Sopenharmony_ci goto error; 18448c2ecf20Sopenharmony_ci } 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci /* Reset the ADC (reset is active low). */ 18478c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 18488c2ecf20Sopenharmony_ci data &= ~(0x1 << 15); 18498c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci if (hw->model == CTSB1270) { 18528c2ecf20Sopenharmony_ci /* Set up the PCM4220 ADC on Titanium HD */ 18538c2ecf20Sopenharmony_ci data &= ~0x0C; 18548c2ecf20Sopenharmony_ci if (1 == info->msr) 18558c2ecf20Sopenharmony_ci data |= 0x00; /* Single Speed Mode 32-50kHz */ 18568c2ecf20Sopenharmony_ci else if (2 == info->msr) 18578c2ecf20Sopenharmony_ci data |= 0x08; /* Double Speed Mode 50-108kHz */ 18588c2ecf20Sopenharmony_ci else 18598c2ecf20Sopenharmony_ci data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */ 18608c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 18618c2ecf20Sopenharmony_ci } 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci usleep_range(10000, 11000); 18648c2ecf20Sopenharmony_ci /* Return the ADC to normal operation. */ 18658c2ecf20Sopenharmony_ci data |= (0x1 << 15); 18668c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 18678c2ecf20Sopenharmony_ci msleep(50); 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ 18708c2ecf20Sopenharmony_ci /* invert bit, interface format to I2S, word length to 24-bit, */ 18718c2ecf20Sopenharmony_ci /* enable ADC high pass filter. Fixes bug 5323? */ 18728c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26), 18738c2ecf20Sopenharmony_ci MAKE_WM8775_DATA(0x26)); 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci /* Set the master mode (256fs) */ 18768c2ecf20Sopenharmony_ci if (1 == info->msr) { 18778c2ecf20Sopenharmony_ci /* slave mode, 128x oversampling 256fs */ 18788c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), 18798c2ecf20Sopenharmony_ci MAKE_WM8775_DATA(0x02)); 18808c2ecf20Sopenharmony_ci } else if ((2 == info->msr) || (4 == info->msr)) { 18818c2ecf20Sopenharmony_ci /* slave mode, 64x oversampling, 256fs */ 18828c2ecf20Sopenharmony_ci hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), 18838c2ecf20Sopenharmony_ci MAKE_WM8775_DATA(0x0A)); 18848c2ecf20Sopenharmony_ci } else { 18858c2ecf20Sopenharmony_ci dev_alert(hw->card->dev, 18868c2ecf20Sopenharmony_ci "Invalid master sampling rate (msr %d)!!!\n", 18878c2ecf20Sopenharmony_ci info->msr); 18888c2ecf20Sopenharmony_ci err = -EINVAL; 18898c2ecf20Sopenharmony_ci goto error; 18908c2ecf20Sopenharmony_ci } 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci if (hw->model != CTSB1270) { 18938c2ecf20Sopenharmony_ci /* Configure GPIO bit 14 change to line-in/mic-in */ 18948c2ecf20Sopenharmony_ci ctl = hw_read_20kx(hw, GPIO_CTRL); 18958c2ecf20Sopenharmony_ci ctl |= 0x1 << 14; 18968c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_CTRL, ctl); 18978c2ecf20Sopenharmony_ci hw_adc_input_select(hw, ADC_LINEIN); 18988c2ecf20Sopenharmony_ci } else { 18998c2ecf20Sopenharmony_ci hw_wm8775_input_select(hw, 0, 0); 19008c2ecf20Sopenharmony_ci } 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci return 0; 19038c2ecf20Sopenharmony_cierror: 19048c2ecf20Sopenharmony_ci hw20k2_i2c_uninit(hw); 19058c2ecf20Sopenharmony_ci return err; 19068c2ecf20Sopenharmony_ci} 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_cistatic struct capabilities hw_capabilities(struct hw *hw) 19098c2ecf20Sopenharmony_ci{ 19108c2ecf20Sopenharmony_ci struct capabilities cap; 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci cap.digit_io_switch = 0; 19138c2ecf20Sopenharmony_ci cap.dedicated_mic = hw->model == CTSB1270; 19148c2ecf20Sopenharmony_ci cap.output_switch = hw->model == CTSB1270; 19158c2ecf20Sopenharmony_ci cap.mic_source_switch = hw->model == CTSB1270; 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci return cap; 19188c2ecf20Sopenharmony_ci} 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_cistatic int hw_output_switch_get(struct hw *hw) 19218c2ecf20Sopenharmony_ci{ 19228c2ecf20Sopenharmony_ci u32 data = hw_read_20kx(hw, GPIO_EXT_DATA); 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci switch (data & 0x30) { 19258c2ecf20Sopenharmony_ci case 0x00: 19268c2ecf20Sopenharmony_ci return 0; 19278c2ecf20Sopenharmony_ci case 0x10: 19288c2ecf20Sopenharmony_ci return 1; 19298c2ecf20Sopenharmony_ci case 0x20: 19308c2ecf20Sopenharmony_ci return 2; 19318c2ecf20Sopenharmony_ci default: 19328c2ecf20Sopenharmony_ci return 3; 19338c2ecf20Sopenharmony_ci } 19348c2ecf20Sopenharmony_ci} 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_cistatic int hw_output_switch_put(struct hw *hw, int position) 19378c2ecf20Sopenharmony_ci{ 19388c2ecf20Sopenharmony_ci u32 data; 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci if (position == hw_output_switch_get(hw)) 19418c2ecf20Sopenharmony_ci return 0; 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci /* Mute line and headphones (intended for anti-pop). */ 19448c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 19458c2ecf20Sopenharmony_ci data |= (0x03 << 11); 19468c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30; 19498c2ecf20Sopenharmony_ci switch (position) { 19508c2ecf20Sopenharmony_ci case 0: 19518c2ecf20Sopenharmony_ci break; 19528c2ecf20Sopenharmony_ci case 1: 19538c2ecf20Sopenharmony_ci data |= 0x10; 19548c2ecf20Sopenharmony_ci break; 19558c2ecf20Sopenharmony_ci default: 19568c2ecf20Sopenharmony_ci data |= 0x20; 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_EXT_DATA, data); 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_ci /* Unmute line and headphones. */ 19618c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, GPIO_DATA); 19628c2ecf20Sopenharmony_ci data &= ~(0x03 << 11); 19638c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_DATA, data); 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci return 1; 19668c2ecf20Sopenharmony_ci} 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_cistatic int hw_mic_source_switch_get(struct hw *hw) 19698c2ecf20Sopenharmony_ci{ 19708c2ecf20Sopenharmony_ci struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci return hw20k2->mic_source; 19738c2ecf20Sopenharmony_ci} 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_cistatic int hw_mic_source_switch_put(struct hw *hw, int position) 19768c2ecf20Sopenharmony_ci{ 19778c2ecf20Sopenharmony_ci struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci if (position == hw20k2->mic_source) 19808c2ecf20Sopenharmony_ci return 0; 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci switch (position) { 19838c2ecf20Sopenharmony_ci case 0: 19848c2ecf20Sopenharmony_ci hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */ 19858c2ecf20Sopenharmony_ci break; 19868c2ecf20Sopenharmony_ci case 1: 19878c2ecf20Sopenharmony_ci hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */ 19888c2ecf20Sopenharmony_ci break; 19898c2ecf20Sopenharmony_ci case 2: 19908c2ecf20Sopenharmony_ci hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */ 19918c2ecf20Sopenharmony_ci break; 19928c2ecf20Sopenharmony_ci default: 19938c2ecf20Sopenharmony_ci return 0; 19948c2ecf20Sopenharmony_ci } 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci hw20k2->mic_source = position; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci return 1; 19998c2ecf20Sopenharmony_ci} 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_cistatic irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) 20028c2ecf20Sopenharmony_ci{ 20038c2ecf20Sopenharmony_ci struct hw *hw = dev_id; 20048c2ecf20Sopenharmony_ci unsigned int status; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci status = hw_read_20kx(hw, GIP); 20078c2ecf20Sopenharmony_ci if (!status) 20088c2ecf20Sopenharmony_ci return IRQ_NONE; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci if (hw->irq_callback) 20118c2ecf20Sopenharmony_ci hw->irq_callback(hw->irq_callback_data, status); 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci hw_write_20kx(hw, GIP, status); 20148c2ecf20Sopenharmony_ci return IRQ_HANDLED; 20158c2ecf20Sopenharmony_ci} 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_cistatic int hw_card_start(struct hw *hw) 20188c2ecf20Sopenharmony_ci{ 20198c2ecf20Sopenharmony_ci int err = 0; 20208c2ecf20Sopenharmony_ci struct pci_dev *pci = hw->pci; 20218c2ecf20Sopenharmony_ci unsigned int gctl; 20228c2ecf20Sopenharmony_ci const unsigned int dma_bits = BITS_PER_LONG; 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ci err = pci_enable_device(pci); 20258c2ecf20Sopenharmony_ci if (err < 0) 20268c2ecf20Sopenharmony_ci return err; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci /* Set DMA transfer mask */ 20298c2ecf20Sopenharmony_ci if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) { 20308c2ecf20Sopenharmony_ci dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits)); 20318c2ecf20Sopenharmony_ci } else { 20328c2ecf20Sopenharmony_ci dma_set_mask(&pci->dev, DMA_BIT_MASK(32)); 20338c2ecf20Sopenharmony_ci dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)); 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci if (!hw->io_base) { 20378c2ecf20Sopenharmony_ci err = pci_request_regions(pci, "XFi"); 20388c2ecf20Sopenharmony_ci if (err < 0) 20398c2ecf20Sopenharmony_ci goto error1; 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci hw->io_base = pci_resource_start(hw->pci, 2); 20428c2ecf20Sopenharmony_ci hw->mem_base = ioremap(hw->io_base, 20438c2ecf20Sopenharmony_ci pci_resource_len(hw->pci, 2)); 20448c2ecf20Sopenharmony_ci if (!hw->mem_base) { 20458c2ecf20Sopenharmony_ci err = -ENOENT; 20468c2ecf20Sopenharmony_ci goto error2; 20478c2ecf20Sopenharmony_ci } 20488c2ecf20Sopenharmony_ci } 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci /* Switch to 20k2 mode from UAA mode. */ 20518c2ecf20Sopenharmony_ci gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); 20528c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_UAA, 0); 20538c2ecf20Sopenharmony_ci hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci if (hw->irq < 0) { 20568c2ecf20Sopenharmony_ci err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, 20578c2ecf20Sopenharmony_ci KBUILD_MODNAME, hw); 20588c2ecf20Sopenharmony_ci if (err < 0) { 20598c2ecf20Sopenharmony_ci dev_err(hw->card->dev, 20608c2ecf20Sopenharmony_ci "XFi: Cannot get irq %d\n", pci->irq); 20618c2ecf20Sopenharmony_ci goto error2; 20628c2ecf20Sopenharmony_ci } 20638c2ecf20Sopenharmony_ci hw->irq = pci->irq; 20648c2ecf20Sopenharmony_ci hw->card->sync_irq = hw->irq; 20658c2ecf20Sopenharmony_ci } 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci pci_set_master(pci); 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_ci return 0; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci/*error3: 20728c2ecf20Sopenharmony_ci iounmap((void *)hw->mem_base); 20738c2ecf20Sopenharmony_ci hw->mem_base = (unsigned long)NULL;*/ 20748c2ecf20Sopenharmony_cierror2: 20758c2ecf20Sopenharmony_ci pci_release_regions(pci); 20768c2ecf20Sopenharmony_ci hw->io_base = 0; 20778c2ecf20Sopenharmony_cierror1: 20788c2ecf20Sopenharmony_ci pci_disable_device(pci); 20798c2ecf20Sopenharmony_ci return err; 20808c2ecf20Sopenharmony_ci} 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_cistatic int hw_card_stop(struct hw *hw) 20838c2ecf20Sopenharmony_ci{ 20848c2ecf20Sopenharmony_ci unsigned int data; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci /* disable transport bus master and queueing of request */ 20878c2ecf20Sopenharmony_ci hw_write_20kx(hw, TRANSPORT_CTL, 0x00); 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci /* disable pll */ 20908c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, PLL_ENB); 20918c2ecf20Sopenharmony_ci hw_write_20kx(hw, PLL_ENB, (data & (~0x07))); 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci /* TODO: Disable interrupt and so on... */ 20948c2ecf20Sopenharmony_ci return 0; 20958c2ecf20Sopenharmony_ci} 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_cistatic int hw_card_shutdown(struct hw *hw) 20988c2ecf20Sopenharmony_ci{ 20998c2ecf20Sopenharmony_ci if (hw->irq >= 0) 21008c2ecf20Sopenharmony_ci free_irq(hw->irq, hw); 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci hw->irq = -1; 21038c2ecf20Sopenharmony_ci iounmap(hw->mem_base); 21048c2ecf20Sopenharmony_ci hw->mem_base = NULL; 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci if (hw->io_base) 21078c2ecf20Sopenharmony_ci pci_release_regions(hw->pci); 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci hw->io_base = 0; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci pci_disable_device(hw->pci); 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ci return 0; 21148c2ecf20Sopenharmony_ci} 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_cistatic int hw_card_init(struct hw *hw, struct card_conf *info) 21178c2ecf20Sopenharmony_ci{ 21188c2ecf20Sopenharmony_ci int err; 21198c2ecf20Sopenharmony_ci unsigned int gctl; 21208c2ecf20Sopenharmony_ci u32 data = 0; 21218c2ecf20Sopenharmony_ci struct dac_conf dac_info = {0}; 21228c2ecf20Sopenharmony_ci struct adc_conf adc_info = {0}; 21238c2ecf20Sopenharmony_ci struct daio_conf daio_info = {0}; 21248c2ecf20Sopenharmony_ci struct trn_conf trn_info = {0}; 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci /* Get PCI io port/memory base address and 21278c2ecf20Sopenharmony_ci * do 20kx core switch if needed. */ 21288c2ecf20Sopenharmony_ci err = hw_card_start(hw); 21298c2ecf20Sopenharmony_ci if (err) 21308c2ecf20Sopenharmony_ci return err; 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci /* PLL init */ 21338c2ecf20Sopenharmony_ci err = hw_pll_init(hw, info->rsr); 21348c2ecf20Sopenharmony_ci if (err < 0) 21358c2ecf20Sopenharmony_ci return err; 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci /* kick off auto-init */ 21388c2ecf20Sopenharmony_ci err = hw_auto_init(hw); 21398c2ecf20Sopenharmony_ci if (err < 0) 21408c2ecf20Sopenharmony_ci return err; 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci gctl = hw_read_20kx(hw, GLOBAL_CNTL_GCTL); 21438c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_DBP, 1); 21448c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_TBP, 1); 21458c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_FBP, 1); 21468c2ecf20Sopenharmony_ci set_field(&gctl, GCTL_DPC, 0); 21478c2ecf20Sopenharmony_ci hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci /* Reset all global pending interrupts */ 21508c2ecf20Sopenharmony_ci hw_write_20kx(hw, GIE, 0); 21518c2ecf20Sopenharmony_ci /* Reset all SRC pending interrupts */ 21528c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_IP, 0); 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci if (hw->model != CTSB1270) { 21558c2ecf20Sopenharmony_ci /* TODO: detect the card ID and configure GPIO accordingly. */ 21568c2ecf20Sopenharmony_ci /* Configures GPIO (0xD802 0x98028) */ 21578c2ecf20Sopenharmony_ci /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ 21588c2ecf20Sopenharmony_ci /* Configures GPIO (SB0880) */ 21598c2ecf20Sopenharmony_ci /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ 21608c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_CTRL, 0xD802); 21618c2ecf20Sopenharmony_ci } else { 21628c2ecf20Sopenharmony_ci hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); 21638c2ecf20Sopenharmony_ci } 21648c2ecf20Sopenharmony_ci /* Enable audio ring */ 21658c2ecf20Sopenharmony_ci hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci trn_info.vm_pgt_phys = info->vm_pgt_phys; 21688c2ecf20Sopenharmony_ci err = hw_trn_init(hw, &trn_info); 21698c2ecf20Sopenharmony_ci if (err < 0) 21708c2ecf20Sopenharmony_ci return err; 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci daio_info.msr = info->msr; 21738c2ecf20Sopenharmony_ci err = hw_daio_init(hw, &daio_info); 21748c2ecf20Sopenharmony_ci if (err < 0) 21758c2ecf20Sopenharmony_ci return err; 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci dac_info.msr = info->msr; 21788c2ecf20Sopenharmony_ci err = hw_dac_init(hw, &dac_info); 21798c2ecf20Sopenharmony_ci if (err < 0) 21808c2ecf20Sopenharmony_ci return err; 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci adc_info.msr = info->msr; 21838c2ecf20Sopenharmony_ci adc_info.input = ADC_LINEIN; 21848c2ecf20Sopenharmony_ci adc_info.mic20db = 0; 21858c2ecf20Sopenharmony_ci err = hw_adc_init(hw, &adc_info); 21868c2ecf20Sopenharmony_ci if (err < 0) 21878c2ecf20Sopenharmony_ci return err; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci data = hw_read_20kx(hw, SRC_MCTL); 21908c2ecf20Sopenharmony_ci data |= 0x1; /* Enables input from the audio ring */ 21918c2ecf20Sopenharmony_ci hw_write_20kx(hw, SRC_MCTL, data); 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci return 0; 21948c2ecf20Sopenharmony_ci} 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 21978c2ecf20Sopenharmony_cistatic int hw_suspend(struct hw *hw) 21988c2ecf20Sopenharmony_ci{ 21998c2ecf20Sopenharmony_ci hw_card_stop(hw); 22008c2ecf20Sopenharmony_ci return 0; 22018c2ecf20Sopenharmony_ci} 22028c2ecf20Sopenharmony_ci 22038c2ecf20Sopenharmony_cistatic int hw_resume(struct hw *hw, struct card_conf *info) 22048c2ecf20Sopenharmony_ci{ 22058c2ecf20Sopenharmony_ci /* Re-initialize card hardware. */ 22068c2ecf20Sopenharmony_ci return hw_card_init(hw, info); 22078c2ecf20Sopenharmony_ci} 22088c2ecf20Sopenharmony_ci#endif 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_cistatic u32 hw_read_20kx(struct hw *hw, u32 reg) 22118c2ecf20Sopenharmony_ci{ 22128c2ecf20Sopenharmony_ci return readl(hw->mem_base + reg); 22138c2ecf20Sopenharmony_ci} 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_cistatic void hw_write_20kx(struct hw *hw, u32 reg, u32 data) 22168c2ecf20Sopenharmony_ci{ 22178c2ecf20Sopenharmony_ci writel(data, hw->mem_base + reg); 22188c2ecf20Sopenharmony_ci} 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_cistatic const struct hw ct20k2_preset = { 22218c2ecf20Sopenharmony_ci .irq = -1, 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_ci .card_init = hw_card_init, 22248c2ecf20Sopenharmony_ci .card_stop = hw_card_stop, 22258c2ecf20Sopenharmony_ci .pll_init = hw_pll_init, 22268c2ecf20Sopenharmony_ci .is_adc_source_selected = hw_is_adc_input_selected, 22278c2ecf20Sopenharmony_ci .select_adc_source = hw_adc_input_select, 22288c2ecf20Sopenharmony_ci .capabilities = hw_capabilities, 22298c2ecf20Sopenharmony_ci .output_switch_get = hw_output_switch_get, 22308c2ecf20Sopenharmony_ci .output_switch_put = hw_output_switch_put, 22318c2ecf20Sopenharmony_ci .mic_source_switch_get = hw_mic_source_switch_get, 22328c2ecf20Sopenharmony_ci .mic_source_switch_put = hw_mic_source_switch_put, 22338c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 22348c2ecf20Sopenharmony_ci .suspend = hw_suspend, 22358c2ecf20Sopenharmony_ci .resume = hw_resume, 22368c2ecf20Sopenharmony_ci#endif 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, 22398c2ecf20Sopenharmony_ci .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, 22408c2ecf20Sopenharmony_ci .src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk, 22418c2ecf20Sopenharmony_ci .src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk, 22428c2ecf20Sopenharmony_ci .src_set_state = src_set_state, 22438c2ecf20Sopenharmony_ci .src_set_bm = src_set_bm, 22448c2ecf20Sopenharmony_ci .src_set_rsr = src_set_rsr, 22458c2ecf20Sopenharmony_ci .src_set_sf = src_set_sf, 22468c2ecf20Sopenharmony_ci .src_set_wr = src_set_wr, 22478c2ecf20Sopenharmony_ci .src_set_pm = src_set_pm, 22488c2ecf20Sopenharmony_ci .src_set_rom = src_set_rom, 22498c2ecf20Sopenharmony_ci .src_set_vo = src_set_vo, 22508c2ecf20Sopenharmony_ci .src_set_st = src_set_st, 22518c2ecf20Sopenharmony_ci .src_set_ie = src_set_ie, 22528c2ecf20Sopenharmony_ci .src_set_ilsz = src_set_ilsz, 22538c2ecf20Sopenharmony_ci .src_set_bp = src_set_bp, 22548c2ecf20Sopenharmony_ci .src_set_cisz = src_set_cisz, 22558c2ecf20Sopenharmony_ci .src_set_ca = src_set_ca, 22568c2ecf20Sopenharmony_ci .src_set_sa = src_set_sa, 22578c2ecf20Sopenharmony_ci .src_set_la = src_set_la, 22588c2ecf20Sopenharmony_ci .src_set_pitch = src_set_pitch, 22598c2ecf20Sopenharmony_ci .src_set_dirty = src_set_dirty, 22608c2ecf20Sopenharmony_ci .src_set_clear_zbufs = src_set_clear_zbufs, 22618c2ecf20Sopenharmony_ci .src_set_dirty_all = src_set_dirty_all, 22628c2ecf20Sopenharmony_ci .src_commit_write = src_commit_write, 22638c2ecf20Sopenharmony_ci .src_get_ca = src_get_ca, 22648c2ecf20Sopenharmony_ci .src_get_dirty = src_get_dirty, 22658c2ecf20Sopenharmony_ci .src_dirty_conj_mask = src_dirty_conj_mask, 22668c2ecf20Sopenharmony_ci .src_mgr_enbs_src = src_mgr_enbs_src, 22678c2ecf20Sopenharmony_ci .src_mgr_enb_src = src_mgr_enb_src, 22688c2ecf20Sopenharmony_ci .src_mgr_dsb_src = src_mgr_dsb_src, 22698c2ecf20Sopenharmony_ci .src_mgr_commit_write = src_mgr_commit_write, 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci .srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk, 22728c2ecf20Sopenharmony_ci .srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk, 22738c2ecf20Sopenharmony_ci .srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc, 22748c2ecf20Sopenharmony_ci .srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser, 22758c2ecf20Sopenharmony_ci .srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt, 22768c2ecf20Sopenharmony_ci .srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr, 22778c2ecf20Sopenharmony_ci .srcimp_mgr_commit_write = srcimp_mgr_commit_write, 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci .amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk, 22808c2ecf20Sopenharmony_ci .amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk, 22818c2ecf20Sopenharmony_ci .amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk, 22828c2ecf20Sopenharmony_ci .amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk, 22838c2ecf20Sopenharmony_ci .amixer_set_mode = amixer_set_mode, 22848c2ecf20Sopenharmony_ci .amixer_set_iv = amixer_set_iv, 22858c2ecf20Sopenharmony_ci .amixer_set_x = amixer_set_x, 22868c2ecf20Sopenharmony_ci .amixer_set_y = amixer_set_y, 22878c2ecf20Sopenharmony_ci .amixer_set_sadr = amixer_set_sadr, 22888c2ecf20Sopenharmony_ci .amixer_set_se = amixer_set_se, 22898c2ecf20Sopenharmony_ci .amixer_set_dirty = amixer_set_dirty, 22908c2ecf20Sopenharmony_ci .amixer_set_dirty_all = amixer_set_dirty_all, 22918c2ecf20Sopenharmony_ci .amixer_commit_write = amixer_commit_write, 22928c2ecf20Sopenharmony_ci .amixer_get_y = amixer_get_y, 22938c2ecf20Sopenharmony_ci .amixer_get_dirty = amixer_get_dirty, 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci .dai_get_ctrl_blk = dai_get_ctrl_blk, 22968c2ecf20Sopenharmony_ci .dai_put_ctrl_blk = dai_put_ctrl_blk, 22978c2ecf20Sopenharmony_ci .dai_srt_set_srco = dai_srt_set_srco, 22988c2ecf20Sopenharmony_ci .dai_srt_set_srcm = dai_srt_set_srcm, 22998c2ecf20Sopenharmony_ci .dai_srt_set_rsr = dai_srt_set_rsr, 23008c2ecf20Sopenharmony_ci .dai_srt_set_drat = dai_srt_set_drat, 23018c2ecf20Sopenharmony_ci .dai_srt_set_ec = dai_srt_set_ec, 23028c2ecf20Sopenharmony_ci .dai_srt_set_et = dai_srt_set_et, 23038c2ecf20Sopenharmony_ci .dai_commit_write = dai_commit_write, 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci .dao_get_ctrl_blk = dao_get_ctrl_blk, 23068c2ecf20Sopenharmony_ci .dao_put_ctrl_blk = dao_put_ctrl_blk, 23078c2ecf20Sopenharmony_ci .dao_set_spos = dao_set_spos, 23088c2ecf20Sopenharmony_ci .dao_commit_write = dao_commit_write, 23098c2ecf20Sopenharmony_ci .dao_get_spos = dao_get_spos, 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci .daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk, 23128c2ecf20Sopenharmony_ci .daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk, 23138c2ecf20Sopenharmony_ci .daio_mgr_enb_dai = daio_mgr_enb_dai, 23148c2ecf20Sopenharmony_ci .daio_mgr_dsb_dai = daio_mgr_dsb_dai, 23158c2ecf20Sopenharmony_ci .daio_mgr_enb_dao = daio_mgr_enb_dao, 23168c2ecf20Sopenharmony_ci .daio_mgr_dsb_dao = daio_mgr_dsb_dao, 23178c2ecf20Sopenharmony_ci .daio_mgr_dao_init = daio_mgr_dao_init, 23188c2ecf20Sopenharmony_ci .daio_mgr_set_imaparc = daio_mgr_set_imaparc, 23198c2ecf20Sopenharmony_ci .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, 23208c2ecf20Sopenharmony_ci .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, 23218c2ecf20Sopenharmony_ci .daio_mgr_commit_write = daio_mgr_commit_write, 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci .set_timer_irq = set_timer_irq, 23248c2ecf20Sopenharmony_ci .set_timer_tick = set_timer_tick, 23258c2ecf20Sopenharmony_ci .get_wc = get_wc, 23268c2ecf20Sopenharmony_ci}; 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ciint create_20k2_hw_obj(struct hw **rhw) 23298c2ecf20Sopenharmony_ci{ 23308c2ecf20Sopenharmony_ci struct hw20k2 *hw20k2; 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci *rhw = NULL; 23338c2ecf20Sopenharmony_ci hw20k2 = kzalloc(sizeof(*hw20k2), GFP_KERNEL); 23348c2ecf20Sopenharmony_ci if (!hw20k2) 23358c2ecf20Sopenharmony_ci return -ENOMEM; 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci hw20k2->hw = ct20k2_preset; 23388c2ecf20Sopenharmony_ci *rhw = &hw20k2->hw; 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci return 0; 23418c2ecf20Sopenharmony_ci} 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ciint destroy_20k2_hw_obj(struct hw *hw) 23448c2ecf20Sopenharmony_ci{ 23458c2ecf20Sopenharmony_ci if (hw->io_base) 23468c2ecf20Sopenharmony_ci hw_card_shutdown(hw); 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci kfree(hw); 23498c2ecf20Sopenharmony_ci return 0; 23508c2ecf20Sopenharmony_ci} 2351