brintos

brintos / linux-shallow public Read only

0
0
Text · 8.0 KiB · ff86c8c Raw
375 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Copyright (C) 2017-2020 Jacopo Mondi4 * Copyright (C) 2017-2020 Kieran Bingham5 * Copyright (C) 2017-2020 Laurent Pinchart6 * Copyright (C) 2017-2020 Niklas Söderlund7 * Copyright (C) 2016 Renesas Electronics Corporation8 * Copyright (C) 2015 Cogent Embedded, Inc.9 *10 * This file exports functions to control the Maxim MAX9271 GMSL serializer11 * chip. This is not a self-contained driver, as MAX9271 is usually embedded in12 * camera modules with at least one image sensor and optional additional13 * components, such as uController units or ISPs/DSPs.14 *15 * Drivers for the camera modules (i.e. rdacm20/21) are expected to use16 * functions exported from this library driver to maximize code re-use.17 */18 19#include <linux/delay.h>20#include <linux/i2c.h>21#include <linux/module.h>22 23#include "max9271.h"24 25static int max9271_read(struct max9271_device *dev, u8 reg)26{27	int ret;28 29	dev_dbg(&dev->client->dev, "%s(0x%02x)\n", __func__, reg);30 31	ret = i2c_smbus_read_byte_data(dev->client, reg);32	if (ret < 0)33		dev_dbg(&dev->client->dev,34			"%s: register 0x%02x read failed (%d)\n",35			__func__, reg, ret);36 37	return ret;38}39 40static int max9271_write(struct max9271_device *dev, u8 reg, u8 val)41{42	int ret;43 44	dev_dbg(&dev->client->dev, "%s(0x%02x, 0x%02x)\n", __func__, reg, val);45 46	ret = i2c_smbus_write_byte_data(dev->client, reg, val);47	if (ret < 0)48		dev_err(&dev->client->dev,49			"%s: register 0x%02x write failed (%d)\n",50			__func__, reg, ret);51 52	return ret;53}54 55/*56 * max9271_pclk_detect() - Detect valid pixel clock from image sensor57 *58 * Wait up to 10ms for a valid pixel clock.59 *60 * Returns 0 for success, < 0 for pixel clock not properly detected61 */62static int max9271_pclk_detect(struct max9271_device *dev)63{64	unsigned int i;65	int ret;66 67	for (i = 0; i < 100; i++) {68		ret = max9271_read(dev, 0x15);69		if (ret < 0)70			return ret;71 72		if (ret & MAX9271_PCLKDET)73			return 0;74 75		usleep_range(50, 100);76	}77 78	dev_err(&dev->client->dev, "Unable to detect valid pixel clock\n");79 80	return -EIO;81}82 83void max9271_wake_up(struct max9271_device *dev)84{85	/*86	 * Use the chip default address as this function has to be called87	 * before any other one.88	 */89	dev->client->addr = MAX9271_DEFAULT_ADDR;90	i2c_smbus_read_byte(dev->client);91	usleep_range(5000, 8000);92}93EXPORT_SYMBOL_GPL(max9271_wake_up);94 95int max9271_set_serial_link(struct max9271_device *dev, bool enable)96{97	int ret;98	u8 val = MAX9271_REVCCEN | MAX9271_FWDCCEN;99 100	if (enable) {101		ret = max9271_pclk_detect(dev);102		if (ret)103			return ret;104 105		val |= MAX9271_SEREN;106	} else {107		val |= MAX9271_CLINKEN;108	}109 110	/*111	 * The serializer temporarily disables the reverse control channel for112	 * 350µs after starting/stopping the forward serial link, but the113	 * deserializer synchronization time isn't clearly documented.114	 *115	 * According to the serializer datasheet we should wait 3ms, while116	 * according to the deserializer datasheet we should wait 5ms.117	 *118	 * Short delays here appear to show bit-errors in the writes following.119	 * Therefore a conservative delay seems best here.120	 */121	ret = max9271_write(dev, 0x04, val);122	if (ret < 0)123		return ret;124 125	usleep_range(5000, 8000);126 127	return 0;128}129EXPORT_SYMBOL_GPL(max9271_set_serial_link);130 131int max9271_configure_i2c(struct max9271_device *dev, u8 i2c_config)132{133	int ret;134 135	ret = max9271_write(dev, 0x0d, i2c_config);136	if (ret < 0)137		return ret;138 139	/* The delay required after an I2C bus configuration change is not140	 * characterized in the serializer manual. Sleep up to 5msec to141	 * stay safe.142	 */143	usleep_range(3500, 5000);144 145	return 0;146}147EXPORT_SYMBOL_GPL(max9271_configure_i2c);148 149int max9271_set_high_threshold(struct max9271_device *dev, bool enable)150{151	int ret;152 153	ret = max9271_read(dev, 0x08);154	if (ret < 0)155		return ret;156 157	/*158	 * Enable or disable reverse channel high threshold to increase159	 * immunity to power supply noise.160	 */161	ret = max9271_write(dev, 0x08, enable ? ret | BIT(0) : ret & ~BIT(0));162	if (ret < 0)163		return ret;164 165	usleep_range(2000, 2500);166 167	return 0;168}169EXPORT_SYMBOL_GPL(max9271_set_high_threshold);170 171int max9271_configure_gmsl_link(struct max9271_device *dev)172{173	int ret;174 175	/*176	 * Configure the GMSL link:177	 *178	 * - Double input mode, high data rate, 24-bit mode179	 * - Latch input data on PCLKIN rising edge180	 * - Enable HS/VS encoding181	 * - 1-bit parity error detection182	 *183	 * TODO: Make the GMSL link configuration parametric.184	 */185	ret = max9271_write(dev, 0x07, MAX9271_DBL | MAX9271_HVEN |186			    MAX9271_EDC_1BIT_PARITY);187	if (ret < 0)188		return ret;189 190	usleep_range(5000, 8000);191 192	/*193	 * Adjust spread spectrum to +4% and auto-detect pixel clock194	 * and serial link rate.195	 */196	ret = max9271_write(dev, 0x02,197			    MAX9271_SPREAD_SPECT_4 | MAX9271_R02_RES |198			    MAX9271_PCLK_AUTODETECT |199			    MAX9271_SERIAL_AUTODETECT);200	if (ret < 0)201		return ret;202 203	usleep_range(5000, 8000);204 205	return 0;206}207EXPORT_SYMBOL_GPL(max9271_configure_gmsl_link);208 209int max9271_set_gpios(struct max9271_device *dev, u8 gpio_mask)210{211	int ret;212 213	ret = max9271_read(dev, 0x0f);214	if (ret < 0)215		return 0;216 217	ret |= gpio_mask;218	ret = max9271_write(dev, 0x0f, ret);219	if (ret < 0) {220		dev_err(&dev->client->dev, "Failed to set gpio (%d)\n", ret);221		return ret;222	}223 224	usleep_range(3500, 5000);225 226	return 0;227}228EXPORT_SYMBOL_GPL(max9271_set_gpios);229 230int max9271_clear_gpios(struct max9271_device *dev, u8 gpio_mask)231{232	int ret;233 234	ret = max9271_read(dev, 0x0f);235	if (ret < 0)236		return 0;237 238	ret &= ~gpio_mask;239	ret = max9271_write(dev, 0x0f, ret);240	if (ret < 0) {241		dev_err(&dev->client->dev, "Failed to clear gpio (%d)\n", ret);242		return ret;243	}244 245	usleep_range(3500, 5000);246 247	return 0;248}249EXPORT_SYMBOL_GPL(max9271_clear_gpios);250 251int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask)252{253	int ret;254 255	ret = max9271_read(dev, 0x0e);256	if (ret < 0)257		return 0;258 259	/* BIT(0) reserved: GPO is always enabled. */260	ret |= (gpio_mask & ~BIT(0));261	ret = max9271_write(dev, 0x0e, ret);262	if (ret < 0) {263		dev_err(&dev->client->dev, "Failed to enable gpio (%d)\n", ret);264		return ret;265	}266 267	usleep_range(3500, 5000);268 269	return 0;270}271EXPORT_SYMBOL_GPL(max9271_enable_gpios);272 273int max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask)274{275	int ret;276 277	ret = max9271_read(dev, 0x0e);278	if (ret < 0)279		return 0;280 281	/* BIT(0) reserved: GPO cannot be disabled */282	ret &= ~(gpio_mask | BIT(0));283	ret = max9271_write(dev, 0x0e, ret);284	if (ret < 0) {285		dev_err(&dev->client->dev, "Failed to disable gpio (%d)\n", ret);286		return ret;287	}288 289	usleep_range(3500, 5000);290 291	return 0;292}293EXPORT_SYMBOL_GPL(max9271_disable_gpios);294 295int max9271_verify_id(struct max9271_device *dev)296{297	int ret;298 299	ret = max9271_read(dev, 0x1e);300	if (ret < 0) {301		dev_err(&dev->client->dev, "MAX9271 ID read failed (%d)\n",302			ret);303		return ret;304	}305 306	if (ret != MAX9271_ID) {307		dev_err(&dev->client->dev, "MAX9271 ID mismatch (0x%02x)\n",308			ret);309		return -ENXIO;310	}311 312	return 0;313}314EXPORT_SYMBOL_GPL(max9271_verify_id);315 316int max9271_set_address(struct max9271_device *dev, u8 addr)317{318	int ret;319 320	ret = max9271_write(dev, 0x00, addr << 1);321	if (ret < 0) {322		dev_err(&dev->client->dev,323			"MAX9271 I2C address change failed (%d)\n", ret);324		return ret;325	}326	usleep_range(3500, 5000);327 328	return 0;329}330EXPORT_SYMBOL_GPL(max9271_set_address);331 332int max9271_set_deserializer_address(struct max9271_device *dev, u8 addr)333{334	int ret;335 336	ret = max9271_write(dev, 0x01, addr << 1);337	if (ret < 0) {338		dev_err(&dev->client->dev,339			"MAX9271 deserializer address set failed (%d)\n", ret);340		return ret;341	}342	usleep_range(3500, 5000);343 344	return 0;345}346EXPORT_SYMBOL_GPL(max9271_set_deserializer_address);347 348int max9271_set_translation(struct max9271_device *dev, u8 source, u8 dest)349{350	int ret;351 352	ret = max9271_write(dev, 0x09, source << 1);353	if (ret < 0) {354		dev_err(&dev->client->dev,355			"MAX9271 I2C translation setup failed (%d)\n", ret);356		return ret;357	}358	usleep_range(3500, 5000);359 360	ret = max9271_write(dev, 0x0a, dest << 1);361	if (ret < 0) {362		dev_err(&dev->client->dev,363			"MAX9271 I2C translation setup failed (%d)\n", ret);364		return ret;365	}366	usleep_range(3500, 5000);367 368	return 0;369}370EXPORT_SYMBOL_GPL(max9271_set_translation);371 372MODULE_DESCRIPTION("Maxim MAX9271 GMSL Serializer");373MODULE_AUTHOR("Jacopo Mondi");374MODULE_LICENSE("GPL v2");375