Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * drivers/mfd/si476x-cmd.c -- Subroutines implementing command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * protocol of si476x series of chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * Copyright (C) 2012 Innovative Converged Devices(ICD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * Copyright (C) 2013 Andrey Smirnov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/videodev2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/mfd/si476x-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #define msb(x)                  ((u8)((u16) x >> 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #define lsb(x)                  ((u8)((u16) x &  0x00FF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define CMD_POWER_UP				0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #define CMD_POWER_UP_A10_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #define CMD_POWER_UP_A10_NARGS			5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #define CMD_POWER_UP_A20_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #define CMD_POWER_UP_A20_NARGS			5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #define POWER_UP_DELAY_MS			110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define CMD_POWER_DOWN				0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #define CMD_POWER_DOWN_A10_NRESP		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #define CMD_POWER_DOWN_A20_NRESP		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #define CMD_POWER_DOWN_A20_NARGS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #define CMD_FUNC_INFO				0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #define CMD_FUNC_INFO_NRESP			7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define CMD_SET_PROPERTY			0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #define CMD_SET_PROPERTY_NARGS			5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #define CMD_SET_PROPERTY_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #define CMD_GET_PROPERTY			0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #define CMD_GET_PROPERTY_NARGS			3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define CMD_GET_PROPERTY_NRESP			4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #define CMD_AGC_STATUS				0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #define CMD_AGC_STATUS_NRESP_A10		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #define CMD_AGC_STATUS_NRESP_A20                6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define PIN_CFG_BYTE(x) (0x7F & (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define CMD_DIG_AUDIO_PIN_CFG			0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define CMD_DIG_AUDIO_PIN_CFG_NARGS		4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define CMD_DIG_AUDIO_PIN_CFG_NRESP		5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define CMD_ZIF_PIN_CFG				0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define CMD_ZIF_PIN_CFG_NARGS			4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define CMD_ZIF_PIN_CFG_NRESP			5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define CMD_IC_LINK_GPO_CTL_PIN_CFG		0x1A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #define CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define CMD_ANA_AUDIO_PIN_CFG			0x1B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define CMD_ANA_AUDIO_PIN_CFG_NARGS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define CMD_ANA_AUDIO_PIN_CFG_NRESP		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) #define CMD_INTB_PIN_CFG			0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) #define CMD_INTB_PIN_CFG_NARGS			2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) #define CMD_INTB_PIN_CFG_A10_NRESP		6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define CMD_INTB_PIN_CFG_A20_NRESP		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define CMD_FM_TUNE_FREQ			0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define CMD_FM_TUNE_FREQ_A10_NARGS		5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define CMD_FM_TUNE_FREQ_A20_NARGS		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define CMD_FM_TUNE_FREQ_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define CMD_FM_RSQ_STATUS			0x32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #define CMD_FM_RSQ_STATUS_A10_NARGS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define CMD_FM_RSQ_STATUS_A10_NRESP		17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define CMD_FM_RSQ_STATUS_A30_NARGS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #define CMD_FM_RSQ_STATUS_A30_NRESP		23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #define CMD_FM_SEEK_START			0x31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define CMD_FM_SEEK_START_NARGS			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #define CMD_FM_SEEK_START_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #define CMD_FM_RDS_STATUS			0x36
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) #define CMD_FM_RDS_STATUS_NARGS			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) #define CMD_FM_RDS_STATUS_NRESP			16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) #define CMD_FM_RDS_BLOCKCOUNT			0x37
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #define CMD_FM_RDS_BLOCKCOUNT_NARGS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define CMD_FM_RDS_BLOCKCOUNT_NRESP		8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) #define CMD_FM_PHASE_DIVERSITY			0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define CMD_FM_PHASE_DIVERSITY_NARGS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) #define CMD_FM_PHASE_DIVERSITY_NRESP		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) #define CMD_FM_PHASE_DIV_STATUS			0x39
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) #define CMD_FM_PHASE_DIV_STATUS_NRESP		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) #define CMD_AM_TUNE_FREQ			0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) #define CMD_AM_TUNE_FREQ_NARGS			3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) #define CMD_AM_TUNE_FREQ_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define CMD_AM_RSQ_STATUS			0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define CMD_AM_RSQ_STATUS_NARGS			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) #define CMD_AM_RSQ_STATUS_NRESP			13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) #define CMD_AM_SEEK_START			0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) #define CMD_AM_SEEK_START_NARGS			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) #define CMD_AM_SEEK_START_NRESP			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) #define CMD_AM_ACF_STATUS			0x45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) #define CMD_AM_ACF_STATUS_NRESP			6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) #define CMD_AM_ACF_STATUS_NARGS			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) #define CMD_FM_ACF_STATUS			0x35
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) #define CMD_FM_ACF_STATUS_NRESP			8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) #define CMD_FM_ACF_STATUS_NARGS			1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) #define CMD_MAX_ARGS_COUNT			(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) enum si476x_acf_status_report_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	SI476X_ACF_BLEND_INT	= (1 << 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	SI476X_ACF_HIBLEND_INT	= (1 << 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	SI476X_ACF_HICUT_INT	= (1 << 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	SI476X_ACF_CHBW_INT	= (1 << 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	SI476X_ACF_SOFTMUTE_INT	= (1 << 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	SI476X_ACF_SMUTE	= (1 << 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	SI476X_ACF_SMATTN	= 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	SI476X_ACF_PILOT	= (1 << 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	SI476X_ACF_STBLEND	= ~SI476X_ACF_PILOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) enum si476x_agc_status_report_bits {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	SI476X_AGC_MXHI		= (1 << 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	SI476X_AGC_MXLO		= (1 << 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	SI476X_AGC_LNAHI	= (1 << 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	SI476X_AGC_LNALO	= (1 << 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) enum si476x_errors {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	SI476X_ERR_BAD_COMMAND		= 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	SI476X_ERR_BAD_ARG1		= 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	SI476X_ERR_BAD_ARG2		= 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	SI476X_ERR_BAD_ARG3		= 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	SI476X_ERR_BAD_ARG4		= 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	SI476X_ERR_BUSY			= 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	SI476X_ERR_BAD_INTERNAL_MEMORY  = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	SI476X_ERR_BAD_PATCH		= 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	SI476X_ERR_BAD_BOOT_MODE	= 0x31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	SI476X_ERR_BAD_PROPERTY		= 0x40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) static int si476x_core_parse_and_nag_about_error(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	char *cause;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	u8 buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	if (core->revision != SI476X_REVISION_A10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		err = si476x_core_i2c_xfer(core, SI476X_I2C_RECV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 					   buffer, sizeof(buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 		if (err == sizeof(buffer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 			switch (buffer[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 			case SI476X_ERR_BAD_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 				cause = "Bad command";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 			case SI476X_ERR_BAD_ARG1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 				cause = "Bad argument #1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 			case SI476X_ERR_BAD_ARG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 				cause = "Bad argument #2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 			case SI476X_ERR_BAD_ARG3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 				cause = "Bad argument #3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 			case SI476X_ERR_BAD_ARG4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 				cause = "Bad argument #4";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 			case SI476X_ERR_BUSY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 				cause = "Chip is busy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 				err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 			case SI476X_ERR_BAD_INTERNAL_MEMORY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 				cause = "Bad internal memory";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 				err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			case SI476X_ERR_BAD_PATCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 				cause = "Bad patch";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 			case SI476X_ERR_BAD_BOOT_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 				cause = "Bad boot mode";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 			case SI476X_ERR_BAD_PROPERTY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 				cause = "Bad property";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 				err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 			default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 				cause = "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 				err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 			dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 				"[Chip error status]: %s\n", cause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 			dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 				"Failed to fetch error code\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 			err = (err >= 0) ? -EIO : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242)  * si476x_core_send_command() - sends a command to si476x and waits its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243)  * response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244)  * @core:     si476x_device structure for the device we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245)  *            communicating with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246)  * @command:  command id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247)  * @args:     command arguments we are sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248)  * @argn:     actual size of @args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249)  * @resp:     buffer to place the expected response from the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250)  * @respn:    actual size of @resp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)  * @usecs:    amount of time to wait before reading the response (in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)  *            usecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)  * Function returns 0 on succsess and negative error code on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)  * failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) static int si476x_core_send_command(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 				    const u8 command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 				    const u8 args[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 				    const int argn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 				    u8 resp[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 				    const int respn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 				    const int usecs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	struct i2c_client *client = core->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	u8  data[CMD_MAX_ARGS_COUNT + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	if (argn > CMD_MAX_ARGS_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	if (!client->adapter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 		err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	/* First send the command and its arguments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	data[0] = command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	memcpy(&data[1], args, argn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	dev_dbg(&client->dev, "Command:\n %*ph\n", argn + 1, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	err = si476x_core_i2c_xfer(core, SI476X_I2C_SEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 				   (char *) data, argn + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	if (err != argn + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 			"Error while sending command 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 			command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 		err = (err >= 0) ? -EIO : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	/* Set CTS to zero only after the command is send to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	 * possible racing conditions when working in polling mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	atomic_set(&core->cts, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	/* if (unlikely(command == CMD_POWER_DOWN) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	if (!wait_event_timeout(core->command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 				atomic_read(&core->cts),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 				usecs_to_jiffies(usecs) + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		dev_warn(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 			 "(%s) [CMD 0x%02x] Answer timeout.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 			 __func__, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	  When working in polling mode, for some reason the tuner will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	  report CTS bit as being set in the first status byte read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	  but all the consequtive ones will return zeros until the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	  tuner is actually completed the POWER_UP command. To
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	  workaround that we wait for second CTS to be reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	if (unlikely(!core->client->irq && command == CMD_POWER_UP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 		if (!wait_event_timeout(core->command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 					atomic_read(&core->cts),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 					usecs_to_jiffies(usecs) + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 			dev_warn(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 				 "(%s) Power up took too much time.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 				 __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	/* Then get the response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	err = si476x_core_i2c_xfer(core, SI476X_I2C_RECV, resp, respn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	if (err != respn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 			"Error while reading response for command 0x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 			command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 		err = (err >= 0) ? -EIO : err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	dev_dbg(&client->dev, "Response:\n %*ph\n", respn, resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	if (resp[0] & SI476X_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 			"[CMD 0x%02x] Chip set error flag\n", command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		err = si476x_core_parse_and_nag_about_error(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	if (!(resp[0] & SI476X_CTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) static int si476x_cmd_clear_stc(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	struct si476x_rsq_status_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 		.primary	= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		.rsqack		= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 		.attune		= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		.cancel		= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 		.stcack		= true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	switch (core->power_up_parameters.func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	case SI476X_FUNC_FM_RECEIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		err = si476x_core_cmd_fm_rsq_status(core, &args, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	case SI476X_FUNC_AM_RECEIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 		err = si476x_core_cmd_am_rsq_status(core, &args, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) static int si476x_cmd_tune_seek_freq(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 				     uint8_t cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 				     const uint8_t args[], size_t argn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 				     uint8_t *resp, size_t respn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	atomic_set(&core->stc, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	err = si476x_core_send_command(core, cmd, args, argn, resp, respn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 				       SI476X_TIMEOUT_TUNE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 		wait_event_killable(core->tuning,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 				    atomic_read(&core->stc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 		si476x_cmd_clear_stc(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393)  * si476x_cmd_func_info() - send 'FUNC_INFO' command to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)  * @core: device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395)  * @info:  struct si476x_func_info to fill all the information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)  *         returned by the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)  * The command requests the firmware and patch version for currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)  * loaded firmware (dependent on the function of the device FM/AM/WB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  * Function returns 0 on succsess and negative error code on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)  * failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) int si476x_core_cmd_func_info(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 			      struct si476x_func_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	u8  resp[CMD_FUNC_INFO_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	err = si476x_core_send_command(core, CMD_FUNC_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 				       NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	info->firmware.major    = resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	info->firmware.minor[0] = resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	info->firmware.minor[1] = resp[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	info->patch_id = ((u16) resp[4] << 8) | resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	info->func     = resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) EXPORT_SYMBOL_GPL(si476x_core_cmd_func_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427)  * si476x_cmd_set_property() - send 'SET_PROPERTY' command to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428)  * @core:    device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429)  * @property: property address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430)  * @value:    property value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432)  * Function returns 0 on succsess and negative error code on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433)  * failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) int si476x_core_cmd_set_property(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 				 u16 property, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	u8       resp[CMD_SET_PROPERTY_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	const u8 args[CMD_SET_PROPERTY_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 		msb(property),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		lsb(property),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		msb(value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		lsb(value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	return si476x_core_send_command(core, CMD_SET_PROPERTY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) EXPORT_SYMBOL_GPL(si476x_core_cmd_set_property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455)  * si476x_cmd_get_property() - send 'GET_PROPERTY' command to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456)  * @core:    device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457)  * @property: property address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459)  * Function return the value of property as u16 on success or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460)  * negative error on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) int si476x_core_cmd_get_property(struct si476x_core *core, u16 property)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	u8       resp[CMD_GET_PROPERTY_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	const u8 args[CMD_GET_PROPERTY_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		msb(property),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		lsb(property),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	err = si476x_core_send_command(core, CMD_GET_PROPERTY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		return get_unaligned_be16(resp + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) EXPORT_SYMBOL_GPL(si476x_core_cmd_get_property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484)  * si476x_cmd_dig_audio_pin_cfg() - send 'DIG_AUDIO_PIN_CFG' command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485)  * the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486)  * @core: device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487)  * @dclk:  DCLK pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488)  *	   #SI476X_DCLK_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489)  *         #SI476X_DCLK_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490)  *                                 enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)  *         #SI476X_DCLK_DAUDIO   - set the pin to be a part of digital
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492)  *                                 audio interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493)  * @dfs:   DFS pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494)  *         #SI476X_DFS_NOOP      - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)  *         #SI476X_DFS_TRISTATE  - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)  *                             enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)  *      SI476X_DFS_DAUDIO    - set the pin to be a part of digital
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498)  *                             audio interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499)  * @dout: - DOUT pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500)  *      SI476X_DOUT_NOOP       - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)  *      SI476X_DOUT_TRISTATE   - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502)  *                               enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)  *      SI476X_DOUT_I2S_OUTPUT - set this pin to be digital out on I2S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)  *                               port 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505)  *      SI476X_DOUT_I2S_INPUT  - set this pin to be digital in on I2S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506)  *                               port 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507)  * @xout: - XOUT pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508)  *	SI476X_XOUT_NOOP        - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509)  *      SI476X_XOUT_TRISTATE    - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510)  *                                enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511)  *      SI476X_XOUT_I2S_INPUT   - set this pin to be digital in on I2S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512)  *                                port 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513)  *      SI476X_XOUT_MODE_SELECT - set this pin to be the input that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514)  *                                selects the mode of the I2S audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515)  *                                combiner (analog or HD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516)  *                                [SI4761/63/65/67 Only]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) int si476x_core_cmd_dig_audio_pin_cfg(struct  si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 				      enum si476x_dclk_config dclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 				      enum si476x_dfs_config  dfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 				      enum si476x_dout_config dout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 				      enum si476x_xout_config xout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	u8       resp[CMD_DIG_AUDIO_PIN_CFG_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	const u8 args[CMD_DIG_AUDIO_PIN_CFG_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		PIN_CFG_BYTE(dclk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		PIN_CFG_BYTE(dfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		PIN_CFG_BYTE(dout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		PIN_CFG_BYTE(xout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	return si476x_core_send_command(core, CMD_DIG_AUDIO_PIN_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) EXPORT_SYMBOL_GPL(si476x_core_cmd_dig_audio_pin_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542)  * si476x_cmd_zif_pin_cfg - send 'ZIF_PIN_CFG_COMMAND'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543)  * @core: - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544)  * @iqclk: - IQCL pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545)  *       SI476X_IQCLK_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546)  *       SI476X_IQCLK_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547)  *                               enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548)  *       SI476X_IQCLK_IQ       - set pin to be a part of I/Q interace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549)  *                               in master mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550)  * @iqfs: - IQFS pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551)  *       SI476X_IQFS_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552)  *       SI476X_IQFS_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553)  *                              enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554)  *       SI476X_IQFS_IQ       - set pin to be a part of I/Q interace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555)  *                              in master mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)  * @iout: - IOUT pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)  *       SI476X_IOUT_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)  *       SI476X_IOUT_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)  *                              enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)  *       SI476X_IOUT_OUTPUT   - set pin to be I out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)  * @qout: - QOUT pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)  *       SI476X_QOUT_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)  *       SI476X_QOUT_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564)  *                              enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565)  *       SI476X_QOUT_OUTPUT   - set pin to be Q out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) int si476x_core_cmd_zif_pin_cfg(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 				enum si476x_iqclk_config iqclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 				enum si476x_iqfs_config iqfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 				enum si476x_iout_config iout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 				enum si476x_qout_config qout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	u8       resp[CMD_ZIF_PIN_CFG_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	const u8 args[CMD_ZIF_PIN_CFG_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		PIN_CFG_BYTE(iqclk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		PIN_CFG_BYTE(iqfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		PIN_CFG_BYTE(iout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		PIN_CFG_BYTE(qout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	return si476x_core_send_command(core, CMD_ZIF_PIN_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) EXPORT_SYMBOL_GPL(si476x_core_cmd_zif_pin_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591)  * si476x_cmd_ic_link_gpo_ctl_pin_cfg - send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592)  * 'IC_LINK_GPIO_CTL_PIN_CFG' comand to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593)  * @core: - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594)  * @icin: - ICIN pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595)  *      SI476X_ICIN_NOOP      - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596)  *      SI476X_ICIN_TRISTATE  - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)  *                              enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598)  *      SI476X_ICIN_GPO1_HIGH - set pin to be an output, drive it high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599)  *      SI476X_ICIN_GPO1_LOW  - set pin to be an output, drive it low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600)  *      SI476X_ICIN_IC_LINK   - set the pin to be a part of Inter-Chip link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601)  * @icip: - ICIP pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602)  *      SI476X_ICIP_NOOP      - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603)  *      SI476X_ICIP_TRISTATE  - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604)  *                              enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605)  *      SI476X_ICIP_GPO1_HIGH - set pin to be an output, drive it high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606)  *      SI476X_ICIP_GPO1_LOW  - set pin to be an output, drive it low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607)  *      SI476X_ICIP_IC_LINK   - set the pin to be a part of Inter-Chip link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608)  * @icon: - ICON pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609)  *      SI476X_ICON_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610)  *      SI476X_ICON_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611)  *                             enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612)  *      SI476X_ICON_I2S      - set the pin to be a part of audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613)  *                             interface in slave mode (DCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614)  *      SI476X_ICON_IC_LINK  - set the pin to be a part of Inter-Chip link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615)  * @icop: - ICOP pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616)  *      SI476X_ICOP_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617)  *      SI476X_ICOP_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618)  *                             enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619)  *      SI476X_ICOP_I2S      - set the pin to be a part of audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620)  *                             interface in slave mode (DOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621)  *                             [Si4761/63/65/67 Only]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622)  *      SI476X_ICOP_IC_LINK  - set the pin to be a part of Inter-Chip link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) int si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 					    enum si476x_icin_config icin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 					    enum si476x_icip_config icip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 					    enum si476x_icon_config icon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 					    enum si476x_icop_config icop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	u8       resp[CMD_IC_LINK_GPO_CTL_PIN_CFG_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	const u8 args[CMD_IC_LINK_GPO_CTL_PIN_CFG_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		PIN_CFG_BYTE(icin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		PIN_CFG_BYTE(icip),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		PIN_CFG_BYTE(icon),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		PIN_CFG_BYTE(icop),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	return si476x_core_send_command(core, CMD_IC_LINK_GPO_CTL_PIN_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) EXPORT_SYMBOL_GPL(si476x_core_cmd_ic_link_gpo_ctl_pin_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648)  * si476x_cmd_ana_audio_pin_cfg - send 'ANA_AUDIO_PIN_CFG' to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649)  * device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650)  * @core: - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651)  * @lrout: - LROUT pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652)  *       SI476X_LROUT_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653)  *       SI476X_LROUT_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654)  *                               enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655)  *       SI476X_LROUT_AUDIO    - set pin to be audio output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656)  *       SI476X_LROUT_MPX      - set pin to be MPX output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) int si476x_core_cmd_ana_audio_pin_cfg(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 				      enum si476x_lrout_config lrout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	u8       resp[CMD_ANA_AUDIO_PIN_CFG_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	const u8 args[CMD_ANA_AUDIO_PIN_CFG_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		PIN_CFG_BYTE(lrout),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	return si476x_core_send_command(core, CMD_ANA_AUDIO_PIN_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) EXPORT_SYMBOL_GPL(si476x_core_cmd_ana_audio_pin_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)  * si476x_cmd_intb_pin_cfg - send 'INTB_PIN_CFG' command to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678)  * @core: - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)  * @intb: - INTB pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)  *      SI476X_INTB_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)  *      SI476X_INTB_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)  *                             enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  *      SI476X_INTB_DAUDIO   - set pin to be a part of digital
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)  *                             audio interface in slave mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685)  *      SI476X_INTB_IRQ      - set pin to be an interrupt request line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)  * @a1: - A1 pin function configuration:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687)  *      SI476X_A1_NOOP     - do not modify the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688)  *      SI476X_A1_TRISTATE - put the pin in tristate condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)  *                           enable 1MOhm pulldown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)  *      SI476X_A1_IRQ      - set pin to be an interrupt request line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) static int si476x_core_cmd_intb_pin_cfg_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 					    enum si476x_intb_config intb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 					    enum si476x_a1_config a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	u8       resp[CMD_INTB_PIN_CFG_A10_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	const u8 args[CMD_INTB_PIN_CFG_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		PIN_CFG_BYTE(intb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		PIN_CFG_BYTE(a1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	return si476x_core_send_command(core, CMD_INTB_PIN_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) static int si476x_core_cmd_intb_pin_cfg_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 					    enum si476x_intb_config intb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 					    enum si476x_a1_config a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	u8       resp[CMD_INTB_PIN_CFG_A20_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	const u8 args[CMD_INTB_PIN_CFG_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		PIN_CFG_BYTE(intb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 		PIN_CFG_BYTE(a1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	return si476x_core_send_command(core, CMD_INTB_PIN_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729)  * si476x_cmd_am_rsq_status - send 'AM_RSQ_STATUS' command to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730)  * device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731)  * @core:  - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732)  * @rsqargs: - pointer to a structure containing a group of sub-args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733)  *             relevant to sending the RSQ status command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734)  * @report: - all signal quality information retured by the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735)  *           (if NULL then the output of the command is ignored)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) int si476x_core_cmd_am_rsq_status(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 				  struct si476x_rsq_status_args *rsqargs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 				  struct si476x_rsq_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	u8       resp[CMD_AM_RSQ_STATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	const u8 args[CMD_AM_RSQ_STATUS_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		rsqargs->rsqack << 3 | rsqargs->attune << 2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		rsqargs->cancel << 1 | rsqargs->stcack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	err = si476x_core_send_command(core, CMD_AM_RSQ_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	 * Besides getting received signal quality information this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	 * command can be used to just acknowledge different interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	 * flags in those cases it is useless to copy and parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	 * received data so user can pass NULL, and thus avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	 * unnecessary copying.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	if (!report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	report->snrhint		= 0x08 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	report->snrlint		= 0x04 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	report->rssihint	= 0x02 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	report->rssilint	= 0x01 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	report->bltf		= 0x80 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	report->snr_ready	= 0x20 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	report->rssiready	= 0x08 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	report->afcrl		= 0x02 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	report->valid		= 0x01 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	report->readfreq	= get_unaligned_be16(resp + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	report->freqoff		= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	report->rssi		= resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	report->snr		= resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	report->lassi		= resp[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	report->hassi		= resp[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	report->mult		= resp[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	report->dev		= resp[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) EXPORT_SYMBOL_GPL(si476x_core_cmd_am_rsq_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) int si476x_core_cmd_fm_acf_status(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 			     struct si476x_acf_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	u8       resp[CMD_FM_ACF_STATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	const u8 args[CMD_FM_ACF_STATUS_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	if (!report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	err = si476x_core_send_command(core, CMD_FM_ACF_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	report->blend_int	= resp[1] & SI476X_ACF_BLEND_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	report->hblend_int	= resp[1] & SI476X_ACF_HIBLEND_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	report->hicut_int	= resp[1] & SI476X_ACF_HICUT_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	report->chbw_int	= resp[1] & SI476X_ACF_CHBW_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	report->softmute_int	= resp[1] & SI476X_ACF_SOFTMUTE_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	report->smute		= resp[2] & SI476X_ACF_SMUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	report->smattn		= resp[3] & SI476X_ACF_SMATTN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	report->chbw		= resp[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	report->hicut		= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	report->hiblend		= resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	report->pilot		= resp[7] & SI476X_ACF_PILOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	report->stblend		= resp[7] & SI476X_ACF_STBLEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_acf_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) int si476x_core_cmd_am_acf_status(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 				  struct si476x_acf_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	u8       resp[CMD_AM_ACF_STATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	const u8 args[CMD_AM_ACF_STATUS_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		0x0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	if (!report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	err = si476x_core_send_command(core, CMD_AM_ACF_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	report->blend_int	= resp[1] & SI476X_ACF_BLEND_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	report->hblend_int	= resp[1] & SI476X_ACF_HIBLEND_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	report->hicut_int	= resp[1] & SI476X_ACF_HICUT_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	report->chbw_int	= resp[1] & SI476X_ACF_CHBW_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	report->softmute_int	= resp[1] & SI476X_ACF_SOFTMUTE_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	report->smute		= resp[2] & SI476X_ACF_SMUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	report->smattn		= resp[3] & SI476X_ACF_SMATTN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	report->chbw		= resp[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	report->hicut		= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) EXPORT_SYMBOL_GPL(si476x_core_cmd_am_acf_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859)  * si476x_cmd_fm_seek_start - send 'FM_SEEK_START' command to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860)  * device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861)  * @core:  - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862)  * @seekup: - if set the direction of the search is 'up'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863)  * @wrap:   - if set seek wraps when hitting band limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865)  * This function begins search for a valid station. The station is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866)  * considered valid when 'FM_VALID_SNR_THRESHOLD' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867)  * 'FM_VALID_RSSI_THRESHOLD' and 'FM_VALID_MAX_TUNE_ERROR' criteria
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868)  * are met.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) } *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) int si476x_core_cmd_fm_seek_start(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 				  bool seekup, bool wrap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	u8       resp[CMD_FM_SEEK_START_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	const u8 args[CMD_FM_SEEK_START_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		seekup << 3 | wrap << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	return si476x_cmd_tune_seek_freq(core, CMD_FM_SEEK_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 					 args, sizeof(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 					 resp, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_seek_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887)  * si476x_cmd_fm_rds_status - send 'FM_RDS_STATUS' command to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888)  * device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889)  * @core: - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890)  * @status_only: - if set the data is not removed from RDSFIFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891)  *                RDSFIFOUSED is not decremented and data in all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892)  *                rest RDS data contains the last valid info received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893)  * @mtfifo: if set the command clears RDS receive FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894)  * @intack: if set the command clards the RDSINT bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895)  * @report: - all signal quality information retured by the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896)  *           (if NULL then the output of the command is ignored)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) int si476x_core_cmd_fm_rds_status(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 				  bool status_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 				  bool mtfifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 				  bool intack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 				  struct si476x_rds_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	u8       resp[CMD_FM_RDS_STATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	const u8 args[CMD_FM_RDS_STATUS_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		status_only << 2 | mtfifo << 1 | intack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	err = si476x_core_send_command(core, CMD_FM_RDS_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	 * Besides getting RDS status information this command can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	 * used to just acknowledge different interrupt flags in those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 	 * cases it is useless to copy and parse received data so user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	 * can pass NULL, and thus avoid unnecessary copying.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	if (err < 0 || report == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	report->rdstpptyint	= 0x10 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	report->rdspiint	= 0x08 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	report->rdssyncint	= 0x02 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	report->rdsfifoint	= 0x01 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	report->tpptyvalid	= 0x10 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	report->pivalid		= 0x08 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	report->rdssync		= 0x02 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	report->rdsfifolost	= 0x01 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	report->tp		= 0x20 & resp[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	report->pty		= 0x1f & resp[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	report->pi		= get_unaligned_be16(resp + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	report->rdsfifoused	= resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	report->ble[V4L2_RDS_BLOCK_A]	= 0xc0 & resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	report->ble[V4L2_RDS_BLOCK_B]	= 0x30 & resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	report->ble[V4L2_RDS_BLOCK_C]	= 0x0c & resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	report->ble[V4L2_RDS_BLOCK_D]	= 0x03 & resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	report->rds[V4L2_RDS_BLOCK_A].block = V4L2_RDS_BLOCK_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	report->rds[V4L2_RDS_BLOCK_A].msb = resp[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	report->rds[V4L2_RDS_BLOCK_A].lsb = resp[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	report->rds[V4L2_RDS_BLOCK_B].block = V4L2_RDS_BLOCK_B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	report->rds[V4L2_RDS_BLOCK_B].msb = resp[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	report->rds[V4L2_RDS_BLOCK_B].lsb = resp[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	report->rds[V4L2_RDS_BLOCK_C].block = V4L2_RDS_BLOCK_C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	report->rds[V4L2_RDS_BLOCK_C].msb = resp[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	report->rds[V4L2_RDS_BLOCK_C].lsb = resp[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	report->rds[V4L2_RDS_BLOCK_D].block = V4L2_RDS_BLOCK_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	report->rds[V4L2_RDS_BLOCK_D].msb = resp[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	report->rds[V4L2_RDS_BLOCK_D].lsb = resp[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_rds_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) int si476x_core_cmd_fm_rds_blockcount(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 				bool clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 				struct si476x_rds_blockcount_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	u8       resp[CMD_FM_RDS_BLOCKCOUNT_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	const u8 args[CMD_FM_RDS_BLOCKCOUNT_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	if (!report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	err = si476x_core_send_command(core, CMD_FM_RDS_BLOCKCOUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		report->expected	= get_unaligned_be16(resp + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		report->received	= get_unaligned_be16(resp + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		report->uncorrectable	= get_unaligned_be16(resp + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_rds_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) int si476x_core_cmd_fm_phase_diversity(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 				       enum si476x_phase_diversity_mode mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	u8       resp[CMD_FM_PHASE_DIVERSITY_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	const u8 args[CMD_FM_PHASE_DIVERSITY_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		mode & 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	return si476x_core_send_command(core, CMD_FM_PHASE_DIVERSITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_diversity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)  * si476x_core_cmd_fm_phase_div_status() - get the phase diversity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)  * status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)  * @core: si476x device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)  * NOTE caller must hold core lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)  * Function returns the value of the status bit in case of success and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)  * negative error code in case of failre.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) int si476x_core_cmd_fm_phase_div_status(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	u8 resp[CMD_FM_PHASE_DIV_STATUS_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	err = si476x_core_send_command(core, CMD_FM_PHASE_DIV_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 				       NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	return (err < 0) ? err : resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_phase_div_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)  * si476x_cmd_am_seek_start - send 'FM_SEEK_START' command to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)  * device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)  * @core:  - device to send the command to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)  * @seekup: - if set the direction of the search is 'up'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)  * @wrap:   - if set seek wraps when hitting band limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)  * This function begins search for a valid station. The station is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)  * considered valid when 'FM_VALID_SNR_THRESHOLD' and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)  * 'FM_VALID_RSSI_THRESHOLD' and 'FM_VALID_MAX_TUNE_ERROR' criteria
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)  * are met.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)  * Function returns 0 on success and negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) int si476x_core_cmd_am_seek_start(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 				  bool seekup, bool wrap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	u8       resp[CMD_AM_SEEK_START_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	const u8 args[CMD_AM_SEEK_START_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		seekup << 3 | wrap << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	return si476x_cmd_tune_seek_freq(core,  CMD_AM_SEEK_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 					 args, sizeof(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 					 resp, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) EXPORT_SYMBOL_GPL(si476x_core_cmd_am_seek_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int si476x_core_cmd_power_up_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 					struct si476x_power_up_args *puargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	u8       resp[CMD_POWER_UP_A10_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	const bool intsel = (core->pinmux.a1 == SI476X_A1_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	const bool ctsen  = (core->client->irq != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	const u8 args[CMD_POWER_UP_A10_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		0xF7,		/* Reserved, always 0xF7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 		0x3F & puargs->xcload,	/* First two bits are reserved to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 				 * zeros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		ctsen << 7 | intsel << 6 | 0x07, /* Last five bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 						   * are reserved to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 						   * be written as 0x7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 		puargs->func << 4 | puargs->freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 		0x11,		/* Reserved, always 0x11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	return si476x_core_send_command(core, CMD_POWER_UP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 					SI476X_TIMEOUT_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static int si476x_core_cmd_power_up_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 				 struct si476x_power_up_args *puargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	u8       resp[CMD_POWER_UP_A20_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	const bool intsel = (core->pinmux.a1 == SI476X_A1_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	const bool ctsen  = (core->client->irq != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	const u8 args[CMD_POWER_UP_A20_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 		puargs->ibias6x << 7 | puargs->xstart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		0x3F & puargs->xcload,	/* First two bits are reserved to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 					 * zeros */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		ctsen << 7 | intsel << 6 | puargs->fastboot << 5 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		puargs->xbiashc << 3 | puargs->xbias,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 		puargs->func << 4 | puargs->freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 		0x10 | puargs->xmode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	return si476x_core_send_command(core, CMD_POWER_UP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 					SI476X_TIMEOUT_POWER_UP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int si476x_core_cmd_power_down_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 					  struct si476x_power_down_args *pdargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 	u8 resp[CMD_POWER_DOWN_A10_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	return si476x_core_send_command(core, CMD_POWER_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 					NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) static int si476x_core_cmd_power_down_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 					  struct si476x_power_down_args *pdargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	u8 resp[CMD_POWER_DOWN_A20_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	const u8 args[CMD_POWER_DOWN_A20_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		pdargs->xosc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	return si476x_core_send_command(core, CMD_POWER_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 					args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 					resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 					SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static int si476x_core_cmd_am_tune_freq_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 					struct si476x_tune_freq_args *tuneargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	const int am_freq = tuneargs->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	u8       resp[CMD_AM_TUNE_FREQ_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	const u8 args[CMD_AM_TUNE_FREQ_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 		(tuneargs->hd << 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		msb(am_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		lsb(am_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	return si476x_cmd_tune_seek_freq(core, CMD_AM_TUNE_FREQ, args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 					 sizeof(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 					 resp, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) static int si476x_core_cmd_am_tune_freq_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 					struct si476x_tune_freq_args *tuneargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	const int am_freq = tuneargs->freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	u8       resp[CMD_AM_TUNE_FREQ_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	const u8 args[CMD_AM_TUNE_FREQ_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 		(tuneargs->zifsr << 6) | (tuneargs->injside & 0x03),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		msb(am_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 		lsb(am_freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	return si476x_cmd_tune_seek_freq(core, CMD_AM_TUNE_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 					 args, sizeof(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 					 resp, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) static int si476x_core_cmd_fm_rsq_status_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 					struct si476x_rsq_status_args *rsqargs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 					struct si476x_rsq_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	u8       resp[CMD_FM_RSQ_STATUS_A10_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	const u8 args[CMD_FM_RSQ_STATUS_A10_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		rsqargs->rsqack << 3 | rsqargs->attune << 2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		rsqargs->cancel << 1 | rsqargs->stcack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	err = si476x_core_send_command(core, CMD_FM_RSQ_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	 * Besides getting received signal quality information this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	 * command can be used to just acknowledge different interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	 * flags in those cases it is useless to copy and parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	 * received data so user can pass NULL, and thus avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	 * unnecessary copying.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	if (err < 0 || report == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	report->multhint	= 0x80 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	report->multlint	= 0x40 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	report->snrhint		= 0x08 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	report->snrlint		= 0x04 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	report->rssihint	= 0x02 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	report->rssilint	= 0x01 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	report->bltf		= 0x80 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	report->snr_ready	= 0x20 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	report->rssiready	= 0x08 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	report->afcrl		= 0x02 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 	report->valid		= 0x01 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 	report->readfreq	= get_unaligned_be16(resp + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	report->freqoff		= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 	report->rssi		= resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	report->snr		= resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	report->lassi		= resp[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	report->hassi		= resp[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	report->mult		= resp[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	report->dev		= resp[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	report->readantcap	= get_unaligned_be16(resp + 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 	report->assi		= resp[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	report->usn		= resp[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 				     struct si476x_rsq_status_args *rsqargs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 				     struct si476x_rsq_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	u8       resp[CMD_FM_RSQ_STATUS_A10_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	const u8 args[CMD_FM_RSQ_STATUS_A30_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		rsqargs->primary << 4 | rsqargs->rsqack << 3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		rsqargs->attune  << 2 | rsqargs->cancel << 1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		rsqargs->stcack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	err = si476x_core_send_command(core, CMD_FM_RSQ_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	 * Besides getting received signal quality information this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	 * command can be used to just acknowledge different interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	 * flags in those cases it is useless to copy and parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	 * received data so user can pass NULL, and thus avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	 * unnecessary copying.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	if (err < 0 || report == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	report->multhint	= 0x80 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	report->multlint	= 0x40 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	report->snrhint		= 0x08 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	report->snrlint		= 0x04 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	report->rssihint	= 0x02 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	report->rssilint	= 0x01 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	report->bltf		= 0x80 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	report->snr_ready	= 0x20 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	report->rssiready	= 0x08 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	report->afcrl		= 0x02 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 	report->valid		= 0x01 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	report->readfreq	= get_unaligned_be16(resp + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	report->freqoff		= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 	report->rssi		= resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 	report->snr		= resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 	report->lassi		= resp[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	report->hassi		= resp[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	report->mult		= resp[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	report->dev		= resp[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	report->readantcap	= get_unaligned_be16(resp + 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	report->assi		= resp[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	report->usn		= resp[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) static int si476x_core_cmd_fm_rsq_status_a30(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 					struct si476x_rsq_status_args *rsqargs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 					struct si476x_rsq_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	u8       resp[CMD_FM_RSQ_STATUS_A30_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	const u8 args[CMD_FM_RSQ_STATUS_A30_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 		rsqargs->primary << 4 | rsqargs->rsqack << 3 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 		rsqargs->attune << 2 | rsqargs->cancel << 1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 		rsqargs->stcack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	err = si476x_core_send_command(core, CMD_FM_RSQ_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 				       args, ARRAY_SIZE(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	 * Besides getting received signal quality information this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	 * command can be used to just acknowledge different interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	 * flags in those cases it is useless to copy and parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	 * received data so user can pass NULL, and thus avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	 * unnecessary copying.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	if (err < 0 || report == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	report->multhint	= 0x80 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	report->multlint	= 0x40 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	report->snrhint		= 0x08 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	report->snrlint		= 0x04 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 	report->rssihint	= 0x02 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 	report->rssilint	= 0x01 & resp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	report->bltf		= 0x80 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	report->snr_ready	= 0x20 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	report->rssiready	= 0x08 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 	report->injside         = 0x04 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	report->afcrl		= 0x02 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	report->valid		= 0x01 & resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	report->readfreq	= get_unaligned_be16(resp + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 	report->freqoff		= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	report->rssi		= resp[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	report->snr		= resp[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 	report->issi		= resp[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 	report->lassi		= resp[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	report->hassi		= resp[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	report->mult		= resp[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	report->dev		= resp[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	report->readantcap	= get_unaligned_be16(resp + 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	report->assi		= resp[15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	report->usn		= resp[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	report->pilotdev	= resp[17];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	report->rdsdev		= resp[18];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	report->assidev		= resp[19];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	report->strongdev	= resp[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	report->rdspi		= get_unaligned_be16(resp + 21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) static int si476x_core_cmd_fm_tune_freq_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 					struct si476x_tune_freq_args *tuneargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 	u8       resp[CMD_FM_TUNE_FREQ_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	const u8 args[CMD_FM_TUNE_FREQ_A10_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		(tuneargs->hd << 6) | (tuneargs->tunemode << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		| (tuneargs->smoothmetrics << 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 		msb(tuneargs->freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 		lsb(tuneargs->freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 		msb(tuneargs->antcap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 		lsb(tuneargs->antcap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	return si476x_cmd_tune_seek_freq(core, CMD_FM_TUNE_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 					 args, sizeof(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 					 resp, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) static int si476x_core_cmd_fm_tune_freq_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 					struct si476x_tune_freq_args *tuneargs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 	u8       resp[CMD_FM_TUNE_FREQ_NRESP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	const u8 args[CMD_FM_TUNE_FREQ_A20_NARGS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 		(tuneargs->hd << 6) | (tuneargs->tunemode << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 		|  (tuneargs->smoothmetrics << 2) | (tuneargs->injside),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 		msb(tuneargs->freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 		lsb(tuneargs->freq),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	return si476x_cmd_tune_seek_freq(core, CMD_FM_TUNE_FREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 					 args, sizeof(args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 					 resp, sizeof(resp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) static int si476x_core_cmd_agc_status_a20(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 					struct si476x_agc_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	u8 resp[CMD_AGC_STATUS_NRESP_A20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	if (!report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 	err = si476x_core_send_command(core, CMD_AGC_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 				       NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	report->mxhi		= resp[1] & SI476X_AGC_MXHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	report->mxlo		= resp[1] & SI476X_AGC_MXLO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	report->lnahi		= resp[1] & SI476X_AGC_LNAHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	report->lnalo		= resp[1] & SI476X_AGC_LNALO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	report->fmagc1		= resp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 	report->fmagc2		= resp[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	report->pgagain		= resp[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	report->fmwblang	= resp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) static int si476x_core_cmd_agc_status_a10(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 					struct si476x_agc_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 	u8 resp[CMD_AGC_STATUS_NRESP_A10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	if (!report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 	err = si476x_core_send_command(core, CMD_AGC_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 				       NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 				       resp, ARRAY_SIZE(resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 				       SI476X_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 	report->mxhi	= resp[1] & SI476X_AGC_MXHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	report->mxlo	= resp[1] & SI476X_AGC_MXLO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	report->lnahi	= resp[1] & SI476X_AGC_LNAHI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	report->lnalo	= resp[1] & SI476X_AGC_LNALO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) typedef int (*tune_freq_func_t) (struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 				 struct si476x_tune_freq_args *tuneargs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 	int (*power_up)(struct si476x_core *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 			struct si476x_power_up_args *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 	int (*power_down)(struct si476x_core *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 			  struct si476x_power_down_args *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 	tune_freq_func_t fm_tune_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 	tune_freq_func_t am_tune_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 	int (*fm_rsq_status)(struct si476x_core *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 			     struct si476x_rsq_status_args *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 			     struct si476x_rsq_status_report *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 	int (*agc_status)(struct si476x_core *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 			  struct si476x_agc_status_report *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 	int (*intb_pin_cfg)(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 			    enum si476x_intb_config intb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 			    enum si476x_a1_config a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) } si476x_cmds_vtable[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 	[SI476X_REVISION_A10] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 		.power_up	= si476x_core_cmd_power_up_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		.power_down	= si476x_core_cmd_power_down_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 		.fm_tune_freq	= si476x_core_cmd_fm_tune_freq_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		.am_tune_freq	= si476x_core_cmd_am_tune_freq_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 		.fm_rsq_status	= si476x_core_cmd_fm_rsq_status_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 		.agc_status	= si476x_core_cmd_agc_status_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 		.intb_pin_cfg   = si476x_core_cmd_intb_pin_cfg_a10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	[SI476X_REVISION_A20] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		.power_up	= si476x_core_cmd_power_up_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 		.power_down	= si476x_core_cmd_power_down_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 		.fm_tune_freq	= si476x_core_cmd_fm_tune_freq_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 		.am_tune_freq	= si476x_core_cmd_am_tune_freq_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 		.fm_rsq_status	= si476x_core_cmd_fm_rsq_status_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 		.agc_status	= si476x_core_cmd_agc_status_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 		.intb_pin_cfg   = si476x_core_cmd_intb_pin_cfg_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	[SI476X_REVISION_A30] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 		.power_up	= si476x_core_cmd_power_up_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		.power_down	= si476x_core_cmd_power_down_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 		.fm_tune_freq	= si476x_core_cmd_fm_tune_freq_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 		.am_tune_freq	= si476x_core_cmd_am_tune_freq_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		.fm_rsq_status	= si476x_core_cmd_fm_rsq_status_a30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 		.agc_status	= si476x_core_cmd_agc_status_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 		.intb_pin_cfg   = si476x_core_cmd_intb_pin_cfg_a20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) int si476x_core_cmd_power_up(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 			     struct si476x_power_up_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 	return si476x_cmds_vtable[core->revision].power_up(core, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) EXPORT_SYMBOL_GPL(si476x_core_cmd_power_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) int si476x_core_cmd_power_down(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 			       struct si476x_power_down_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	return si476x_cmds_vtable[core->revision].power_down(core, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) EXPORT_SYMBOL_GPL(si476x_core_cmd_power_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) int si476x_core_cmd_fm_tune_freq(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 				 struct si476x_tune_freq_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 	return si476x_cmds_vtable[core->revision].fm_tune_freq(core, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_tune_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) int si476x_core_cmd_am_tune_freq(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 				 struct si476x_tune_freq_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	return si476x_cmds_vtable[core->revision].am_tune_freq(core, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) EXPORT_SYMBOL_GPL(si476x_core_cmd_am_tune_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) int si476x_core_cmd_fm_rsq_status(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 				  struct si476x_rsq_status_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 				  struct si476x_rsq_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 	return si476x_cmds_vtable[core->revision].fm_rsq_status(core, args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 								report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) EXPORT_SYMBOL_GPL(si476x_core_cmd_fm_rsq_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) int si476x_core_cmd_agc_status(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 				  struct si476x_agc_status_report *report)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 	return si476x_cmds_vtable[core->revision].agc_status(core, report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) EXPORT_SYMBOL_GPL(si476x_core_cmd_agc_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) int si476x_core_cmd_intb_pin_cfg(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 			    enum si476x_intb_config intb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 			    enum si476x_a1_config a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	BUG_ON(core->revision > SI476X_REVISION_A30 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 	       core->revision == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 	return si476x_cmds_vtable[core->revision].intb_pin_cfg(core, intb, a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) EXPORT_SYMBOL_GPL(si476x_core_cmd_intb_pin_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) MODULE_DESCRIPTION("API for command exchange for si476x");