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-i2c.c -- Core device driver for si476x MFD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * device
^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) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/err.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) #define SI476X_MAX_IO_ERRORS		10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define SI476X_DRIVER_RDS_FIFO_DEPTH	128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * si476x_core_config_pinmux() - pin function configuration function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Configure the functions of the pins of the radio chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * The function returns zero in case of succes or negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static int si476x_core_config_pinmux(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	dev_dbg(&core->client->dev, "Configuring pinmux\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	err = si476x_core_cmd_dig_audio_pin_cfg(core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 						core->pinmux.dclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 						core->pinmux.dfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 						core->pinmux.dout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 						core->pinmux.xout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			"Failed to configure digital audio pins(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	err = si476x_core_cmd_zif_pin_cfg(core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 					  core->pinmux.iqclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 					  core->pinmux.iqfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 					  core->pinmux.iout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 					  core->pinmux.qout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			"Failed to configure ZIF pins(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	err = si476x_core_cmd_ic_link_gpo_ctl_pin_cfg(core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 						      core->pinmux.icin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 						      core->pinmux.icip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 						      core->pinmux.icon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 						      core->pinmux.icop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			"Failed to configure IC-Link/GPO pins(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	err = si476x_core_cmd_ana_audio_pin_cfg(core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 						core->pinmux.lrout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			"Failed to configure analog audio pins(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	err = si476x_core_cmd_intb_pin_cfg(core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 					   core->pinmux.intb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 					   core->pinmux.a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			"Failed to configure interrupt pins(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		return err;
^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) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) static inline void si476x_core_schedule_polling_work(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	schedule_delayed_work(&core->status_monitor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 			      usecs_to_jiffies(SI476X_STATUS_POLL_US));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  * si476x_core_start() - early chip startup function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * @soft: When set, this flag forces "soft" startup, where "soft"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * power down is the one done by sending appropriate command instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * of using reset pin of the tuner
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * Perform required startup sequence to correctly power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * up the chip and perform initial configuration. It does the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * following sequence of actions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *       1. Claims and enables the power supplies VD and VIO1 required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  *          for I2C interface of the chip operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  *       2. Waits for 100us, pulls the reset line up, enables irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  *          waits for another 100us as it is specified by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  *          datasheet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  *       3. Sends 'POWER_UP' command to the device with all provided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  *          information about power-up parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  *       4. Configures, pin multiplexor, disables digital audio and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  *          configures interrupt sources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * The function returns zero in case of succes or negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int si476x_core_start(struct si476x_core *core, bool soft)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	struct i2c_client *client = core->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	if (!soft) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		if (gpio_is_valid(core->gpio_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			gpio_set_value_cansleep(core->gpio_reset, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			enable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		if (!client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			atomic_set(&core->is_alive, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			si476x_core_schedule_polling_work(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			enable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			atomic_set(&core->is_alive, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			si476x_core_schedule_polling_work(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	err = si476x_core_cmd_power_up(core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 				       &core->power_up_parameters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			"Power up failure(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		goto disable_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		atomic_set(&core->is_alive, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	err = si476x_core_config_pinmux(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			"Failed to configure pinmux(err = %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		goto disable_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		err = regmap_write(core->regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 				   SI476X_PROP_INT_CTL_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				   SI476X_RDSIEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 				   SI476X_STCIEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 				   SI476X_CTSIEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 				"Failed to configure interrupt sources"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 				"(err = %d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			goto disable_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) disable_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (err == -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		atomic_set(&core->is_alive, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		disable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		cancel_delayed_work_sync(&core->status_monitor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	if (gpio_is_valid(core->gpio_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		gpio_set_value_cansleep(core->gpio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) EXPORT_SYMBOL_GPL(si476x_core_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  * si476x_core_stop() - chip power-down function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  * @soft: When set, function sends a POWER_DOWN command instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  * bringing reset line low
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  * Power down the chip by performing following actions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * 1. Disable IRQ or stop the polling worker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * 2. Send the POWER_DOWN command if the power down is soft or bring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *    reset line low if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * The function returns zero in case of succes or negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int si476x_core_stop(struct si476x_core *core, bool soft)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	atomic_set(&core->is_alive, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (soft) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		/* TODO: This probably shoud be a configurable option,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		 * so it is possible to have the chips keep their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		 * oscillators running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		struct si476x_power_down_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			.xosc = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		err = si476x_core_cmd_power_down(core, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	/* We couldn't disable those before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	 * 'si476x_core_cmd_power_down' since we expect to get CTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	 * interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (core->client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		disable_irq(core->client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		cancel_delayed_work_sync(&core->status_monitor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	if (!soft) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		if (gpio_is_valid(core->gpio_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			gpio_set_value_cansleep(core->gpio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) EXPORT_SYMBOL_GPL(si476x_core_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * si476x_core_set_power_state() - set the level at which the power is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  * supplied for the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * @next_state: enum si476x_power_state describing power state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  *              switch to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)  * Switch on all the required power supplies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)  * This function returns 0 in case of suvccess and negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)  * otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int si476x_core_set_power_state(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 				enum si476x_power_state next_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	   It is not clear form the datasheet if it is possible to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	   work with device if not all power domains are operational.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	   So for now the power-up policy is "power-up all the things!"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (core->power_state == SI476X_POWER_INCONSISTENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			"The device in inconsistent power state\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	if (next_state != core->power_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		switch (next_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		case SI476X_POWER_UP_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 			err = regulator_bulk_enable(ARRAY_SIZE(core->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 						    core->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 				core->power_state = SI476X_POWER_INCONSISTENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			 * Startup timing diagram recommends to have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			 * 100 us delay between enabling of the power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			 * supplies and turning the tuner on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 			udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			err = si476x_core_start(core, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 				goto disable_regulators;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			core->power_state = next_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		case SI476X_POWER_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			core->power_state = next_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			err = si476x_core_stop(core, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 				core->power_state = SI476X_POWER_INCONSISTENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) disable_regulators:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			err = regulator_bulk_disable(ARRAY_SIZE(core->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 						     core->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 				core->power_state = SI476X_POWER_INCONSISTENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) EXPORT_SYMBOL_GPL(si476x_core_set_power_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)  * si476x_core_report_drainer_stop() - mark the completion of the RDS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)  * buffer drain porcess by the worker.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static inline void si476x_core_report_drainer_stop(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	mutex_lock(&core->rds_drainer_status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	core->rds_drainer_is_working = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	mutex_unlock(&core->rds_drainer_status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  * si476x_core_start_rds_drainer_once() - start RDS drainer worker if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  * ther is none working, do nothing otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  * @core: Datastructure corresponding to the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static inline void si476x_core_start_rds_drainer_once(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	mutex_lock(&core->rds_drainer_status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	if (!core->rds_drainer_is_working) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		core->rds_drainer_is_working = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		schedule_work(&core->rds_fifo_drainer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	mutex_unlock(&core->rds_drainer_status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)  * si476x_drain_rds_fifo() - RDS buffer drainer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)  * @work: struct work_struct being ppassed to the function by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  * kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)  * Drain the contents of the RDS FIFO of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static void si476x_core_drain_rds_fifo(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	struct si476x_core *core = container_of(work, struct si476x_core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 						rds_fifo_drainer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	struct si476x_rds_status_report report;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	si476x_core_lock(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	err = si476x_core_cmd_fm_rds_status(core, true, false, false, &report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		int i = report.rdsfifoused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		dev_dbg(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			"%d elements in RDS FIFO. Draining.\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		for (; i > 0; --i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 			err = si476x_core_cmd_fm_rds_status(core, false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 							    (i == 1), &report);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 				goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 			kfifo_in(&core->rds_fifo, report.rds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 				 sizeof(report.rds));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 			dev_dbg(&core->client->dev, "RDS data:\n %*ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 				(int)sizeof(report.rds), report.rds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		dev_dbg(&core->client->dev, "Drrrrained!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		wake_up_interruptible(&core->rds_read_queue);
^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) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	si476x_core_unlock(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	si476x_core_report_drainer_stop(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  * si476x_core_pronounce_dead()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)  * Mark the device as being dead and wake up all potentially waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)  * threads of execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void si476x_core_pronounce_dead(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	dev_info(&core->client->dev, "Core device is dead.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	atomic_set(&core->is_alive, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	/* Wake up al possible waiting processes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	wake_up_interruptible(&core->rds_read_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	atomic_set(&core->cts, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	wake_up(&core->command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	atomic_set(&core->stc, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	wake_up(&core->tuning);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)  * si476x_core_i2c_xfer()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)  * @type: Transfer type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)  * @buf: Transfer buffer for/with data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)  * @count: Transfer buffer size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)  * Perfrom and I2C transfer(either read or write) and keep a counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)  * of I/O errors. If the error counter rises above the threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  * pronounce device dead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  * The function returns zero on succes or negative error code on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  * failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int si476x_core_i2c_xfer(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		    enum si476x_i2c_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		    char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	static int io_errors_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	if (type == SI476X_I2C_SEND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		err = i2c_master_send(core->client, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		err = i2c_master_recv(core->client, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		if (io_errors_count++ > SI476X_MAX_IO_ERRORS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			si476x_core_pronounce_dead(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		io_errors_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) EXPORT_SYMBOL_GPL(si476x_core_i2c_xfer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)  * si476x_get_status()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)  * Get the status byte of the core device by berforming one byte I2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)  * read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)  * The function returns a status value or a negative error code on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)  * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int si476x_core_get_status(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	u8 response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	int err = si476x_core_i2c_xfer(core, SI476X_I2C_RECV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 				  &response, sizeof(response));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	return (err < 0) ? err : response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)  * si476x_get_and_signal_status() - IRQ dispatcher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)  * Dispatch the arrived interrupt request based on the value of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)  * status byte reported by the tuner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static void si476x_core_get_and_signal_status(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	int status = si476x_core_get_status(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		dev_err(&core->client->dev, "Failed to get status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	if (status & SI476X_CTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		/* Unfortunately completions could not be used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		 * signalling CTS since this flag cannot be cleared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		 * in status byte, and therefore once it becomes true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		 * multiple calls to 'complete' would cause the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		 * commands following the current one to be completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		 * before they actually are */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		dev_dbg(&core->client->dev, "[interrupt] CTSINT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		atomic_set(&core->cts, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		wake_up(&core->command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	if (status & SI476X_FM_RDS_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		dev_dbg(&core->client->dev, "[interrupt] RDSINT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		si476x_core_start_rds_drainer_once(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	if (status & SI476X_STC_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		dev_dbg(&core->client->dev, "[interrupt] STCINT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		atomic_set(&core->stc, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		wake_up(&core->tuning);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) static void si476x_core_poll_loop(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	struct si476x_core *core = SI476X_WORK_TO_CORE(work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	si476x_core_get_and_signal_status(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	if (atomic_read(&core->is_alive))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		si476x_core_schedule_polling_work(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static irqreturn_t si476x_core_interrupt(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	struct si476x_core *core = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	si476x_core_get_and_signal_status(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	return IRQ_HANDLED;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  * si476x_firmware_version_to_revision()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)  * @func: Selects the boot function of the device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)  *         *_BOOTLOADER  - Boot loader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)  *         *_FM_RECEIVER - FM receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)  *         *_AM_RECEIVER - AM receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)  *         *_WB_RECEIVER - Weatherband receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)  * @major:  Firmware major number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)  * @minor1: Firmware first minor number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)  * @minor2: Firmware second minor number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)  * Convert a chip's firmware version number into an offset that later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)  * will be used to as offset in "vtable" of tuner functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)  * This function returns a positive offset in case of success and a -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)  * in case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static int si476x_core_fwver_to_revision(struct si476x_core *core,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 					 int func, int major,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 					 int minor1, int minor2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	case SI476X_FUNC_FM_RECEIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		switch (major) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 			return SI476X_REVISION_A10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 			return SI476X_REVISION_A20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 			return SI476X_REVISION_A30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 			goto unknown_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	case SI476X_FUNC_AM_RECEIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		switch (major) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 		case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 			return SI476X_REVISION_A10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 			return SI476X_REVISION_A20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 			return SI476X_REVISION_A30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 			goto unknown_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	case SI476X_FUNC_WB_RECEIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		switch (major) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 			return SI476X_REVISION_A10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			return SI476X_REVISION_A20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 			return SI476X_REVISION_A30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 			goto unknown_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	case SI476X_FUNC_BOOTLOADER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	default:		/* FALLTHROUGH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) unknown_revision:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	dev_err(&core->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 		"Unsupported version of the firmware: %d.%d.%d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		"reverting to A10 compatible functions\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 		major, minor1, minor2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	return SI476X_REVISION_A10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)  * si476x_get_revision_info()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)  * @core: Core device structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)  * Get the firmware version number of the device. It is done in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)  * following three steps:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)  *    1. Power-up the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)  *    2. Send the 'FUNC_INFO' command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)  *    3. Powering the device down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)  * The function return zero on success and a negative error code on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)  * failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static int si476x_core_get_revision_info(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	struct si476x_func_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	si476x_core_lock(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	rval = si476x_core_set_power_state(core, SI476X_POWER_UP_FULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	rval = si476x_core_cmd_func_info(core, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	if (rval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		goto power_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	core->revision = si476x_core_fwver_to_revision(core, info.func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 						       info.firmware.major,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 						       info.firmware.minor[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 						       info.firmware.minor[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) power_down:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	si476x_core_set_power_state(core, SI476X_POWER_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	si476x_core_unlock(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) bool si476x_core_has_am(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	return core->chip_id == SI476X_CHIP_SI4761 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		core->chip_id == SI476X_CHIP_SI4764;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) EXPORT_SYMBOL_GPL(si476x_core_has_am);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) bool si476x_core_has_diversity(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	return core->chip_id == SI476X_CHIP_SI4764;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) EXPORT_SYMBOL_GPL(si476x_core_has_diversity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) bool si476x_core_is_a_secondary_tuner(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	return si476x_core_has_diversity(core) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 		(core->diversity_mode == SI476X_PHDIV_SECONDARY_ANTENNA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		 core->diversity_mode == SI476X_PHDIV_SECONDARY_COMBINING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) EXPORT_SYMBOL_GPL(si476x_core_is_a_secondary_tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) bool si476x_core_is_a_primary_tuner(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	return si476x_core_has_diversity(core) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		(core->diversity_mode == SI476X_PHDIV_PRIMARY_ANTENNA ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		 core->diversity_mode == SI476X_PHDIV_PRIMARY_COMBINING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) EXPORT_SYMBOL_GPL(si476x_core_is_a_primary_tuner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) bool si476x_core_is_in_am_receiver_mode(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	return si476x_core_has_am(core) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 		(core->power_up_parameters.func == SI476X_FUNC_AM_RECEIVER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) EXPORT_SYMBOL_GPL(si476x_core_is_in_am_receiver_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) bool si476x_core_is_powered_up(struct si476x_core *core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	return core->power_state == SI476X_POWER_UP_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) EXPORT_SYMBOL_GPL(si476x_core_is_powered_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static int si476x_core_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 			     const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	struct si476x_core          *core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	struct si476x_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	struct mfd_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	int              cell_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	if (!core)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	core->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	core->regmap = devm_regmap_init_si476x(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	if (IS_ERR(core->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		rval = PTR_ERR(core->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 			"Failed to allocate register map: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 			rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		return rval;
^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) 	i2c_set_clientdata(client, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	atomic_set(&core->is_alive, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	core->power_state = SI476X_POWER_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	pdata = dev_get_platdata(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	if (pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 		memcpy(&core->power_up_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 		       &pdata->power_up_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 		       sizeof(core->power_up_parameters));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 		core->gpio_reset = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 		if (gpio_is_valid(pdata->gpio_reset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 			rval = gpio_request(pdata->gpio_reset, "si476x reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 			if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 				dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 					"Failed to request gpio: %d\n", rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 				return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 			core->gpio_reset = pdata->gpio_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 			gpio_direction_output(core->gpio_reset, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 		core->diversity_mode = pdata->diversity_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 		memcpy(&core->pinmux, &pdata->pinmux,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 		       sizeof(struct si476x_pinmux));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		dev_err(&client->dev, "No platform data provided\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	core->supplies[0].supply = "vd";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	core->supplies[1].supply = "va";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	core->supplies[2].supply = "vio1";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	core->supplies[3].supply = "vio2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	rval = devm_regulator_bulk_get(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 				       ARRAY_SIZE(core->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 				       core->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		dev_err(&client->dev, "Failed to get all of the regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 		goto free_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	mutex_init(&core->cmd_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	init_waitqueue_head(&core->command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	init_waitqueue_head(&core->tuning);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 	rval = kfifo_alloc(&core->rds_fifo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 			   SI476X_DRIVER_RDS_FIFO_DEPTH *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 			   sizeof(struct v4l2_rds_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 			   GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	if (rval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 		dev_err(&client->dev, "Could not allocate the FIFO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 		goto free_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	mutex_init(&core->rds_drainer_status_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	init_waitqueue_head(&core->rds_read_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	INIT_WORK(&core->rds_fifo_drainer, si476x_core_drain_rds_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 		rval = devm_request_threaded_irq(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 						 client->irq, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 						 si476x_core_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 						 IRQF_TRIGGER_FALLING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 						 IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 						 client->name, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 		if (rval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 			dev_err(&client->dev, "Could not request IRQ %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 				client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 			goto free_kfifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 		disable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 		dev_dbg(&client->dev, "IRQ requested.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 		core->rds_fifo_depth = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 		INIT_DELAYED_WORK(&core->status_monitor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 				  si476x_core_poll_loop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 		dev_info(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 			 "No IRQ number specified, will use polling\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 		core->rds_fifo_depth = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 	core->chip_id = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	rval = si476x_core_get_revision_info(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	if (rval < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 		rval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 		goto free_kfifo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	cell_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	cell = &core->cells[SI476X_RADIO_CELL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	cell->name = "si476x-radio";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	cell_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) #ifdef CONFIG_SND_SOC_SI476X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	if ((core->chip_id == SI476X_CHIP_SI4761 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 	     core->chip_id == SI476X_CHIP_SI4764)	&&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 	    core->pinmux.dclk == SI476X_DCLK_DAUDIO     &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 	    core->pinmux.dfs  == SI476X_DFS_DAUDIO      &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	    core->pinmux.dout == SI476X_DOUT_I2S_OUTPUT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	    core->pinmux.xout == SI476X_XOUT_TRISTATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 		cell = &core->cells[SI476X_CODEC_CELL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 		cell->name          = "si476x-codec";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 		cell_num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 	rval = mfd_add_devices(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 			       (client->adapter->nr << 8) + client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 			       core->cells, cell_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 			       NULL, 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	if (!rval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) free_kfifo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	kfifo_free(&core->rds_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) free_gpio:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	if (gpio_is_valid(core->gpio_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 		gpio_free(core->gpio_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static int si476x_core_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	struct si476x_core *core = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	si476x_core_pronounce_dead(core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 	mfd_remove_devices(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	if (client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 		disable_irq(client->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 		cancel_delayed_work_sync(&core->status_monitor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	kfifo_free(&core->rds_fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	if (gpio_is_valid(core->gpio_reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 		gpio_free(core->gpio_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	return 0;
^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) static const struct i2c_device_id si476x_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 	{ "si4761", SI476X_CHIP_SI4761 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	{ "si4764", SI476X_CHIP_SI4764 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 	{ "si4768", SI476X_CHIP_SI4768 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) MODULE_DEVICE_TABLE(i2c, si476x_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) static struct i2c_driver si476x_core_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	.driver		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 		.name	= "si476x-core",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	.probe		= si476x_core_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	.remove         = si476x_core_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 	.id_table       = si476x_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) module_i2c_driver(si476x_core_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) MODULE_DESCRIPTION("Si4761/64/68 AM/FM MFD core device driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) MODULE_LICENSE("GPL");