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