162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * @File cthw20k1.c 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * @Brief 862306a36Sopenharmony_ci * This file contains the implementation of hardware access methord for 20k1. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * @Author Liu Chun 1162306a36Sopenharmony_ci * @Date Jun 24 2008 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/pci.h> 1762306a36Sopenharmony_ci#include <linux/io.h> 1862306a36Sopenharmony_ci#include <linux/string.h> 1962306a36Sopenharmony_ci#include <linux/spinlock.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include <linux/interrupt.h> 2262306a36Sopenharmony_ci#include <linux/delay.h> 2362306a36Sopenharmony_ci#include "cthw20k1.h" 2462306a36Sopenharmony_ci#include "ct20k1reg.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct hw20k1 { 2762306a36Sopenharmony_ci struct hw hw; 2862306a36Sopenharmony_ci spinlock_t reg_20k1_lock; 2962306a36Sopenharmony_ci spinlock_t reg_pci_lock; 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic u32 hw_read_20kx(struct hw *hw, u32 reg); 3362306a36Sopenharmony_cistatic void hw_write_20kx(struct hw *hw, u32 reg, u32 data); 3462306a36Sopenharmony_cistatic u32 hw_read_pci(struct hw *hw, u32 reg); 3562306a36Sopenharmony_cistatic void hw_write_pci(struct hw *hw, u32 reg, u32 data); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* 3862306a36Sopenharmony_ci * Type definition block. 3962306a36Sopenharmony_ci * The layout of control structures can be directly applied on 20k2 chip. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * SRC control block definitions. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* SRC resource control block */ 4762306a36Sopenharmony_ci#define SRCCTL_STATE 0x00000007 4862306a36Sopenharmony_ci#define SRCCTL_BM 0x00000008 4962306a36Sopenharmony_ci#define SRCCTL_RSR 0x00000030 5062306a36Sopenharmony_ci#define SRCCTL_SF 0x000001C0 5162306a36Sopenharmony_ci#define SRCCTL_WR 0x00000200 5262306a36Sopenharmony_ci#define SRCCTL_PM 0x00000400 5362306a36Sopenharmony_ci#define SRCCTL_ROM 0x00001800 5462306a36Sopenharmony_ci#define SRCCTL_VO 0x00002000 5562306a36Sopenharmony_ci#define SRCCTL_ST 0x00004000 5662306a36Sopenharmony_ci#define SRCCTL_IE 0x00008000 5762306a36Sopenharmony_ci#define SRCCTL_ILSZ 0x000F0000 5862306a36Sopenharmony_ci#define SRCCTL_BP 0x00100000 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define SRCCCR_CISZ 0x000007FF 6162306a36Sopenharmony_ci#define SRCCCR_CWA 0x001FF800 6262306a36Sopenharmony_ci#define SRCCCR_D 0x00200000 6362306a36Sopenharmony_ci#define SRCCCR_RS 0x01C00000 6462306a36Sopenharmony_ci#define SRCCCR_NAL 0x3E000000 6562306a36Sopenharmony_ci#define SRCCCR_RA 0xC0000000 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define SRCCA_CA 0x03FFFFFF 6862306a36Sopenharmony_ci#define SRCCA_RS 0x1C000000 6962306a36Sopenharmony_ci#define SRCCA_NAL 0xE0000000 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#define SRCSA_SA 0x03FFFFFF 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define SRCLA_LA 0x03FFFFFF 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* Mixer Parameter Ring ram Low and Hight register. 7662306a36Sopenharmony_ci * Fixed-point value in 8.24 format for parameter channel */ 7762306a36Sopenharmony_ci#define MPRLH_PITCH 0xFFFFFFFF 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* SRC resource register dirty flags */ 8062306a36Sopenharmony_ciunion src_dirty { 8162306a36Sopenharmony_ci struct { 8262306a36Sopenharmony_ci u16 ctl:1; 8362306a36Sopenharmony_ci u16 ccr:1; 8462306a36Sopenharmony_ci u16 sa:1; 8562306a36Sopenharmony_ci u16 la:1; 8662306a36Sopenharmony_ci u16 ca:1; 8762306a36Sopenharmony_ci u16 mpr:1; 8862306a36Sopenharmony_ci u16 czbfs:1; /* Clear Z-Buffers */ 8962306a36Sopenharmony_ci u16 rsv:9; 9062306a36Sopenharmony_ci } bf; 9162306a36Sopenharmony_ci u16 data; 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistruct src_rsc_ctrl_blk { 9562306a36Sopenharmony_ci unsigned int ctl; 9662306a36Sopenharmony_ci unsigned int ccr; 9762306a36Sopenharmony_ci unsigned int ca; 9862306a36Sopenharmony_ci unsigned int sa; 9962306a36Sopenharmony_ci unsigned int la; 10062306a36Sopenharmony_ci unsigned int mpr; 10162306a36Sopenharmony_ci union src_dirty dirty; 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* SRC manager control block */ 10562306a36Sopenharmony_ciunion src_mgr_dirty { 10662306a36Sopenharmony_ci struct { 10762306a36Sopenharmony_ci u16 enb0:1; 10862306a36Sopenharmony_ci u16 enb1:1; 10962306a36Sopenharmony_ci u16 enb2:1; 11062306a36Sopenharmony_ci u16 enb3:1; 11162306a36Sopenharmony_ci u16 enb4:1; 11262306a36Sopenharmony_ci u16 enb5:1; 11362306a36Sopenharmony_ci u16 enb6:1; 11462306a36Sopenharmony_ci u16 enb7:1; 11562306a36Sopenharmony_ci u16 enbsa:1; 11662306a36Sopenharmony_ci u16 rsv:7; 11762306a36Sopenharmony_ci } bf; 11862306a36Sopenharmony_ci u16 data; 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistruct src_mgr_ctrl_blk { 12262306a36Sopenharmony_ci unsigned int enbsa; 12362306a36Sopenharmony_ci unsigned int enb[8]; 12462306a36Sopenharmony_ci union src_mgr_dirty dirty; 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/* SRCIMP manager control block */ 12862306a36Sopenharmony_ci#define SRCAIM_ARC 0x00000FFF 12962306a36Sopenharmony_ci#define SRCAIM_NXT 0x00FF0000 13062306a36Sopenharmony_ci#define SRCAIM_SRC 0xFF000000 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistruct srcimap { 13362306a36Sopenharmony_ci unsigned int srcaim; 13462306a36Sopenharmony_ci unsigned int idx; 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* SRCIMP manager register dirty flags */ 13862306a36Sopenharmony_ciunion srcimp_mgr_dirty { 13962306a36Sopenharmony_ci struct { 14062306a36Sopenharmony_ci u16 srcimap:1; 14162306a36Sopenharmony_ci u16 rsv:15; 14262306a36Sopenharmony_ci } bf; 14362306a36Sopenharmony_ci u16 data; 14462306a36Sopenharmony_ci}; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistruct srcimp_mgr_ctrl_blk { 14762306a36Sopenharmony_ci struct srcimap srcimap; 14862306a36Sopenharmony_ci union srcimp_mgr_dirty dirty; 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci/* 15262306a36Sopenharmony_ci * Function implementation block. 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int src_get_rsc_ctrl_blk(void **rblk) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci struct src_rsc_ctrl_blk *blk; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci *rblk = NULL; 16062306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 16162306a36Sopenharmony_ci if (!blk) 16262306a36Sopenharmony_ci return -ENOMEM; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci *rblk = blk; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic int src_put_rsc_ctrl_blk(void *blk) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci kfree(blk); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return 0; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic int src_set_state(void *blk, unsigned int state) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_STATE, state); 18162306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic int src_set_bm(void *blk, unsigned int bm) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_BM, bm); 19062306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic int src_set_rsr(void *blk, unsigned int rsr) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_RSR, rsr); 19962306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 20062306a36Sopenharmony_ci return 0; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic int src_set_sf(void *blk, unsigned int sf) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_SF, sf); 20862306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 20962306a36Sopenharmony_ci return 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic int src_set_wr(void *blk, unsigned int wr) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_WR, wr); 21762306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 21862306a36Sopenharmony_ci return 0; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic int src_set_pm(void *blk, unsigned int pm) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_PM, pm); 22662306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 22762306a36Sopenharmony_ci return 0; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic int src_set_rom(void *blk, unsigned int rom) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_ROM, rom); 23562306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 23662306a36Sopenharmony_ci return 0; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic int src_set_vo(void *blk, unsigned int vo) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_VO, vo); 24462306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 24562306a36Sopenharmony_ci return 0; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic int src_set_st(void *blk, unsigned int st) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_ST, st); 25362306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 25462306a36Sopenharmony_ci return 0; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic int src_set_ie(void *blk, unsigned int ie) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_IE, ie); 26262306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 26362306a36Sopenharmony_ci return 0; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int src_set_ilsz(void *blk, unsigned int ilsz) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_ILSZ, ilsz); 27162306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 27262306a36Sopenharmony_ci return 0; 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cistatic int src_set_bp(void *blk, unsigned int bp) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci set_field(&ctl->ctl, SRCCTL_BP, bp); 28062306a36Sopenharmony_ci ctl->dirty.bf.ctl = 1; 28162306a36Sopenharmony_ci return 0; 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic int src_set_cisz(void *blk, unsigned int cisz) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci set_field(&ctl->ccr, SRCCCR_CISZ, cisz); 28962306a36Sopenharmony_ci ctl->dirty.bf.ccr = 1; 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic int src_set_ca(void *blk, unsigned int ca) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci set_field(&ctl->ca, SRCCA_CA, ca); 29862306a36Sopenharmony_ci ctl->dirty.bf.ca = 1; 29962306a36Sopenharmony_ci return 0; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic int src_set_sa(void *blk, unsigned int sa) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci set_field(&ctl->sa, SRCSA_SA, sa); 30762306a36Sopenharmony_ci ctl->dirty.bf.sa = 1; 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic int src_set_la(void *blk, unsigned int la) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci set_field(&ctl->la, SRCLA_LA, la); 31662306a36Sopenharmony_ci ctl->dirty.bf.la = 1; 31762306a36Sopenharmony_ci return 0; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic int src_set_pitch(void *blk, unsigned int pitch) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci set_field(&ctl->mpr, MPRLH_PITCH, pitch); 32562306a36Sopenharmony_ci ctl->dirty.bf.mpr = 1; 32662306a36Sopenharmony_ci return 0; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic int src_set_clear_zbufs(void *blk, unsigned int clear) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci ((struct src_rsc_ctrl_blk *)blk)->dirty.bf.czbfs = (clear ? 1 : 0); 33262306a36Sopenharmony_ci return 0; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int src_set_dirty(void *blk, unsigned int flags) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci ((struct src_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic int src_set_dirty_all(void *blk) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci ((struct src_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci#define AR_SLOT_SIZE 4096 34862306a36Sopenharmony_ci#define AR_SLOT_BLOCK_SIZE 16 34962306a36Sopenharmony_ci#define AR_PTS_PITCH 6 35062306a36Sopenharmony_ci#define AR_PARAM_SRC_OFFSET 0x60 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic unsigned int src_param_pitch_mixer(unsigned int src_idx) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci return ((src_idx << 4) + AR_PTS_PITCH + AR_SLOT_SIZE 35562306a36Sopenharmony_ci - AR_PARAM_SRC_OFFSET) % AR_SLOT_SIZE; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic int src_commit_write(struct hw *hw, unsigned int idx, void *blk) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 36262306a36Sopenharmony_ci int i; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (ctl->dirty.bf.czbfs) { 36562306a36Sopenharmony_ci /* Clear Z-Buffer registers */ 36662306a36Sopenharmony_ci for (i = 0; i < 8; i++) 36762306a36Sopenharmony_ci hw_write_20kx(hw, SRCUPZ+idx*0x100+i*0x4, 0); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci for (i = 0; i < 4; i++) 37062306a36Sopenharmony_ci hw_write_20kx(hw, SRCDN0Z+idx*0x100+i*0x4, 0); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci for (i = 0; i < 8; i++) 37362306a36Sopenharmony_ci hw_write_20kx(hw, SRCDN1Z+idx*0x100+i*0x4, 0); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci ctl->dirty.bf.czbfs = 0; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci if (ctl->dirty.bf.mpr) { 37862306a36Sopenharmony_ci /* Take the parameter mixer resource in the same group as that 37962306a36Sopenharmony_ci * the idx src is in for simplicity. Unlike src, all conjugate 38062306a36Sopenharmony_ci * parameter mixer resources must be programmed for 38162306a36Sopenharmony_ci * corresponding conjugate src resources. */ 38262306a36Sopenharmony_ci unsigned int pm_idx = src_param_pitch_mixer(idx); 38362306a36Sopenharmony_ci hw_write_20kx(hw, PRING_LO_HI+4*pm_idx, ctl->mpr); 38462306a36Sopenharmony_ci hw_write_20kx(hw, PMOPLO+8*pm_idx, 0x3); 38562306a36Sopenharmony_ci hw_write_20kx(hw, PMOPHI+8*pm_idx, 0x0); 38662306a36Sopenharmony_ci ctl->dirty.bf.mpr = 0; 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci if (ctl->dirty.bf.sa) { 38962306a36Sopenharmony_ci hw_write_20kx(hw, SRCSA+idx*0x100, ctl->sa); 39062306a36Sopenharmony_ci ctl->dirty.bf.sa = 0; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci if (ctl->dirty.bf.la) { 39362306a36Sopenharmony_ci hw_write_20kx(hw, SRCLA+idx*0x100, ctl->la); 39462306a36Sopenharmony_ci ctl->dirty.bf.la = 0; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci if (ctl->dirty.bf.ca) { 39762306a36Sopenharmony_ci hw_write_20kx(hw, SRCCA+idx*0x100, ctl->ca); 39862306a36Sopenharmony_ci ctl->dirty.bf.ca = 0; 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* Write srccf register */ 40262306a36Sopenharmony_ci hw_write_20kx(hw, SRCCF+idx*0x100, 0x0); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (ctl->dirty.bf.ccr) { 40562306a36Sopenharmony_ci hw_write_20kx(hw, SRCCCR+idx*0x100, ctl->ccr); 40662306a36Sopenharmony_ci ctl->dirty.bf.ccr = 0; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci if (ctl->dirty.bf.ctl) { 40962306a36Sopenharmony_ci hw_write_20kx(hw, SRCCTL+idx*0x100, ctl->ctl); 41062306a36Sopenharmony_ci ctl->dirty.bf.ctl = 0; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci return 0; 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_cistatic int src_get_ca(struct hw *hw, unsigned int idx, void *blk) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci struct src_rsc_ctrl_blk *ctl = blk; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci ctl->ca = hw_read_20kx(hw, SRCCA+idx*0x100); 42162306a36Sopenharmony_ci ctl->dirty.bf.ca = 0; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci return get_field(ctl->ca, SRCCA_CA); 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic unsigned int src_get_dirty(void *blk) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci return ((struct src_rsc_ctrl_blk *)blk)->dirty.data; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic unsigned int src_dirty_conj_mask(void) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci return 0x20; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int src_mgr_enbs_src(void *blk, unsigned int idx) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->enbsa = ~(0x0); 43962306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->dirty.bf.enbsa = 1; 44062306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic int src_mgr_enb_src(void *blk, unsigned int idx) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] |= (0x1 << (idx%32)); 44762306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic int src_mgr_dsb_src(void *blk, unsigned int idx) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->enb[idx/32] &= ~(0x1 << (idx%32)); 45462306a36Sopenharmony_ci ((struct src_mgr_ctrl_blk *)blk)->dirty.data |= (0x1 << (idx/32)); 45562306a36Sopenharmony_ci return 0; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic int src_mgr_commit_write(struct hw *hw, void *blk) 45962306a36Sopenharmony_ci{ 46062306a36Sopenharmony_ci struct src_mgr_ctrl_blk *ctl = blk; 46162306a36Sopenharmony_ci int i; 46262306a36Sopenharmony_ci unsigned int ret; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci if (ctl->dirty.bf.enbsa) { 46562306a36Sopenharmony_ci do { 46662306a36Sopenharmony_ci ret = hw_read_20kx(hw, SRCENBSTAT); 46762306a36Sopenharmony_ci } while (ret & 0x1); 46862306a36Sopenharmony_ci hw_write_20kx(hw, SRCENBS, ctl->enbsa); 46962306a36Sopenharmony_ci ctl->dirty.bf.enbsa = 0; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 47262306a36Sopenharmony_ci if ((ctl->dirty.data & (0x1 << i))) { 47362306a36Sopenharmony_ci hw_write_20kx(hw, SRCENB+(i*0x100), ctl->enb[i]); 47462306a36Sopenharmony_ci ctl->dirty.data &= ~(0x1 << i); 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci return 0; 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic int src_mgr_get_ctrl_blk(void **rblk) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci struct src_mgr_ctrl_blk *blk; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci *rblk = NULL; 48662306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 48762306a36Sopenharmony_ci if (!blk) 48862306a36Sopenharmony_ci return -ENOMEM; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci *rblk = blk; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci return 0; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic int src_mgr_put_ctrl_blk(void *blk) 49662306a36Sopenharmony_ci{ 49762306a36Sopenharmony_ci kfree(blk); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci return 0; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic int srcimp_mgr_get_ctrl_blk(void **rblk) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci struct srcimp_mgr_ctrl_blk *blk; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci *rblk = NULL; 50762306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 50862306a36Sopenharmony_ci if (!blk) 50962306a36Sopenharmony_ci return -ENOMEM; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci *rblk = blk; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci return 0; 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic int srcimp_mgr_put_ctrl_blk(void *blk) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci kfree(blk); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci return 0; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic int srcimp_mgr_set_imaparc(void *blk, unsigned int slot) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci struct srcimp_mgr_ctrl_blk *ctl = blk; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci set_field(&ctl->srcimap.srcaim, SRCAIM_ARC, slot); 52862306a36Sopenharmony_ci ctl->dirty.bf.srcimap = 1; 52962306a36Sopenharmony_ci return 0; 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic int srcimp_mgr_set_imapuser(void *blk, unsigned int user) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci struct srcimp_mgr_ctrl_blk *ctl = blk; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci set_field(&ctl->srcimap.srcaim, SRCAIM_SRC, user); 53762306a36Sopenharmony_ci ctl->dirty.bf.srcimap = 1; 53862306a36Sopenharmony_ci return 0; 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic int srcimp_mgr_set_imapnxt(void *blk, unsigned int next) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci struct srcimp_mgr_ctrl_blk *ctl = blk; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci set_field(&ctl->srcimap.srcaim, SRCAIM_NXT, next); 54662306a36Sopenharmony_ci ctl->dirty.bf.srcimap = 1; 54762306a36Sopenharmony_ci return 0; 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic int srcimp_mgr_set_imapaddr(void *blk, unsigned int addr) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci struct srcimp_mgr_ctrl_blk *ctl = blk; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci ctl->srcimap.idx = addr; 55562306a36Sopenharmony_ci ctl->dirty.bf.srcimap = 1; 55662306a36Sopenharmony_ci return 0; 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cistatic int srcimp_mgr_commit_write(struct hw *hw, void *blk) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci struct srcimp_mgr_ctrl_blk *ctl = blk; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (ctl->dirty.bf.srcimap) { 56462306a36Sopenharmony_ci hw_write_20kx(hw, SRCIMAP+ctl->srcimap.idx*0x100, 56562306a36Sopenharmony_ci ctl->srcimap.srcaim); 56662306a36Sopenharmony_ci ctl->dirty.bf.srcimap = 0; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return 0; 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci/* 57362306a36Sopenharmony_ci * AMIXER control block definitions. 57462306a36Sopenharmony_ci */ 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci#define AMOPLO_M 0x00000003 57762306a36Sopenharmony_ci#define AMOPLO_X 0x0003FFF0 57862306a36Sopenharmony_ci#define AMOPLO_Y 0xFFFC0000 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci#define AMOPHI_SADR 0x000000FF 58162306a36Sopenharmony_ci#define AMOPHI_SE 0x80000000 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci/* AMIXER resource register dirty flags */ 58462306a36Sopenharmony_ciunion amixer_dirty { 58562306a36Sopenharmony_ci struct { 58662306a36Sopenharmony_ci u16 amoplo:1; 58762306a36Sopenharmony_ci u16 amophi:1; 58862306a36Sopenharmony_ci u16 rsv:14; 58962306a36Sopenharmony_ci } bf; 59062306a36Sopenharmony_ci u16 data; 59162306a36Sopenharmony_ci}; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci/* AMIXER resource control block */ 59462306a36Sopenharmony_cistruct amixer_rsc_ctrl_blk { 59562306a36Sopenharmony_ci unsigned int amoplo; 59662306a36Sopenharmony_ci unsigned int amophi; 59762306a36Sopenharmony_ci union amixer_dirty dirty; 59862306a36Sopenharmony_ci}; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic int amixer_set_mode(void *blk, unsigned int mode) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_M, mode); 60562306a36Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 60662306a36Sopenharmony_ci return 0; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic int amixer_set_iv(void *blk, unsigned int iv) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci /* 20k1 amixer does not have this field */ 61262306a36Sopenharmony_ci return 0; 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic int amixer_set_x(void *blk, unsigned int x) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_X, x); 62062306a36Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 62162306a36Sopenharmony_ci return 0; 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistatic int amixer_set_y(void *blk, unsigned int y) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci set_field(&ctl->amoplo, AMOPLO_Y, y); 62962306a36Sopenharmony_ci ctl->dirty.bf.amoplo = 1; 63062306a36Sopenharmony_ci return 0; 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic int amixer_set_sadr(void *blk, unsigned int sadr) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci set_field(&ctl->amophi, AMOPHI_SADR, sadr); 63862306a36Sopenharmony_ci ctl->dirty.bf.amophi = 1; 63962306a36Sopenharmony_ci return 0; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic int amixer_set_se(void *blk, unsigned int se) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci set_field(&ctl->amophi, AMOPHI_SE, se); 64762306a36Sopenharmony_ci ctl->dirty.bf.amophi = 1; 64862306a36Sopenharmony_ci return 0; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic int amixer_set_dirty(void *blk, unsigned int flags) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = (flags & 0xffff); 65462306a36Sopenharmony_ci return 0; 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic int amixer_set_dirty_all(void *blk) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data = ~(0x0); 66062306a36Sopenharmony_ci return 0; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic int amixer_commit_write(struct hw *hw, unsigned int idx, void *blk) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (ctl->dirty.bf.amoplo || ctl->dirty.bf.amophi) { 66862306a36Sopenharmony_ci hw_write_20kx(hw, AMOPLO+idx*8, ctl->amoplo); 66962306a36Sopenharmony_ci ctl->dirty.bf.amoplo = 0; 67062306a36Sopenharmony_ci hw_write_20kx(hw, AMOPHI+idx*8, ctl->amophi); 67162306a36Sopenharmony_ci ctl->dirty.bf.amophi = 0; 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci return 0; 67562306a36Sopenharmony_ci} 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_cistatic int amixer_get_y(void *blk) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *ctl = blk; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci return get_field(ctl->amoplo, AMOPLO_Y); 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic unsigned int amixer_get_dirty(void *blk) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci return ((struct amixer_rsc_ctrl_blk *)blk)->dirty.data; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic int amixer_rsc_get_ctrl_blk(void **rblk) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci struct amixer_rsc_ctrl_blk *blk; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci *rblk = NULL; 69462306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 69562306a36Sopenharmony_ci if (!blk) 69662306a36Sopenharmony_ci return -ENOMEM; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci *rblk = blk; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci return 0; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic int amixer_rsc_put_ctrl_blk(void *blk) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci kfree(blk); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci return 0; 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic int amixer_mgr_get_ctrl_blk(void **rblk) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci /*amixer_mgr_ctrl_blk_t *blk;*/ 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci *rblk = NULL; 71562306a36Sopenharmony_ci /*blk = kzalloc(sizeof(*blk), GFP_KERNEL); 71662306a36Sopenharmony_ci if (!blk) 71762306a36Sopenharmony_ci return -ENOMEM; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci *rblk = blk;*/ 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci return 0; 72262306a36Sopenharmony_ci} 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_cistatic int amixer_mgr_put_ctrl_blk(void *blk) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci /*kfree((amixer_mgr_ctrl_blk_t *)blk);*/ 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci return 0; 72962306a36Sopenharmony_ci} 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci/* 73262306a36Sopenharmony_ci * DAIO control block definitions. 73362306a36Sopenharmony_ci */ 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci/* Receiver Sample Rate Tracker Control register */ 73662306a36Sopenharmony_ci#define SRTCTL_SRCR 0x000000FF 73762306a36Sopenharmony_ci#define SRTCTL_SRCL 0x0000FF00 73862306a36Sopenharmony_ci#define SRTCTL_RSR 0x00030000 73962306a36Sopenharmony_ci#define SRTCTL_DRAT 0x000C0000 74062306a36Sopenharmony_ci#define SRTCTL_RLE 0x10000000 74162306a36Sopenharmony_ci#define SRTCTL_RLP 0x20000000 74262306a36Sopenharmony_ci#define SRTCTL_EC 0x40000000 74362306a36Sopenharmony_ci#define SRTCTL_ET 0x80000000 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci/* DAIO Receiver register dirty flags */ 74662306a36Sopenharmony_ciunion dai_dirty { 74762306a36Sopenharmony_ci struct { 74862306a36Sopenharmony_ci u16 srtctl:1; 74962306a36Sopenharmony_ci u16 rsv:15; 75062306a36Sopenharmony_ci } bf; 75162306a36Sopenharmony_ci u16 data; 75262306a36Sopenharmony_ci}; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci/* DAIO Receiver control block */ 75562306a36Sopenharmony_cistruct dai_ctrl_blk { 75662306a36Sopenharmony_ci unsigned int srtctl; 75762306a36Sopenharmony_ci union dai_dirty dirty; 75862306a36Sopenharmony_ci}; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci/* S/PDIF Transmitter register dirty flags */ 76162306a36Sopenharmony_ciunion dao_dirty { 76262306a36Sopenharmony_ci struct { 76362306a36Sopenharmony_ci u16 spos:1; 76462306a36Sopenharmony_ci u16 rsv:15; 76562306a36Sopenharmony_ci } bf; 76662306a36Sopenharmony_ci u16 data; 76762306a36Sopenharmony_ci}; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci/* S/PDIF Transmitter control block */ 77062306a36Sopenharmony_cistruct dao_ctrl_blk { 77162306a36Sopenharmony_ci unsigned int spos; /* S/PDIF Output Channel Status Register */ 77262306a36Sopenharmony_ci union dao_dirty dirty; 77362306a36Sopenharmony_ci}; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci/* Audio Input Mapper RAM */ 77662306a36Sopenharmony_ci#define AIM_ARC 0x00000FFF 77762306a36Sopenharmony_ci#define AIM_NXT 0x007F0000 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_cistruct daoimap { 78062306a36Sopenharmony_ci unsigned int aim; 78162306a36Sopenharmony_ci unsigned int idx; 78262306a36Sopenharmony_ci}; 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci/* I2S Transmitter/Receiver Control register */ 78562306a36Sopenharmony_ci#define I2SCTL_EA 0x00000004 78662306a36Sopenharmony_ci#define I2SCTL_EI 0x00000010 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci/* S/PDIF Transmitter Control register */ 78962306a36Sopenharmony_ci#define SPOCTL_OE 0x00000001 79062306a36Sopenharmony_ci#define SPOCTL_OS 0x0000000E 79162306a36Sopenharmony_ci#define SPOCTL_RIV 0x00000010 79262306a36Sopenharmony_ci#define SPOCTL_LIV 0x00000020 79362306a36Sopenharmony_ci#define SPOCTL_SR 0x000000C0 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci/* S/PDIF Receiver Control register */ 79662306a36Sopenharmony_ci#define SPICTL_EN 0x00000001 79762306a36Sopenharmony_ci#define SPICTL_I24 0x00000002 79862306a36Sopenharmony_ci#define SPICTL_IB 0x00000004 79962306a36Sopenharmony_ci#define SPICTL_SM 0x00000008 80062306a36Sopenharmony_ci#define SPICTL_VM 0x00000010 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci/* DAIO manager register dirty flags */ 80362306a36Sopenharmony_ciunion daio_mgr_dirty { 80462306a36Sopenharmony_ci struct { 80562306a36Sopenharmony_ci u32 i2soctl:4; 80662306a36Sopenharmony_ci u32 i2sictl:4; 80762306a36Sopenharmony_ci u32 spoctl:4; 80862306a36Sopenharmony_ci u32 spictl:4; 80962306a36Sopenharmony_ci u32 daoimap:1; 81062306a36Sopenharmony_ci u32 rsv:15; 81162306a36Sopenharmony_ci } bf; 81262306a36Sopenharmony_ci u32 data; 81362306a36Sopenharmony_ci}; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci/* DAIO manager control block */ 81662306a36Sopenharmony_cistruct daio_mgr_ctrl_blk { 81762306a36Sopenharmony_ci unsigned int i2sctl; 81862306a36Sopenharmony_ci unsigned int spoctl; 81962306a36Sopenharmony_ci unsigned int spictl; 82062306a36Sopenharmony_ci struct daoimap daoimap; 82162306a36Sopenharmony_ci union daio_mgr_dirty dirty; 82262306a36Sopenharmony_ci}; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_cistatic int dai_srt_set_srcr(void *blk, unsigned int src) 82562306a36Sopenharmony_ci{ 82662306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci set_field(&ctl->srtctl, SRTCTL_SRCR, src); 82962306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 1; 83062306a36Sopenharmony_ci return 0; 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_cistatic int dai_srt_set_srcl(void *blk, unsigned int src) 83462306a36Sopenharmony_ci{ 83562306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci set_field(&ctl->srtctl, SRTCTL_SRCL, src); 83862306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 1; 83962306a36Sopenharmony_ci return 0; 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_cistatic int dai_srt_set_rsr(void *blk, unsigned int rsr) 84362306a36Sopenharmony_ci{ 84462306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci set_field(&ctl->srtctl, SRTCTL_RSR, rsr); 84762306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 1; 84862306a36Sopenharmony_ci return 0; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic int dai_srt_set_drat(void *blk, unsigned int drat) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci set_field(&ctl->srtctl, SRTCTL_DRAT, drat); 85662306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 1; 85762306a36Sopenharmony_ci return 0; 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_cistatic int dai_srt_set_ec(void *blk, unsigned int ec) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci set_field(&ctl->srtctl, SRTCTL_EC, ec ? 1 : 0); 86562306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 1; 86662306a36Sopenharmony_ci return 0; 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic int dai_srt_set_et(void *blk, unsigned int et) 87062306a36Sopenharmony_ci{ 87162306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci set_field(&ctl->srtctl, SRTCTL_ET, et ? 1 : 0); 87462306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 1; 87562306a36Sopenharmony_ci return 0; 87662306a36Sopenharmony_ci} 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_cistatic int dai_commit_write(struct hw *hw, unsigned int idx, void *blk) 87962306a36Sopenharmony_ci{ 88062306a36Sopenharmony_ci struct dai_ctrl_blk *ctl = blk; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci if (ctl->dirty.bf.srtctl) { 88362306a36Sopenharmony_ci if (idx < 4) { 88462306a36Sopenharmony_ci /* S/PDIF SRTs */ 88562306a36Sopenharmony_ci hw_write_20kx(hw, SRTSCTL+0x4*idx, ctl->srtctl); 88662306a36Sopenharmony_ci } else { 88762306a36Sopenharmony_ci /* I2S SRT */ 88862306a36Sopenharmony_ci hw_write_20kx(hw, SRTICTL, ctl->srtctl); 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci ctl->dirty.bf.srtctl = 0; 89162306a36Sopenharmony_ci } 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci return 0; 89462306a36Sopenharmony_ci} 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_cistatic int dai_get_ctrl_blk(void **rblk) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct dai_ctrl_blk *blk; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci *rblk = NULL; 90162306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 90262306a36Sopenharmony_ci if (!blk) 90362306a36Sopenharmony_ci return -ENOMEM; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci *rblk = blk; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci return 0; 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_cistatic int dai_put_ctrl_blk(void *blk) 91162306a36Sopenharmony_ci{ 91262306a36Sopenharmony_ci kfree(blk); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci return 0; 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_cistatic int dao_set_spos(void *blk, unsigned int spos) 91862306a36Sopenharmony_ci{ 91962306a36Sopenharmony_ci ((struct dao_ctrl_blk *)blk)->spos = spos; 92062306a36Sopenharmony_ci ((struct dao_ctrl_blk *)blk)->dirty.bf.spos = 1; 92162306a36Sopenharmony_ci return 0; 92262306a36Sopenharmony_ci} 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_cistatic int dao_commit_write(struct hw *hw, unsigned int idx, void *blk) 92562306a36Sopenharmony_ci{ 92662306a36Sopenharmony_ci struct dao_ctrl_blk *ctl = blk; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (ctl->dirty.bf.spos) { 92962306a36Sopenharmony_ci if (idx < 4) { 93062306a36Sopenharmony_ci /* S/PDIF SPOSx */ 93162306a36Sopenharmony_ci hw_write_20kx(hw, SPOS+0x4*idx, ctl->spos); 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci ctl->dirty.bf.spos = 0; 93462306a36Sopenharmony_ci } 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci return 0; 93762306a36Sopenharmony_ci} 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_cistatic int dao_get_spos(void *blk, unsigned int *spos) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci *spos = ((struct dao_ctrl_blk *)blk)->spos; 94262306a36Sopenharmony_ci return 0; 94362306a36Sopenharmony_ci} 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_cistatic int dao_get_ctrl_blk(void **rblk) 94662306a36Sopenharmony_ci{ 94762306a36Sopenharmony_ci struct dao_ctrl_blk *blk; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci *rblk = NULL; 95062306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 95162306a36Sopenharmony_ci if (!blk) 95262306a36Sopenharmony_ci return -ENOMEM; 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci *rblk = blk; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci return 0; 95762306a36Sopenharmony_ci} 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_cistatic int dao_put_ctrl_blk(void *blk) 96062306a36Sopenharmony_ci{ 96162306a36Sopenharmony_ci kfree(blk); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci return 0; 96462306a36Sopenharmony_ci} 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_cistatic int daio_mgr_enb_dai(void *blk, unsigned int idx) 96762306a36Sopenharmony_ci{ 96862306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci if (idx < 4) { 97162306a36Sopenharmony_ci /* S/PDIF input */ 97262306a36Sopenharmony_ci set_field(&ctl->spictl, SPICTL_EN << (idx*8), 1); 97362306a36Sopenharmony_ci ctl->dirty.bf.spictl |= (0x1 << idx); 97462306a36Sopenharmony_ci } else { 97562306a36Sopenharmony_ci /* I2S input */ 97662306a36Sopenharmony_ci idx %= 4; 97762306a36Sopenharmony_ci set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 1); 97862306a36Sopenharmony_ci ctl->dirty.bf.i2sictl |= (0x1 << idx); 97962306a36Sopenharmony_ci } 98062306a36Sopenharmony_ci return 0; 98162306a36Sopenharmony_ci} 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_cistatic int daio_mgr_dsb_dai(void *blk, unsigned int idx) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci if (idx < 4) { 98862306a36Sopenharmony_ci /* S/PDIF input */ 98962306a36Sopenharmony_ci set_field(&ctl->spictl, SPICTL_EN << (idx*8), 0); 99062306a36Sopenharmony_ci ctl->dirty.bf.spictl |= (0x1 << idx); 99162306a36Sopenharmony_ci } else { 99262306a36Sopenharmony_ci /* I2S input */ 99362306a36Sopenharmony_ci idx %= 4; 99462306a36Sopenharmony_ci set_field(&ctl->i2sctl, I2SCTL_EI << (idx*8), 0); 99562306a36Sopenharmony_ci ctl->dirty.bf.i2sictl |= (0x1 << idx); 99662306a36Sopenharmony_ci } 99762306a36Sopenharmony_ci return 0; 99862306a36Sopenharmony_ci} 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_cistatic int daio_mgr_enb_dao(void *blk, unsigned int idx) 100162306a36Sopenharmony_ci{ 100262306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci if (idx < 4) { 100562306a36Sopenharmony_ci /* S/PDIF output */ 100662306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 1); 100762306a36Sopenharmony_ci ctl->dirty.bf.spoctl |= (0x1 << idx); 100862306a36Sopenharmony_ci } else { 100962306a36Sopenharmony_ci /* I2S output */ 101062306a36Sopenharmony_ci idx %= 4; 101162306a36Sopenharmony_ci set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 1); 101262306a36Sopenharmony_ci ctl->dirty.bf.i2soctl |= (0x1 << idx); 101362306a36Sopenharmony_ci } 101462306a36Sopenharmony_ci return 0; 101562306a36Sopenharmony_ci} 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_cistatic int daio_mgr_dsb_dao(void *blk, unsigned int idx) 101862306a36Sopenharmony_ci{ 101962306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci if (idx < 4) { 102262306a36Sopenharmony_ci /* S/PDIF output */ 102362306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_OE << (idx*8), 0); 102462306a36Sopenharmony_ci ctl->dirty.bf.spoctl |= (0x1 << idx); 102562306a36Sopenharmony_ci } else { 102662306a36Sopenharmony_ci /* I2S output */ 102762306a36Sopenharmony_ci idx %= 4; 102862306a36Sopenharmony_ci set_field(&ctl->i2sctl, I2SCTL_EA << (idx*8), 0); 102962306a36Sopenharmony_ci ctl->dirty.bf.i2soctl |= (0x1 << idx); 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci return 0; 103262306a36Sopenharmony_ci} 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_cistatic int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) 103562306a36Sopenharmony_ci{ 103662306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci if (idx < 4) { 103962306a36Sopenharmony_ci /* S/PDIF output */ 104062306a36Sopenharmony_ci switch ((conf & 0x7)) { 104162306a36Sopenharmony_ci case 0: 104262306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 3); 104362306a36Sopenharmony_ci break; /* CDIF */ 104462306a36Sopenharmony_ci case 1: 104562306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 0); 104662306a36Sopenharmony_ci break; 104762306a36Sopenharmony_ci case 2: 104862306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 1); 104962306a36Sopenharmony_ci break; 105062306a36Sopenharmony_ci case 4: 105162306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_SR << (idx*8), 2); 105262306a36Sopenharmony_ci break; 105362306a36Sopenharmony_ci default: 105462306a36Sopenharmony_ci break; 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_LIV << (idx*8), 105762306a36Sopenharmony_ci (conf >> 4) & 0x1); /* Non-audio */ 105862306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_RIV << (idx*8), 105962306a36Sopenharmony_ci (conf >> 4) & 0x1); /* Non-audio */ 106062306a36Sopenharmony_ci set_field(&ctl->spoctl, SPOCTL_OS << (idx*8), 106162306a36Sopenharmony_ci ((conf >> 3) & 0x1) ? 2 : 2); /* Raw */ 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci ctl->dirty.bf.spoctl |= (0x1 << idx); 106462306a36Sopenharmony_ci } else { 106562306a36Sopenharmony_ci /* I2S output */ 106662306a36Sopenharmony_ci /*idx %= 4; */ 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci return 0; 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_cistatic int daio_mgr_set_imaparc(void *blk, unsigned int slot) 107262306a36Sopenharmony_ci{ 107362306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci set_field(&ctl->daoimap.aim, AIM_ARC, slot); 107662306a36Sopenharmony_ci ctl->dirty.bf.daoimap = 1; 107762306a36Sopenharmony_ci return 0; 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic int daio_mgr_set_imapnxt(void *blk, unsigned int next) 108162306a36Sopenharmony_ci{ 108262306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci set_field(&ctl->daoimap.aim, AIM_NXT, next); 108562306a36Sopenharmony_ci ctl->dirty.bf.daoimap = 1; 108662306a36Sopenharmony_ci return 0; 108762306a36Sopenharmony_ci} 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_cistatic int daio_mgr_set_imapaddr(void *blk, unsigned int addr) 109062306a36Sopenharmony_ci{ 109162306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci ctl->daoimap.idx = addr; 109462306a36Sopenharmony_ci ctl->dirty.bf.daoimap = 1; 109562306a36Sopenharmony_ci return 0; 109662306a36Sopenharmony_ci} 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic int daio_mgr_commit_write(struct hw *hw, void *blk) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *ctl = blk; 110162306a36Sopenharmony_ci int i; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci if (ctl->dirty.bf.i2sictl || ctl->dirty.bf.i2soctl) { 110462306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 110562306a36Sopenharmony_ci if ((ctl->dirty.bf.i2sictl & (0x1 << i))) 110662306a36Sopenharmony_ci ctl->dirty.bf.i2sictl &= ~(0x1 << i); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci if ((ctl->dirty.bf.i2soctl & (0x1 << i))) 110962306a36Sopenharmony_ci ctl->dirty.bf.i2soctl &= ~(0x1 << i); 111062306a36Sopenharmony_ci } 111162306a36Sopenharmony_ci hw_write_20kx(hw, I2SCTL, ctl->i2sctl); 111262306a36Sopenharmony_ci mdelay(1); 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci if (ctl->dirty.bf.spoctl) { 111562306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 111662306a36Sopenharmony_ci if ((ctl->dirty.bf.spoctl & (0x1 << i))) 111762306a36Sopenharmony_ci ctl->dirty.bf.spoctl &= ~(0x1 << i); 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci hw_write_20kx(hw, SPOCTL, ctl->spoctl); 112062306a36Sopenharmony_ci mdelay(1); 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci if (ctl->dirty.bf.spictl) { 112362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 112462306a36Sopenharmony_ci if ((ctl->dirty.bf.spictl & (0x1 << i))) 112562306a36Sopenharmony_ci ctl->dirty.bf.spictl &= ~(0x1 << i); 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci hw_write_20kx(hw, SPICTL, ctl->spictl); 112862306a36Sopenharmony_ci mdelay(1); 112962306a36Sopenharmony_ci } 113062306a36Sopenharmony_ci if (ctl->dirty.bf.daoimap) { 113162306a36Sopenharmony_ci hw_write_20kx(hw, DAOIMAP+ctl->daoimap.idx*4, 113262306a36Sopenharmony_ci ctl->daoimap.aim); 113362306a36Sopenharmony_ci ctl->dirty.bf.daoimap = 0; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci return 0; 113762306a36Sopenharmony_ci} 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_cistatic int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) 114062306a36Sopenharmony_ci{ 114162306a36Sopenharmony_ci struct daio_mgr_ctrl_blk *blk; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci *rblk = NULL; 114462306a36Sopenharmony_ci blk = kzalloc(sizeof(*blk), GFP_KERNEL); 114562306a36Sopenharmony_ci if (!blk) 114662306a36Sopenharmony_ci return -ENOMEM; 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci blk->i2sctl = hw_read_20kx(hw, I2SCTL); 114962306a36Sopenharmony_ci blk->spoctl = hw_read_20kx(hw, SPOCTL); 115062306a36Sopenharmony_ci blk->spictl = hw_read_20kx(hw, SPICTL); 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci *rblk = blk; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci return 0; 115562306a36Sopenharmony_ci} 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_cistatic int daio_mgr_put_ctrl_blk(void *blk) 115862306a36Sopenharmony_ci{ 115962306a36Sopenharmony_ci kfree(blk); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci return 0; 116262306a36Sopenharmony_ci} 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci/* Timer interrupt */ 116562306a36Sopenharmony_cistatic int set_timer_irq(struct hw *hw, int enable) 116662306a36Sopenharmony_ci{ 116762306a36Sopenharmony_ci hw_write_20kx(hw, GIE, enable ? IT_INT : 0); 116862306a36Sopenharmony_ci return 0; 116962306a36Sopenharmony_ci} 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_cistatic int set_timer_tick(struct hw *hw, unsigned int ticks) 117262306a36Sopenharmony_ci{ 117362306a36Sopenharmony_ci if (ticks) 117462306a36Sopenharmony_ci ticks |= TIMR_IE | TIMR_IP; 117562306a36Sopenharmony_ci hw_write_20kx(hw, TIMR, ticks); 117662306a36Sopenharmony_ci return 0; 117762306a36Sopenharmony_ci} 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_cistatic unsigned int get_wc(struct hw *hw) 118062306a36Sopenharmony_ci{ 118162306a36Sopenharmony_ci return hw_read_20kx(hw, WC); 118262306a36Sopenharmony_ci} 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci/* Card hardware initialization block */ 118562306a36Sopenharmony_cistruct dac_conf { 118662306a36Sopenharmony_ci unsigned int msr; /* master sample rate in rsrs */ 118762306a36Sopenharmony_ci}; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_cistruct adc_conf { 119062306a36Sopenharmony_ci unsigned int msr; /* master sample rate in rsrs */ 119162306a36Sopenharmony_ci unsigned char input; /* the input source of ADC */ 119262306a36Sopenharmony_ci unsigned char mic20db; /* boost mic by 20db if input is microphone */ 119362306a36Sopenharmony_ci}; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_cistruct daio_conf { 119662306a36Sopenharmony_ci unsigned int msr; /* master sample rate in rsrs */ 119762306a36Sopenharmony_ci}; 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistruct trn_conf { 120062306a36Sopenharmony_ci unsigned long vm_pgt_phys; 120162306a36Sopenharmony_ci}; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_cistatic int hw_daio_init(struct hw *hw, const struct daio_conf *info) 120462306a36Sopenharmony_ci{ 120562306a36Sopenharmony_ci u32 i2sorg; 120662306a36Sopenharmony_ci u32 spdorg; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci /* Read I2S CTL. Keep original value. */ 120962306a36Sopenharmony_ci /*i2sorg = hw_read_20kx(hw, I2SCTL);*/ 121062306a36Sopenharmony_ci i2sorg = 0x94040404; /* enable all audio out and I2S-D input */ 121162306a36Sopenharmony_ci /* Program I2S with proper master sample rate and enable 121262306a36Sopenharmony_ci * the correct I2S channel. */ 121362306a36Sopenharmony_ci i2sorg &= 0xfffffffc; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci /* Enable S/PDIF-out-A in fixed 24-bit data 121662306a36Sopenharmony_ci * format and default to 48kHz. */ 121762306a36Sopenharmony_ci /* Disable all before doing any changes. */ 121862306a36Sopenharmony_ci hw_write_20kx(hw, SPOCTL, 0x0); 121962306a36Sopenharmony_ci spdorg = 0x05; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci switch (info->msr) { 122262306a36Sopenharmony_ci case 1: 122362306a36Sopenharmony_ci i2sorg |= 1; 122462306a36Sopenharmony_ci spdorg |= (0x0 << 6); 122562306a36Sopenharmony_ci break; 122662306a36Sopenharmony_ci case 2: 122762306a36Sopenharmony_ci i2sorg |= 2; 122862306a36Sopenharmony_ci spdorg |= (0x1 << 6); 122962306a36Sopenharmony_ci break; 123062306a36Sopenharmony_ci case 4: 123162306a36Sopenharmony_ci i2sorg |= 3; 123262306a36Sopenharmony_ci spdorg |= (0x2 << 6); 123362306a36Sopenharmony_ci break; 123462306a36Sopenharmony_ci default: 123562306a36Sopenharmony_ci i2sorg |= 1; 123662306a36Sopenharmony_ci break; 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci hw_write_20kx(hw, I2SCTL, i2sorg); 124062306a36Sopenharmony_ci hw_write_20kx(hw, SPOCTL, spdorg); 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci /* Enable S/PDIF-in-A in fixed 24-bit data format. */ 124362306a36Sopenharmony_ci /* Disable all before doing any changes. */ 124462306a36Sopenharmony_ci hw_write_20kx(hw, SPICTL, 0x0); 124562306a36Sopenharmony_ci mdelay(1); 124662306a36Sopenharmony_ci spdorg = 0x0a0a0a0a; 124762306a36Sopenharmony_ci hw_write_20kx(hw, SPICTL, spdorg); 124862306a36Sopenharmony_ci mdelay(1); 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci return 0; 125162306a36Sopenharmony_ci} 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci/* TRANSPORT operations */ 125462306a36Sopenharmony_cistatic int hw_trn_init(struct hw *hw, const struct trn_conf *info) 125562306a36Sopenharmony_ci{ 125662306a36Sopenharmony_ci u32 trnctl; 125762306a36Sopenharmony_ci u32 ptp_phys_low, ptp_phys_high; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci /* Set up device page table */ 126062306a36Sopenharmony_ci if ((~0UL) == info->vm_pgt_phys) { 126162306a36Sopenharmony_ci dev_err(hw->card->dev, 126262306a36Sopenharmony_ci "Wrong device page table page address!\n"); 126362306a36Sopenharmony_ci return -1; 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci trnctl = 0x13; /* 32-bit, 4k-size page */ 126762306a36Sopenharmony_ci ptp_phys_low = (u32)info->vm_pgt_phys; 126862306a36Sopenharmony_ci ptp_phys_high = upper_32_bits(info->vm_pgt_phys); 126962306a36Sopenharmony_ci if (sizeof(void *) == 8) /* 64bit address */ 127062306a36Sopenharmony_ci trnctl |= (1 << 2); 127162306a36Sopenharmony_ci#if 0 /* Only 4k h/w pages for simplicitiy */ 127262306a36Sopenharmony_ci#if PAGE_SIZE == 8192 127362306a36Sopenharmony_ci trnctl |= (1<<5); 127462306a36Sopenharmony_ci#endif 127562306a36Sopenharmony_ci#endif 127662306a36Sopenharmony_ci hw_write_20kx(hw, PTPALX, ptp_phys_low); 127762306a36Sopenharmony_ci hw_write_20kx(hw, PTPAHX, ptp_phys_high); 127862306a36Sopenharmony_ci hw_write_20kx(hw, TRNCTL, trnctl); 127962306a36Sopenharmony_ci hw_write_20kx(hw, TRNIS, 0x200c01); /* really needed? */ 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci return 0; 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci/* Card initialization */ 128562306a36Sopenharmony_ci#define GCTL_EAC 0x00000001 128662306a36Sopenharmony_ci#define GCTL_EAI 0x00000002 128762306a36Sopenharmony_ci#define GCTL_BEP 0x00000004 128862306a36Sopenharmony_ci#define GCTL_BES 0x00000008 128962306a36Sopenharmony_ci#define GCTL_DSP 0x00000010 129062306a36Sopenharmony_ci#define GCTL_DBP 0x00000020 129162306a36Sopenharmony_ci#define GCTL_ABP 0x00000040 129262306a36Sopenharmony_ci#define GCTL_TBP 0x00000080 129362306a36Sopenharmony_ci#define GCTL_SBP 0x00000100 129462306a36Sopenharmony_ci#define GCTL_FBP 0x00000200 129562306a36Sopenharmony_ci#define GCTL_XA 0x00000400 129662306a36Sopenharmony_ci#define GCTL_ET 0x00000800 129762306a36Sopenharmony_ci#define GCTL_PR 0x00001000 129862306a36Sopenharmony_ci#define GCTL_MRL 0x00002000 129962306a36Sopenharmony_ci#define GCTL_SDE 0x00004000 130062306a36Sopenharmony_ci#define GCTL_SDI 0x00008000 130162306a36Sopenharmony_ci#define GCTL_SM 0x00010000 130262306a36Sopenharmony_ci#define GCTL_SR 0x00020000 130362306a36Sopenharmony_ci#define GCTL_SD 0x00040000 130462306a36Sopenharmony_ci#define GCTL_SE 0x00080000 130562306a36Sopenharmony_ci#define GCTL_AID 0x00100000 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_cistatic int hw_pll_init(struct hw *hw, unsigned int rsr) 130862306a36Sopenharmony_ci{ 130962306a36Sopenharmony_ci unsigned int pllctl; 131062306a36Sopenharmony_ci int i; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci pllctl = (48000 == rsr) ? 0x1480a001 : 0x1480a731; 131362306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 131462306a36Sopenharmony_ci if (hw_read_20kx(hw, PLLCTL) == pllctl) 131562306a36Sopenharmony_ci break; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci hw_write_20kx(hw, PLLCTL, pllctl); 131862306a36Sopenharmony_ci msleep(40); 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_ci if (i >= 3) { 132162306a36Sopenharmony_ci dev_alert(hw->card->dev, "PLL initialization failed!!!\n"); 132262306a36Sopenharmony_ci return -EBUSY; 132362306a36Sopenharmony_ci } 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci return 0; 132662306a36Sopenharmony_ci} 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_cistatic int hw_auto_init(struct hw *hw) 132962306a36Sopenharmony_ci{ 133062306a36Sopenharmony_ci unsigned int gctl; 133162306a36Sopenharmony_ci int i; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci gctl = hw_read_20kx(hw, GCTL); 133462306a36Sopenharmony_ci set_field(&gctl, GCTL_EAI, 0); 133562306a36Sopenharmony_ci hw_write_20kx(hw, GCTL, gctl); 133662306a36Sopenharmony_ci set_field(&gctl, GCTL_EAI, 1); 133762306a36Sopenharmony_ci hw_write_20kx(hw, GCTL, gctl); 133862306a36Sopenharmony_ci mdelay(10); 133962306a36Sopenharmony_ci for (i = 0; i < 400000; i++) { 134062306a36Sopenharmony_ci gctl = hw_read_20kx(hw, GCTL); 134162306a36Sopenharmony_ci if (get_field(gctl, GCTL_AID)) 134262306a36Sopenharmony_ci break; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci if (!get_field(gctl, GCTL_AID)) { 134562306a36Sopenharmony_ci dev_alert(hw->card->dev, "Card Auto-init failed!!!\n"); 134662306a36Sopenharmony_ci return -EBUSY; 134762306a36Sopenharmony_ci } 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci return 0; 135062306a36Sopenharmony_ci} 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistatic int i2c_unlock(struct hw *hw) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 135562306a36Sopenharmony_ci return 0; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci hw_write_pci(hw, 0xcc, 0x8c); 135862306a36Sopenharmony_ci hw_write_pci(hw, 0xcc, 0x0e); 135962306a36Sopenharmony_ci if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 136062306a36Sopenharmony_ci return 0; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci hw_write_pci(hw, 0xcc, 0xee); 136362306a36Sopenharmony_ci hw_write_pci(hw, 0xcc, 0xaa); 136462306a36Sopenharmony_ci if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 136562306a36Sopenharmony_ci return 0; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci return -1; 136862306a36Sopenharmony_ci} 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_cistatic void i2c_lock(struct hw *hw) 137162306a36Sopenharmony_ci{ 137262306a36Sopenharmony_ci if ((hw_read_pci(hw, 0xcc) & 0xff) == 0xaa) 137362306a36Sopenharmony_ci hw_write_pci(hw, 0xcc, 0x00); 137462306a36Sopenharmony_ci} 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_cistatic void i2c_write(struct hw *hw, u32 device, u32 addr, u32 data) 137762306a36Sopenharmony_ci{ 137862306a36Sopenharmony_ci unsigned int ret; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci do { 138162306a36Sopenharmony_ci ret = hw_read_pci(hw, 0xEC); 138262306a36Sopenharmony_ci } while (!(ret & 0x800000)); 138362306a36Sopenharmony_ci hw_write_pci(hw, 0xE0, device); 138462306a36Sopenharmony_ci hw_write_pci(hw, 0xE4, (data << 8) | (addr & 0xff)); 138562306a36Sopenharmony_ci} 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci/* DAC operations */ 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_cistatic int hw_reset_dac(struct hw *hw) 139062306a36Sopenharmony_ci{ 139162306a36Sopenharmony_ci u32 i; 139262306a36Sopenharmony_ci u16 gpioorg; 139362306a36Sopenharmony_ci unsigned int ret; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci if (i2c_unlock(hw)) 139662306a36Sopenharmony_ci return -1; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci do { 139962306a36Sopenharmony_ci ret = hw_read_pci(hw, 0xEC); 140062306a36Sopenharmony_ci } while (!(ret & 0x800000)); 140162306a36Sopenharmony_ci hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* To be effective, need to reset the DAC twice. */ 140462306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 140562306a36Sopenharmony_ci /* set gpio */ 140662306a36Sopenharmony_ci msleep(100); 140762306a36Sopenharmony_ci gpioorg = (u16)hw_read_20kx(hw, GPIO); 140862306a36Sopenharmony_ci gpioorg &= 0xfffd; 140962306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, gpioorg); 141062306a36Sopenharmony_ci mdelay(1); 141162306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, gpioorg | 0x2); 141262306a36Sopenharmony_ci } 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci i2c_write(hw, 0x00180080, 0x01, 0x80); 141562306a36Sopenharmony_ci i2c_write(hw, 0x00180080, 0x02, 0x10); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci i2c_lock(hw); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci return 0; 142062306a36Sopenharmony_ci} 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_cistatic int hw_dac_init(struct hw *hw, const struct dac_conf *info) 142362306a36Sopenharmony_ci{ 142462306a36Sopenharmony_ci u32 data; 142562306a36Sopenharmony_ci u16 gpioorg; 142662306a36Sopenharmony_ci unsigned int ret; 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci if (hw->model == CTSB055X) { 142962306a36Sopenharmony_ci /* SB055x, unmute outputs */ 143062306a36Sopenharmony_ci gpioorg = (u16)hw_read_20kx(hw, GPIO); 143162306a36Sopenharmony_ci gpioorg &= 0xffbf; /* set GPIO6 to low */ 143262306a36Sopenharmony_ci gpioorg |= 2; /* set GPIO1 to high */ 143362306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, gpioorg); 143462306a36Sopenharmony_ci return 0; 143562306a36Sopenharmony_ci } 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci /* mute outputs */ 143862306a36Sopenharmony_ci gpioorg = (u16)hw_read_20kx(hw, GPIO); 143962306a36Sopenharmony_ci gpioorg &= 0xffbf; 144062306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, gpioorg); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci hw_reset_dac(hw); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci if (i2c_unlock(hw)) 144562306a36Sopenharmony_ci return -1; 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 144862306a36Sopenharmony_ci do { 144962306a36Sopenharmony_ci ret = hw_read_pci(hw, 0xEC); 145062306a36Sopenharmony_ci } while (!(ret & 0x800000)); 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci switch (info->msr) { 145362306a36Sopenharmony_ci case 1: 145462306a36Sopenharmony_ci data = 0x24; 145562306a36Sopenharmony_ci break; 145662306a36Sopenharmony_ci case 2: 145762306a36Sopenharmony_ci data = 0x25; 145862306a36Sopenharmony_ci break; 145962306a36Sopenharmony_ci case 4: 146062306a36Sopenharmony_ci data = 0x26; 146162306a36Sopenharmony_ci break; 146262306a36Sopenharmony_ci default: 146362306a36Sopenharmony_ci data = 0x24; 146462306a36Sopenharmony_ci break; 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci i2c_write(hw, 0x00180080, 0x06, data); 146862306a36Sopenharmony_ci i2c_write(hw, 0x00180080, 0x09, data); 146962306a36Sopenharmony_ci i2c_write(hw, 0x00180080, 0x0c, data); 147062306a36Sopenharmony_ci i2c_write(hw, 0x00180080, 0x0f, data); 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci i2c_lock(hw); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci /* unmute outputs */ 147562306a36Sopenharmony_ci gpioorg = (u16)hw_read_20kx(hw, GPIO); 147662306a36Sopenharmony_ci gpioorg = gpioorg | 0x40; 147762306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, gpioorg); 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci return 0; 148062306a36Sopenharmony_ci} 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci/* ADC operations */ 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_cistatic int is_adc_input_selected_SB055x(struct hw *hw, enum ADCSRC type) 148562306a36Sopenharmony_ci{ 148662306a36Sopenharmony_ci return 0; 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_cistatic int is_adc_input_selected_SBx(struct hw *hw, enum ADCSRC type) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci u32 data; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci data = hw_read_20kx(hw, GPIO); 149462306a36Sopenharmony_ci switch (type) { 149562306a36Sopenharmony_ci case ADC_MICIN: 149662306a36Sopenharmony_ci data = ((data & (0x1<<7)) && (data & (0x1<<8))); 149762306a36Sopenharmony_ci break; 149862306a36Sopenharmony_ci case ADC_LINEIN: 149962306a36Sopenharmony_ci data = (!(data & (0x1<<7)) && (data & (0x1<<8))); 150062306a36Sopenharmony_ci break; 150162306a36Sopenharmony_ci case ADC_NONE: /* Digital I/O */ 150262306a36Sopenharmony_ci data = (!(data & (0x1<<8))); 150362306a36Sopenharmony_ci break; 150462306a36Sopenharmony_ci default: 150562306a36Sopenharmony_ci data = 0; 150662306a36Sopenharmony_ci } 150762306a36Sopenharmony_ci return data; 150862306a36Sopenharmony_ci} 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_cistatic int is_adc_input_selected_hendrix(struct hw *hw, enum ADCSRC type) 151162306a36Sopenharmony_ci{ 151262306a36Sopenharmony_ci u32 data; 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci data = hw_read_20kx(hw, GPIO); 151562306a36Sopenharmony_ci switch (type) { 151662306a36Sopenharmony_ci case ADC_MICIN: 151762306a36Sopenharmony_ci data = (data & (0x1 << 7)) ? 1 : 0; 151862306a36Sopenharmony_ci break; 151962306a36Sopenharmony_ci case ADC_LINEIN: 152062306a36Sopenharmony_ci data = (data & (0x1 << 7)) ? 0 : 1; 152162306a36Sopenharmony_ci break; 152262306a36Sopenharmony_ci default: 152362306a36Sopenharmony_ci data = 0; 152462306a36Sopenharmony_ci } 152562306a36Sopenharmony_ci return data; 152662306a36Sopenharmony_ci} 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_cistatic int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) 152962306a36Sopenharmony_ci{ 153062306a36Sopenharmony_ci switch (hw->model) { 153162306a36Sopenharmony_ci case CTSB055X: 153262306a36Sopenharmony_ci return is_adc_input_selected_SB055x(hw, type); 153362306a36Sopenharmony_ci case CTSB073X: 153462306a36Sopenharmony_ci return is_adc_input_selected_hendrix(hw, type); 153562306a36Sopenharmony_ci case CTUAA: 153662306a36Sopenharmony_ci return is_adc_input_selected_hendrix(hw, type); 153762306a36Sopenharmony_ci default: 153862306a36Sopenharmony_ci return is_adc_input_selected_SBx(hw, type); 153962306a36Sopenharmony_ci } 154062306a36Sopenharmony_ci} 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_cistatic int 154362306a36Sopenharmony_ciadc_input_select_SB055x(struct hw *hw, enum ADCSRC type, unsigned char boost) 154462306a36Sopenharmony_ci{ 154562306a36Sopenharmony_ci u32 data; 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci /* 154862306a36Sopenharmony_ci * check and set the following GPIO bits accordingly 154962306a36Sopenharmony_ci * ADC_Gain = GPIO2 155062306a36Sopenharmony_ci * DRM_off = GPIO3 155162306a36Sopenharmony_ci * Mic_Pwr_on = GPIO7 155262306a36Sopenharmony_ci * Digital_IO_Sel = GPIO8 155362306a36Sopenharmony_ci * Mic_Sw = GPIO9 155462306a36Sopenharmony_ci * Aux/MicLine_Sw = GPIO12 155562306a36Sopenharmony_ci */ 155662306a36Sopenharmony_ci data = hw_read_20kx(hw, GPIO); 155762306a36Sopenharmony_ci data &= 0xec73; 155862306a36Sopenharmony_ci switch (type) { 155962306a36Sopenharmony_ci case ADC_MICIN: 156062306a36Sopenharmony_ci data |= (0x1<<7) | (0x1<<8) | (0x1<<9) ; 156162306a36Sopenharmony_ci data |= boost ? (0x1<<2) : 0; 156262306a36Sopenharmony_ci break; 156362306a36Sopenharmony_ci case ADC_LINEIN: 156462306a36Sopenharmony_ci data |= (0x1<<8); 156562306a36Sopenharmony_ci break; 156662306a36Sopenharmony_ci case ADC_AUX: 156762306a36Sopenharmony_ci data |= (0x1<<8) | (0x1<<12); 156862306a36Sopenharmony_ci break; 156962306a36Sopenharmony_ci case ADC_NONE: 157062306a36Sopenharmony_ci data |= (0x1<<12); /* set to digital */ 157162306a36Sopenharmony_ci break; 157262306a36Sopenharmony_ci default: 157362306a36Sopenharmony_ci return -1; 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, data); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci return 0; 157962306a36Sopenharmony_ci} 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_cistatic int 158362306a36Sopenharmony_ciadc_input_select_SBx(struct hw *hw, enum ADCSRC type, unsigned char boost) 158462306a36Sopenharmony_ci{ 158562306a36Sopenharmony_ci u32 data; 158662306a36Sopenharmony_ci u32 i2c_data; 158762306a36Sopenharmony_ci unsigned int ret; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci if (i2c_unlock(hw)) 159062306a36Sopenharmony_ci return -1; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci do { 159362306a36Sopenharmony_ci ret = hw_read_pci(hw, 0xEC); 159462306a36Sopenharmony_ci } while (!(ret & 0x800000)); /* i2c ready poll */ 159562306a36Sopenharmony_ci /* set i2c access mode as Direct Control */ 159662306a36Sopenharmony_ci hw_write_pci(hw, 0xEC, 0x05); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci data = hw_read_20kx(hw, GPIO); 159962306a36Sopenharmony_ci switch (type) { 160062306a36Sopenharmony_ci case ADC_MICIN: 160162306a36Sopenharmony_ci data |= ((0x1 << 7) | (0x1 << 8)); 160262306a36Sopenharmony_ci i2c_data = 0x1; /* Mic-in */ 160362306a36Sopenharmony_ci break; 160462306a36Sopenharmony_ci case ADC_LINEIN: 160562306a36Sopenharmony_ci data &= ~(0x1 << 7); 160662306a36Sopenharmony_ci data |= (0x1 << 8); 160762306a36Sopenharmony_ci i2c_data = 0x2; /* Line-in */ 160862306a36Sopenharmony_ci break; 160962306a36Sopenharmony_ci case ADC_NONE: 161062306a36Sopenharmony_ci data &= ~(0x1 << 8); 161162306a36Sopenharmony_ci i2c_data = 0x0; /* set to Digital */ 161262306a36Sopenharmony_ci break; 161362306a36Sopenharmony_ci default: 161462306a36Sopenharmony_ci i2c_lock(hw); 161562306a36Sopenharmony_ci return -1; 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, data); 161862306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 161962306a36Sopenharmony_ci if (boost) { 162062306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 162162306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 162262306a36Sopenharmony_ci } else { 162362306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 162462306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 162562306a36Sopenharmony_ci } 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci i2c_lock(hw); 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci return 0; 163062306a36Sopenharmony_ci} 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_cistatic int 163362306a36Sopenharmony_ciadc_input_select_hendrix(struct hw *hw, enum ADCSRC type, unsigned char boost) 163462306a36Sopenharmony_ci{ 163562306a36Sopenharmony_ci u32 data; 163662306a36Sopenharmony_ci u32 i2c_data; 163762306a36Sopenharmony_ci unsigned int ret; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci if (i2c_unlock(hw)) 164062306a36Sopenharmony_ci return -1; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci do { 164362306a36Sopenharmony_ci ret = hw_read_pci(hw, 0xEC); 164462306a36Sopenharmony_ci } while (!(ret & 0x800000)); /* i2c ready poll */ 164562306a36Sopenharmony_ci /* set i2c access mode as Direct Control */ 164662306a36Sopenharmony_ci hw_write_pci(hw, 0xEC, 0x05); 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci data = hw_read_20kx(hw, GPIO); 164962306a36Sopenharmony_ci switch (type) { 165062306a36Sopenharmony_ci case ADC_MICIN: 165162306a36Sopenharmony_ci data |= (0x1 << 7); 165262306a36Sopenharmony_ci i2c_data = 0x1; /* Mic-in */ 165362306a36Sopenharmony_ci break; 165462306a36Sopenharmony_ci case ADC_LINEIN: 165562306a36Sopenharmony_ci data &= ~(0x1 << 7); 165662306a36Sopenharmony_ci i2c_data = 0x2; /* Line-in */ 165762306a36Sopenharmony_ci break; 165862306a36Sopenharmony_ci default: 165962306a36Sopenharmony_ci i2c_lock(hw); 166062306a36Sopenharmony_ci return -1; 166162306a36Sopenharmony_ci } 166262306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, data); 166362306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x2a, i2c_data); 166462306a36Sopenharmony_ci if (boost) { 166562306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1c, 0xe7); /* +12dB boost */ 166662306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1e, 0xe7); /* +12dB boost */ 166762306a36Sopenharmony_ci } else { 166862306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1c, 0xcf); /* No boost */ 166962306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1e, 0xcf); /* No boost */ 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci i2c_lock(hw); 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci return 0; 167562306a36Sopenharmony_ci} 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_cistatic int hw_adc_input_select(struct hw *hw, enum ADCSRC type) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci int state = type == ADC_MICIN; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci switch (hw->model) { 168262306a36Sopenharmony_ci case CTSB055X: 168362306a36Sopenharmony_ci return adc_input_select_SB055x(hw, type, state); 168462306a36Sopenharmony_ci case CTSB073X: 168562306a36Sopenharmony_ci return adc_input_select_hendrix(hw, type, state); 168662306a36Sopenharmony_ci case CTUAA: 168762306a36Sopenharmony_ci return adc_input_select_hendrix(hw, type, state); 168862306a36Sopenharmony_ci default: 168962306a36Sopenharmony_ci return adc_input_select_SBx(hw, type, state); 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci} 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_cistatic int adc_init_SB055x(struct hw *hw, int input, int mic20db) 169462306a36Sopenharmony_ci{ 169562306a36Sopenharmony_ci return adc_input_select_SB055x(hw, input, mic20db); 169662306a36Sopenharmony_ci} 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_cistatic int adc_init_SBx(struct hw *hw, int input, int mic20db) 169962306a36Sopenharmony_ci{ 170062306a36Sopenharmony_ci u16 gpioorg; 170162306a36Sopenharmony_ci u16 input_source; 170262306a36Sopenharmony_ci u32 adcdata; 170362306a36Sopenharmony_ci unsigned int ret; 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci input_source = 0x100; /* default to analog */ 170662306a36Sopenharmony_ci switch (input) { 170762306a36Sopenharmony_ci case ADC_MICIN: 170862306a36Sopenharmony_ci adcdata = 0x1; 170962306a36Sopenharmony_ci input_source = 0x180; /* set GPIO7 to select Mic */ 171062306a36Sopenharmony_ci break; 171162306a36Sopenharmony_ci case ADC_LINEIN: 171262306a36Sopenharmony_ci adcdata = 0x2; 171362306a36Sopenharmony_ci break; 171462306a36Sopenharmony_ci case ADC_VIDEO: 171562306a36Sopenharmony_ci adcdata = 0x4; 171662306a36Sopenharmony_ci break; 171762306a36Sopenharmony_ci case ADC_AUX: 171862306a36Sopenharmony_ci adcdata = 0x8; 171962306a36Sopenharmony_ci break; 172062306a36Sopenharmony_ci case ADC_NONE: 172162306a36Sopenharmony_ci adcdata = 0x0; 172262306a36Sopenharmony_ci input_source = 0x0; /* set to Digital */ 172362306a36Sopenharmony_ci break; 172462306a36Sopenharmony_ci default: 172562306a36Sopenharmony_ci adcdata = 0x0; 172662306a36Sopenharmony_ci break; 172762306a36Sopenharmony_ci } 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci if (i2c_unlock(hw)) 173062306a36Sopenharmony_ci return -1; 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci do { 173362306a36Sopenharmony_ci ret = hw_read_pci(hw, 0xEC); 173462306a36Sopenharmony_ci } while (!(ret & 0x800000)); /* i2c ready poll */ 173562306a36Sopenharmony_ci hw_write_pci(hw, 0xEC, 0x05); /* write to i2c status control */ 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x0e, 0x08); 173862306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x18, 0x0a); 173962306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x28, 0x86); 174062306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x2a, adcdata); 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci if (mic20db) { 174362306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1c, 0xf7); 174462306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1e, 0xf7); 174562306a36Sopenharmony_ci } else { 174662306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1c, 0xcf); 174762306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x1e, 0xcf); 174862306a36Sopenharmony_ci } 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci if (!(hw_read_20kx(hw, ID0) & 0x100)) 175162306a36Sopenharmony_ci i2c_write(hw, 0x001a0080, 0x16, 0x26); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci i2c_lock(hw); 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci gpioorg = (u16)hw_read_20kx(hw, GPIO); 175662306a36Sopenharmony_ci gpioorg &= 0xfe7f; 175762306a36Sopenharmony_ci gpioorg |= input_source; 175862306a36Sopenharmony_ci hw_write_20kx(hw, GPIO, gpioorg); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci return 0; 176162306a36Sopenharmony_ci} 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_cistatic int hw_adc_init(struct hw *hw, const struct adc_conf *info) 176462306a36Sopenharmony_ci{ 176562306a36Sopenharmony_ci if (hw->model == CTSB055X) 176662306a36Sopenharmony_ci return adc_init_SB055x(hw, info->input, info->mic20db); 176762306a36Sopenharmony_ci else 176862306a36Sopenharmony_ci return adc_init_SBx(hw, info->input, info->mic20db); 176962306a36Sopenharmony_ci} 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_cistatic struct capabilities hw_capabilities(struct hw *hw) 177262306a36Sopenharmony_ci{ 177362306a36Sopenharmony_ci struct capabilities cap; 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci /* SB073x and Vista compatible cards have no digit IO switch */ 177662306a36Sopenharmony_ci cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); 177762306a36Sopenharmony_ci cap.dedicated_mic = 0; 177862306a36Sopenharmony_ci cap.output_switch = 0; 177962306a36Sopenharmony_ci cap.mic_source_switch = 0; 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci return cap; 178262306a36Sopenharmony_ci} 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci#define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci#define UAA_CFG_PWRSTATUS 0x44 178762306a36Sopenharmony_ci#define UAA_CFG_SPACE_FLAG 0xA0 178862306a36Sopenharmony_ci#define UAA_CORE_CHANGE 0x3FFC 178962306a36Sopenharmony_cistatic int uaa_to_xfi(struct pci_dev *pci) 179062306a36Sopenharmony_ci{ 179162306a36Sopenharmony_ci unsigned int bar0, bar1, bar2, bar3, bar4, bar5; 179262306a36Sopenharmony_ci unsigned int cmd, irq, cl_size, l_timer, pwr; 179362306a36Sopenharmony_ci unsigned int is_uaa; 179462306a36Sopenharmony_ci unsigned int data[4] = {0}; 179562306a36Sopenharmony_ci unsigned int io_base; 179662306a36Sopenharmony_ci void __iomem *mem_base; 179762306a36Sopenharmony_ci int i; 179862306a36Sopenharmony_ci const u32 CTLX = CTLBITS('C', 'T', 'L', 'X'); 179962306a36Sopenharmony_ci const u32 CTL_ = CTLBITS('C', 'T', 'L', '-'); 180062306a36Sopenharmony_ci const u32 CTLF = CTLBITS('C', 'T', 'L', 'F'); 180162306a36Sopenharmony_ci const u32 CTLi = CTLBITS('C', 'T', 'L', 'i'); 180262306a36Sopenharmony_ci const u32 CTLA = CTLBITS('C', 'T', 'L', 'A'); 180362306a36Sopenharmony_ci const u32 CTLZ = CTLBITS('C', 'T', 'L', 'Z'); 180462306a36Sopenharmony_ci const u32 CTLL = CTLBITS('C', 'T', 'L', 'L'); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci /* By default, Hendrix card UAA Bar0 should be using memory... */ 180762306a36Sopenharmony_ci io_base = pci_resource_start(pci, 0); 180862306a36Sopenharmony_ci mem_base = ioremap(io_base, pci_resource_len(pci, 0)); 180962306a36Sopenharmony_ci if (!mem_base) 181062306a36Sopenharmony_ci return -ENOENT; 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci /* Read current mode from Mode Change Register */ 181362306a36Sopenharmony_ci for (i = 0; i < 4; i++) 181462306a36Sopenharmony_ci data[i] = readl(mem_base + UAA_CORE_CHANGE); 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci /* Determine current mode... */ 181762306a36Sopenharmony_ci if (data[0] == CTLA) { 181862306a36Sopenharmony_ci is_uaa = ((data[1] == CTLZ && data[2] == CTLL 181962306a36Sopenharmony_ci && data[3] == CTLA) || (data[1] == CTLA 182062306a36Sopenharmony_ci && data[2] == CTLZ && data[3] == CTLL)); 182162306a36Sopenharmony_ci } else if (data[0] == CTLZ) { 182262306a36Sopenharmony_ci is_uaa = (data[1] == CTLL 182362306a36Sopenharmony_ci && data[2] == CTLA && data[3] == CTLA); 182462306a36Sopenharmony_ci } else if (data[0] == CTLL) { 182562306a36Sopenharmony_ci is_uaa = (data[1] == CTLA 182662306a36Sopenharmony_ci && data[2] == CTLA && data[3] == CTLZ); 182762306a36Sopenharmony_ci } else { 182862306a36Sopenharmony_ci is_uaa = 0; 182962306a36Sopenharmony_ci } 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci if (!is_uaa) { 183262306a36Sopenharmony_ci /* Not in UAA mode currently. Return directly. */ 183362306a36Sopenharmony_ci iounmap(mem_base); 183462306a36Sopenharmony_ci return 0; 183562306a36Sopenharmony_ci } 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_BASE_ADDRESS_0, &bar0); 183862306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_BASE_ADDRESS_1, &bar1); 183962306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_BASE_ADDRESS_2, &bar2); 184062306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_BASE_ADDRESS_3, &bar3); 184162306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_BASE_ADDRESS_4, &bar4); 184262306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_BASE_ADDRESS_5, &bar5); 184362306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_INTERRUPT_LINE, &irq); 184462306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_CACHE_LINE_SIZE, &cl_size); 184562306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_LATENCY_TIMER, &l_timer); 184662306a36Sopenharmony_ci pci_read_config_dword(pci, UAA_CFG_PWRSTATUS, &pwr); 184762306a36Sopenharmony_ci pci_read_config_dword(pci, PCI_COMMAND, &cmd); 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci /* Set up X-Fi core PCI configuration space. */ 185062306a36Sopenharmony_ci /* Switch to X-Fi config space with BAR0 exposed. */ 185162306a36Sopenharmony_ci pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x87654321); 185262306a36Sopenharmony_ci /* Copy UAA's BAR5 into X-Fi BAR0 */ 185362306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_BASE_ADDRESS_0, bar5); 185462306a36Sopenharmony_ci /* Switch to X-Fi config space without BAR0 exposed. */ 185562306a36Sopenharmony_ci pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x12345678); 185662306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, bar1); 185762306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_BASE_ADDRESS_2, bar2); 185862306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_BASE_ADDRESS_3, bar3); 185962306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_BASE_ADDRESS_4, bar4); 186062306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_INTERRUPT_LINE, irq); 186162306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_CACHE_LINE_SIZE, cl_size); 186262306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_LATENCY_TIMER, l_timer); 186362306a36Sopenharmony_ci pci_write_config_dword(pci, UAA_CFG_PWRSTATUS, pwr); 186462306a36Sopenharmony_ci pci_write_config_dword(pci, PCI_COMMAND, cmd); 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci /* Switch to X-Fi mode */ 186762306a36Sopenharmony_ci writel(CTLX, (mem_base + UAA_CORE_CHANGE)); 186862306a36Sopenharmony_ci writel(CTL_, (mem_base + UAA_CORE_CHANGE)); 186962306a36Sopenharmony_ci writel(CTLF, (mem_base + UAA_CORE_CHANGE)); 187062306a36Sopenharmony_ci writel(CTLi, (mem_base + UAA_CORE_CHANGE)); 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci iounmap(mem_base); 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci return 0; 187562306a36Sopenharmony_ci} 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_cistatic irqreturn_t ct_20k1_interrupt(int irq, void *dev_id) 187862306a36Sopenharmony_ci{ 187962306a36Sopenharmony_ci struct hw *hw = dev_id; 188062306a36Sopenharmony_ci unsigned int status; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci status = hw_read_20kx(hw, GIP); 188362306a36Sopenharmony_ci if (!status) 188462306a36Sopenharmony_ci return IRQ_NONE; 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci if (hw->irq_callback) 188762306a36Sopenharmony_ci hw->irq_callback(hw->irq_callback_data, status); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci hw_write_20kx(hw, GIP, status); 189062306a36Sopenharmony_ci return IRQ_HANDLED; 189162306a36Sopenharmony_ci} 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_cistatic int hw_card_start(struct hw *hw) 189462306a36Sopenharmony_ci{ 189562306a36Sopenharmony_ci int err; 189662306a36Sopenharmony_ci struct pci_dev *pci = hw->pci; 189762306a36Sopenharmony_ci const unsigned int dma_bits = BITS_PER_LONG; 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci err = pci_enable_device(pci); 190062306a36Sopenharmony_ci if (err < 0) 190162306a36Sopenharmony_ci return err; 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci /* Set DMA transfer mask */ 190462306a36Sopenharmony_ci if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits))) 190562306a36Sopenharmony_ci dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32)); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci if (!hw->io_base) { 190862306a36Sopenharmony_ci err = pci_request_regions(pci, "XFi"); 190962306a36Sopenharmony_ci if (err < 0) 191062306a36Sopenharmony_ci goto error1; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci if (hw->model == CTUAA) 191362306a36Sopenharmony_ci hw->io_base = pci_resource_start(pci, 5); 191462306a36Sopenharmony_ci else 191562306a36Sopenharmony_ci hw->io_base = pci_resource_start(pci, 0); 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci } 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci /* Switch to X-Fi mode from UAA mode if needed */ 192062306a36Sopenharmony_ci if (hw->model == CTUAA) { 192162306a36Sopenharmony_ci err = uaa_to_xfi(pci); 192262306a36Sopenharmony_ci if (err) 192362306a36Sopenharmony_ci goto error2; 192462306a36Sopenharmony_ci 192562306a36Sopenharmony_ci } 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci if (hw->irq < 0) { 192862306a36Sopenharmony_ci err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, 192962306a36Sopenharmony_ci KBUILD_MODNAME, hw); 193062306a36Sopenharmony_ci if (err < 0) { 193162306a36Sopenharmony_ci dev_err(hw->card->dev, 193262306a36Sopenharmony_ci "XFi: Cannot get irq %d\n", pci->irq); 193362306a36Sopenharmony_ci goto error2; 193462306a36Sopenharmony_ci } 193562306a36Sopenharmony_ci hw->irq = pci->irq; 193662306a36Sopenharmony_ci hw->card->sync_irq = hw->irq; 193762306a36Sopenharmony_ci } 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci pci_set_master(pci); 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci return 0; 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_cierror2: 194462306a36Sopenharmony_ci pci_release_regions(pci); 194562306a36Sopenharmony_ci hw->io_base = 0; 194662306a36Sopenharmony_cierror1: 194762306a36Sopenharmony_ci pci_disable_device(pci); 194862306a36Sopenharmony_ci return err; 194962306a36Sopenharmony_ci} 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_cistatic int hw_card_stop(struct hw *hw) 195262306a36Sopenharmony_ci{ 195362306a36Sopenharmony_ci unsigned int data; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci /* disable transport bus master and queueing of request */ 195662306a36Sopenharmony_ci hw_write_20kx(hw, TRNCTL, 0x00); 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci /* disable pll */ 195962306a36Sopenharmony_ci data = hw_read_20kx(hw, PLLCTL); 196062306a36Sopenharmony_ci hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12)))); 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci return 0; 196362306a36Sopenharmony_ci} 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_cistatic int hw_card_shutdown(struct hw *hw) 196662306a36Sopenharmony_ci{ 196762306a36Sopenharmony_ci if (hw->irq >= 0) 196862306a36Sopenharmony_ci free_irq(hw->irq, hw); 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci hw->irq = -1; 197162306a36Sopenharmony_ci iounmap(hw->mem_base); 197262306a36Sopenharmony_ci hw->mem_base = NULL; 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci if (hw->io_base) 197562306a36Sopenharmony_ci pci_release_regions(hw->pci); 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci hw->io_base = 0; 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci pci_disable_device(hw->pci); 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci return 0; 198262306a36Sopenharmony_ci} 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_cistatic int hw_card_init(struct hw *hw, struct card_conf *info) 198562306a36Sopenharmony_ci{ 198662306a36Sopenharmony_ci int err; 198762306a36Sopenharmony_ci unsigned int gctl; 198862306a36Sopenharmony_ci u32 data; 198962306a36Sopenharmony_ci struct dac_conf dac_info = {0}; 199062306a36Sopenharmony_ci struct adc_conf adc_info = {0}; 199162306a36Sopenharmony_ci struct daio_conf daio_info = {0}; 199262306a36Sopenharmony_ci struct trn_conf trn_info = {0}; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci /* Get PCI io port base address and do Hendrix switch if needed. */ 199562306a36Sopenharmony_ci err = hw_card_start(hw); 199662306a36Sopenharmony_ci if (err) 199762306a36Sopenharmony_ci return err; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci /* PLL init */ 200062306a36Sopenharmony_ci err = hw_pll_init(hw, info->rsr); 200162306a36Sopenharmony_ci if (err < 0) 200262306a36Sopenharmony_ci return err; 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci /* kick off auto-init */ 200562306a36Sopenharmony_ci err = hw_auto_init(hw); 200662306a36Sopenharmony_ci if (err < 0) 200762306a36Sopenharmony_ci return err; 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ci /* Enable audio ring */ 201062306a36Sopenharmony_ci gctl = hw_read_20kx(hw, GCTL); 201162306a36Sopenharmony_ci set_field(&gctl, GCTL_EAC, 1); 201262306a36Sopenharmony_ci set_field(&gctl, GCTL_DBP, 1); 201362306a36Sopenharmony_ci set_field(&gctl, GCTL_TBP, 1); 201462306a36Sopenharmony_ci set_field(&gctl, GCTL_FBP, 1); 201562306a36Sopenharmony_ci set_field(&gctl, GCTL_ET, 1); 201662306a36Sopenharmony_ci hw_write_20kx(hw, GCTL, gctl); 201762306a36Sopenharmony_ci mdelay(10); 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci /* Reset all global pending interrupts */ 202062306a36Sopenharmony_ci hw_write_20kx(hw, GIE, 0); 202162306a36Sopenharmony_ci /* Reset all SRC pending interrupts */ 202262306a36Sopenharmony_ci hw_write_20kx(hw, SRCIP, 0); 202362306a36Sopenharmony_ci msleep(30); 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci /* Detect the card ID and configure GPIO accordingly. */ 202662306a36Sopenharmony_ci switch (hw->model) { 202762306a36Sopenharmony_ci case CTSB055X: 202862306a36Sopenharmony_ci hw_write_20kx(hw, GPIOCTL, 0x13fe); 202962306a36Sopenharmony_ci break; 203062306a36Sopenharmony_ci case CTSB073X: 203162306a36Sopenharmony_ci hw_write_20kx(hw, GPIOCTL, 0x00e6); 203262306a36Sopenharmony_ci break; 203362306a36Sopenharmony_ci case CTUAA: 203462306a36Sopenharmony_ci hw_write_20kx(hw, GPIOCTL, 0x00c2); 203562306a36Sopenharmony_ci break; 203662306a36Sopenharmony_ci default: 203762306a36Sopenharmony_ci hw_write_20kx(hw, GPIOCTL, 0x01e6); 203862306a36Sopenharmony_ci break; 203962306a36Sopenharmony_ci } 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci trn_info.vm_pgt_phys = info->vm_pgt_phys; 204262306a36Sopenharmony_ci err = hw_trn_init(hw, &trn_info); 204362306a36Sopenharmony_ci if (err < 0) 204462306a36Sopenharmony_ci return err; 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci daio_info.msr = info->msr; 204762306a36Sopenharmony_ci err = hw_daio_init(hw, &daio_info); 204862306a36Sopenharmony_ci if (err < 0) 204962306a36Sopenharmony_ci return err; 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci dac_info.msr = info->msr; 205262306a36Sopenharmony_ci err = hw_dac_init(hw, &dac_info); 205362306a36Sopenharmony_ci if (err < 0) 205462306a36Sopenharmony_ci return err; 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci adc_info.msr = info->msr; 205762306a36Sopenharmony_ci adc_info.input = ADC_LINEIN; 205862306a36Sopenharmony_ci adc_info.mic20db = 0; 205962306a36Sopenharmony_ci err = hw_adc_init(hw, &adc_info); 206062306a36Sopenharmony_ci if (err < 0) 206162306a36Sopenharmony_ci return err; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci data = hw_read_20kx(hw, SRCMCTL); 206462306a36Sopenharmony_ci data |= 0x1; /* Enables input from the audio ring */ 206562306a36Sopenharmony_ci hw_write_20kx(hw, SRCMCTL, data); 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci return 0; 206862306a36Sopenharmony_ci} 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 207162306a36Sopenharmony_cistatic int hw_suspend(struct hw *hw) 207262306a36Sopenharmony_ci{ 207362306a36Sopenharmony_ci struct pci_dev *pci = hw->pci; 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci hw_card_stop(hw); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci if (hw->model == CTUAA) { 207862306a36Sopenharmony_ci /* Switch to UAA config space. */ 207962306a36Sopenharmony_ci pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); 208062306a36Sopenharmony_ci } 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci return 0; 208362306a36Sopenharmony_ci} 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_cistatic int hw_resume(struct hw *hw, struct card_conf *info) 208662306a36Sopenharmony_ci{ 208762306a36Sopenharmony_ci /* Re-initialize card hardware. */ 208862306a36Sopenharmony_ci return hw_card_init(hw, info); 208962306a36Sopenharmony_ci} 209062306a36Sopenharmony_ci#endif 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_cistatic u32 hw_read_20kx(struct hw *hw, u32 reg) 209362306a36Sopenharmony_ci{ 209462306a36Sopenharmony_ci u32 value; 209562306a36Sopenharmony_ci unsigned long flags; 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci spin_lock_irqsave( 209862306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 209962306a36Sopenharmony_ci outl(reg, hw->io_base + 0x0); 210062306a36Sopenharmony_ci value = inl(hw->io_base + 0x4); 210162306a36Sopenharmony_ci spin_unlock_irqrestore( 210262306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci return value; 210562306a36Sopenharmony_ci} 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_cistatic void hw_write_20kx(struct hw *hw, u32 reg, u32 data) 210862306a36Sopenharmony_ci{ 210962306a36Sopenharmony_ci unsigned long flags; 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci spin_lock_irqsave( 211262306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 211362306a36Sopenharmony_ci outl(reg, hw->io_base + 0x0); 211462306a36Sopenharmony_ci outl(data, hw->io_base + 0x4); 211562306a36Sopenharmony_ci spin_unlock_irqrestore( 211662306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_20k1_lock, flags); 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci} 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_cistatic u32 hw_read_pci(struct hw *hw, u32 reg) 212162306a36Sopenharmony_ci{ 212262306a36Sopenharmony_ci u32 value; 212362306a36Sopenharmony_ci unsigned long flags; 212462306a36Sopenharmony_ci 212562306a36Sopenharmony_ci spin_lock_irqsave( 212662306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 212762306a36Sopenharmony_ci outl(reg, hw->io_base + 0x10); 212862306a36Sopenharmony_ci value = inl(hw->io_base + 0x14); 212962306a36Sopenharmony_ci spin_unlock_irqrestore( 213062306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_ci return value; 213362306a36Sopenharmony_ci} 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_cistatic void hw_write_pci(struct hw *hw, u32 reg, u32 data) 213662306a36Sopenharmony_ci{ 213762306a36Sopenharmony_ci unsigned long flags; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci spin_lock_irqsave( 214062306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 214162306a36Sopenharmony_ci outl(reg, hw->io_base + 0x10); 214262306a36Sopenharmony_ci outl(data, hw->io_base + 0x14); 214362306a36Sopenharmony_ci spin_unlock_irqrestore( 214462306a36Sopenharmony_ci &container_of(hw, struct hw20k1, hw)->reg_pci_lock, flags); 214562306a36Sopenharmony_ci} 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_cistatic const struct hw ct20k1_preset = { 214862306a36Sopenharmony_ci .irq = -1, 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci .card_init = hw_card_init, 215162306a36Sopenharmony_ci .card_stop = hw_card_stop, 215262306a36Sopenharmony_ci .pll_init = hw_pll_init, 215362306a36Sopenharmony_ci .is_adc_source_selected = hw_is_adc_input_selected, 215462306a36Sopenharmony_ci .select_adc_source = hw_adc_input_select, 215562306a36Sopenharmony_ci .capabilities = hw_capabilities, 215662306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 215762306a36Sopenharmony_ci .suspend = hw_suspend, 215862306a36Sopenharmony_ci .resume = hw_resume, 215962306a36Sopenharmony_ci#endif 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, 216262306a36Sopenharmony_ci .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, 216362306a36Sopenharmony_ci .src_mgr_get_ctrl_blk = src_mgr_get_ctrl_blk, 216462306a36Sopenharmony_ci .src_mgr_put_ctrl_blk = src_mgr_put_ctrl_blk, 216562306a36Sopenharmony_ci .src_set_state = src_set_state, 216662306a36Sopenharmony_ci .src_set_bm = src_set_bm, 216762306a36Sopenharmony_ci .src_set_rsr = src_set_rsr, 216862306a36Sopenharmony_ci .src_set_sf = src_set_sf, 216962306a36Sopenharmony_ci .src_set_wr = src_set_wr, 217062306a36Sopenharmony_ci .src_set_pm = src_set_pm, 217162306a36Sopenharmony_ci .src_set_rom = src_set_rom, 217262306a36Sopenharmony_ci .src_set_vo = src_set_vo, 217362306a36Sopenharmony_ci .src_set_st = src_set_st, 217462306a36Sopenharmony_ci .src_set_ie = src_set_ie, 217562306a36Sopenharmony_ci .src_set_ilsz = src_set_ilsz, 217662306a36Sopenharmony_ci .src_set_bp = src_set_bp, 217762306a36Sopenharmony_ci .src_set_cisz = src_set_cisz, 217862306a36Sopenharmony_ci .src_set_ca = src_set_ca, 217962306a36Sopenharmony_ci .src_set_sa = src_set_sa, 218062306a36Sopenharmony_ci .src_set_la = src_set_la, 218162306a36Sopenharmony_ci .src_set_pitch = src_set_pitch, 218262306a36Sopenharmony_ci .src_set_dirty = src_set_dirty, 218362306a36Sopenharmony_ci .src_set_clear_zbufs = src_set_clear_zbufs, 218462306a36Sopenharmony_ci .src_set_dirty_all = src_set_dirty_all, 218562306a36Sopenharmony_ci .src_commit_write = src_commit_write, 218662306a36Sopenharmony_ci .src_get_ca = src_get_ca, 218762306a36Sopenharmony_ci .src_get_dirty = src_get_dirty, 218862306a36Sopenharmony_ci .src_dirty_conj_mask = src_dirty_conj_mask, 218962306a36Sopenharmony_ci .src_mgr_enbs_src = src_mgr_enbs_src, 219062306a36Sopenharmony_ci .src_mgr_enb_src = src_mgr_enb_src, 219162306a36Sopenharmony_ci .src_mgr_dsb_src = src_mgr_dsb_src, 219262306a36Sopenharmony_ci .src_mgr_commit_write = src_mgr_commit_write, 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_ci .srcimp_mgr_get_ctrl_blk = srcimp_mgr_get_ctrl_blk, 219562306a36Sopenharmony_ci .srcimp_mgr_put_ctrl_blk = srcimp_mgr_put_ctrl_blk, 219662306a36Sopenharmony_ci .srcimp_mgr_set_imaparc = srcimp_mgr_set_imaparc, 219762306a36Sopenharmony_ci .srcimp_mgr_set_imapuser = srcimp_mgr_set_imapuser, 219862306a36Sopenharmony_ci .srcimp_mgr_set_imapnxt = srcimp_mgr_set_imapnxt, 219962306a36Sopenharmony_ci .srcimp_mgr_set_imapaddr = srcimp_mgr_set_imapaddr, 220062306a36Sopenharmony_ci .srcimp_mgr_commit_write = srcimp_mgr_commit_write, 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci .amixer_rsc_get_ctrl_blk = amixer_rsc_get_ctrl_blk, 220362306a36Sopenharmony_ci .amixer_rsc_put_ctrl_blk = amixer_rsc_put_ctrl_blk, 220462306a36Sopenharmony_ci .amixer_mgr_get_ctrl_blk = amixer_mgr_get_ctrl_blk, 220562306a36Sopenharmony_ci .amixer_mgr_put_ctrl_blk = amixer_mgr_put_ctrl_blk, 220662306a36Sopenharmony_ci .amixer_set_mode = amixer_set_mode, 220762306a36Sopenharmony_ci .amixer_set_iv = amixer_set_iv, 220862306a36Sopenharmony_ci .amixer_set_x = amixer_set_x, 220962306a36Sopenharmony_ci .amixer_set_y = amixer_set_y, 221062306a36Sopenharmony_ci .amixer_set_sadr = amixer_set_sadr, 221162306a36Sopenharmony_ci .amixer_set_se = amixer_set_se, 221262306a36Sopenharmony_ci .amixer_set_dirty = amixer_set_dirty, 221362306a36Sopenharmony_ci .amixer_set_dirty_all = amixer_set_dirty_all, 221462306a36Sopenharmony_ci .amixer_commit_write = amixer_commit_write, 221562306a36Sopenharmony_ci .amixer_get_y = amixer_get_y, 221662306a36Sopenharmony_ci .amixer_get_dirty = amixer_get_dirty, 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci .dai_get_ctrl_blk = dai_get_ctrl_blk, 221962306a36Sopenharmony_ci .dai_put_ctrl_blk = dai_put_ctrl_blk, 222062306a36Sopenharmony_ci .dai_srt_set_srco = dai_srt_set_srcr, 222162306a36Sopenharmony_ci .dai_srt_set_srcm = dai_srt_set_srcl, 222262306a36Sopenharmony_ci .dai_srt_set_rsr = dai_srt_set_rsr, 222362306a36Sopenharmony_ci .dai_srt_set_drat = dai_srt_set_drat, 222462306a36Sopenharmony_ci .dai_srt_set_ec = dai_srt_set_ec, 222562306a36Sopenharmony_ci .dai_srt_set_et = dai_srt_set_et, 222662306a36Sopenharmony_ci .dai_commit_write = dai_commit_write, 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci .dao_get_ctrl_blk = dao_get_ctrl_blk, 222962306a36Sopenharmony_ci .dao_put_ctrl_blk = dao_put_ctrl_blk, 223062306a36Sopenharmony_ci .dao_set_spos = dao_set_spos, 223162306a36Sopenharmony_ci .dao_commit_write = dao_commit_write, 223262306a36Sopenharmony_ci .dao_get_spos = dao_get_spos, 223362306a36Sopenharmony_ci 223462306a36Sopenharmony_ci .daio_mgr_get_ctrl_blk = daio_mgr_get_ctrl_blk, 223562306a36Sopenharmony_ci .daio_mgr_put_ctrl_blk = daio_mgr_put_ctrl_blk, 223662306a36Sopenharmony_ci .daio_mgr_enb_dai = daio_mgr_enb_dai, 223762306a36Sopenharmony_ci .daio_mgr_dsb_dai = daio_mgr_dsb_dai, 223862306a36Sopenharmony_ci .daio_mgr_enb_dao = daio_mgr_enb_dao, 223962306a36Sopenharmony_ci .daio_mgr_dsb_dao = daio_mgr_dsb_dao, 224062306a36Sopenharmony_ci .daio_mgr_dao_init = daio_mgr_dao_init, 224162306a36Sopenharmony_ci .daio_mgr_set_imaparc = daio_mgr_set_imaparc, 224262306a36Sopenharmony_ci .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, 224362306a36Sopenharmony_ci .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, 224462306a36Sopenharmony_ci .daio_mgr_commit_write = daio_mgr_commit_write, 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_ci .set_timer_irq = set_timer_irq, 224762306a36Sopenharmony_ci .set_timer_tick = set_timer_tick, 224862306a36Sopenharmony_ci .get_wc = get_wc, 224962306a36Sopenharmony_ci}; 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ciint create_20k1_hw_obj(struct hw **rhw) 225262306a36Sopenharmony_ci{ 225362306a36Sopenharmony_ci struct hw20k1 *hw20k1; 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci *rhw = NULL; 225662306a36Sopenharmony_ci hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL); 225762306a36Sopenharmony_ci if (!hw20k1) 225862306a36Sopenharmony_ci return -ENOMEM; 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci spin_lock_init(&hw20k1->reg_20k1_lock); 226162306a36Sopenharmony_ci spin_lock_init(&hw20k1->reg_pci_lock); 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci hw20k1->hw = ct20k1_preset; 226462306a36Sopenharmony_ci 226562306a36Sopenharmony_ci *rhw = &hw20k1->hw; 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci return 0; 226862306a36Sopenharmony_ci} 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ciint destroy_20k1_hw_obj(struct hw *hw) 227162306a36Sopenharmony_ci{ 227262306a36Sopenharmony_ci if (hw->io_base) 227362306a36Sopenharmony_ci hw_card_shutdown(hw); 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_ci kfree(container_of(hw, struct hw20k1, hw)); 227662306a36Sopenharmony_ci return 0; 227762306a36Sopenharmony_ci} 2278