18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2017-2020 Jacopo Mondi 48c2ecf20Sopenharmony_ci * Copyright (C) 2017-2020 Kieran Bingham 58c2ecf20Sopenharmony_ci * Copyright (C) 2017-2020 Laurent Pinchart 68c2ecf20Sopenharmony_ci * Copyright (C) 2017-2020 Niklas Söderlund 78c2ecf20Sopenharmony_ci * Copyright (C) 2016 Renesas Electronics Corporation 88c2ecf20Sopenharmony_ci * Copyright (C) 2015 Cogent Embedded, Inc. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This file exports functions to control the Maxim MAX9271 GMSL serializer 118c2ecf20Sopenharmony_ci * chip. This is not a self-contained driver, as MAX9271 is usually embedded in 128c2ecf20Sopenharmony_ci * camera modules with at least one image sensor and optional additional 138c2ecf20Sopenharmony_ci * components, such as uController units or ISPs/DSPs. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Drivers for the camera modules (i.e. rdacm20/21) are expected to use 168c2ecf20Sopenharmony_ci * functions exported from this library driver to maximize code re-use. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/delay.h> 208c2ecf20Sopenharmony_ci#include <linux/i2c.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "max9271.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic int max9271_read(struct max9271_device *dev, u8 reg) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci int ret; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci dev_dbg(&dev->client->dev, "%s(0x%02x)\n", __func__, reg); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci ret = i2c_smbus_read_byte_data(dev->client, reg); 318c2ecf20Sopenharmony_ci if (ret < 0) 328c2ecf20Sopenharmony_ci dev_dbg(&dev->client->dev, 338c2ecf20Sopenharmony_ci "%s: register 0x%02x read failed (%d)\n", 348c2ecf20Sopenharmony_ci __func__, reg, ret); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci return ret; 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int max9271_write(struct max9271_device *dev, u8 reg, u8 val) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci int ret; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci dev_dbg(&dev->client->dev, "%s(0x%02x, 0x%02x)\n", __func__, reg, val); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci ret = i2c_smbus_write_byte_data(dev->client, reg, val); 468c2ecf20Sopenharmony_ci if (ret < 0) 478c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, 488c2ecf20Sopenharmony_ci "%s: register 0x%02x write failed (%d)\n", 498c2ecf20Sopenharmony_ci __func__, reg, ret); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci return ret; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* 558c2ecf20Sopenharmony_ci * max9271_pclk_detect() - Detect valid pixel clock from image sensor 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * Wait up to 10ms for a valid pixel clock. 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Returns 0 for success, < 0 for pixel clock not properly detected 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_cistatic int max9271_pclk_detect(struct max9271_device *dev) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci unsigned int i; 648c2ecf20Sopenharmony_ci int ret; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci for (i = 0; i < 100; i++) { 678c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x15); 688c2ecf20Sopenharmony_ci if (ret < 0) 698c2ecf20Sopenharmony_ci return ret; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (ret & MAX9271_PCLKDET) 728c2ecf20Sopenharmony_ci return 0; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci usleep_range(50, 100); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "Unable to detect valid pixel clock\n"); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return -EIO; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciint max9271_set_serial_link(struct max9271_device *dev, bool enable) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci int ret; 858c2ecf20Sopenharmony_ci u8 val = MAX9271_REVCCEN | MAX9271_FWDCCEN; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (enable) { 888c2ecf20Sopenharmony_ci ret = max9271_pclk_detect(dev); 898c2ecf20Sopenharmony_ci if (ret) 908c2ecf20Sopenharmony_ci return ret; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci val |= MAX9271_SEREN; 938c2ecf20Sopenharmony_ci } else { 948c2ecf20Sopenharmony_ci val |= MAX9271_CLINKEN; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* 988c2ecf20Sopenharmony_ci * The serializer temporarily disables the reverse control channel for 998c2ecf20Sopenharmony_ci * 350µs after starting/stopping the forward serial link, but the 1008c2ecf20Sopenharmony_ci * deserializer synchronization time isn't clearly documented. 1018c2ecf20Sopenharmony_ci * 1028c2ecf20Sopenharmony_ci * According to the serializer datasheet we should wait 3ms, while 1038c2ecf20Sopenharmony_ci * according to the deserializer datasheet we should wait 5ms. 1048c2ecf20Sopenharmony_ci * 1058c2ecf20Sopenharmony_ci * Short delays here appear to show bit-errors in the writes following. 1068c2ecf20Sopenharmony_ci * Therefore a conservative delay seems best here. 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_ci max9271_write(dev, 0x04, val); 1098c2ecf20Sopenharmony_ci usleep_range(5000, 8000); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return 0; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_set_serial_link); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciint max9271_configure_i2c(struct max9271_device *dev, u8 i2c_config) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci int ret; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x0d, i2c_config); 1208c2ecf20Sopenharmony_ci if (ret) 1218c2ecf20Sopenharmony_ci return ret; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* The delay required after an I2C bus configuration change is not 1248c2ecf20Sopenharmony_ci * characterized in the serializer manual. Sleep up to 5msec to 1258c2ecf20Sopenharmony_ci * stay safe. 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return 0; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_configure_i2c); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ciint max9271_set_high_threshold(struct max9271_device *dev, bool enable) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci int ret; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x08); 1388c2ecf20Sopenharmony_ci if (ret < 0) 1398c2ecf20Sopenharmony_ci return ret; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* 1428c2ecf20Sopenharmony_ci * Enable or disable reverse channel high threshold to increase 1438c2ecf20Sopenharmony_ci * immunity to power supply noise. 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci max9271_write(dev, 0x08, enable ? ret | BIT(0) : ret & ~BIT(0)); 1468c2ecf20Sopenharmony_ci usleep_range(2000, 2500); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_set_high_threshold); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciint max9271_configure_gmsl_link(struct max9271_device *dev) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci /* 1558c2ecf20Sopenharmony_ci * Configure the GMSL link: 1568c2ecf20Sopenharmony_ci * 1578c2ecf20Sopenharmony_ci * - Double input mode, high data rate, 24-bit mode 1588c2ecf20Sopenharmony_ci * - Latch input data on PCLKIN rising edge 1598c2ecf20Sopenharmony_ci * - Enable HS/VS encoding 1608c2ecf20Sopenharmony_ci * - 1-bit parity error detection 1618c2ecf20Sopenharmony_ci * 1628c2ecf20Sopenharmony_ci * TODO: Make the GMSL link configuration parametric. 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ci max9271_write(dev, 0x07, MAX9271_DBL | MAX9271_HVEN | 1658c2ecf20Sopenharmony_ci MAX9271_EDC_1BIT_PARITY); 1668c2ecf20Sopenharmony_ci usleep_range(5000, 8000); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* 1698c2ecf20Sopenharmony_ci * Adjust spread spectrum to +4% and auto-detect pixel clock 1708c2ecf20Sopenharmony_ci * and serial link rate. 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_ci max9271_write(dev, 0x02, MAX9271_SPREAD_SPECT_4 | MAX9271_R02_RES | 1738c2ecf20Sopenharmony_ci MAX9271_PCLK_AUTODETECT | MAX9271_SERIAL_AUTODETECT); 1748c2ecf20Sopenharmony_ci usleep_range(5000, 8000); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci return 0; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_configure_gmsl_link); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ciint max9271_set_gpios(struct max9271_device *dev, u8 gpio_mask) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci int ret; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x0f); 1858c2ecf20Sopenharmony_ci if (ret < 0) 1868c2ecf20Sopenharmony_ci return 0; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci ret |= gpio_mask; 1898c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x0f, ret); 1908c2ecf20Sopenharmony_ci if (ret < 0) { 1918c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "Failed to set gpio (%d)\n", ret); 1928c2ecf20Sopenharmony_ci return ret; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_set_gpios); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ciint max9271_clear_gpios(struct max9271_device *dev, u8 gpio_mask) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci int ret; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x0f); 2068c2ecf20Sopenharmony_ci if (ret < 0) 2078c2ecf20Sopenharmony_ci return 0; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci ret &= ~gpio_mask; 2108c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x0f, ret); 2118c2ecf20Sopenharmony_ci if (ret < 0) { 2128c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "Failed to clear gpio (%d)\n", ret); 2138c2ecf20Sopenharmony_ci return ret; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_clear_gpios); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ciint max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci int ret; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x0e); 2278c2ecf20Sopenharmony_ci if (ret < 0) 2288c2ecf20Sopenharmony_ci return 0; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* BIT(0) reserved: GPO is always enabled. */ 2318c2ecf20Sopenharmony_ci ret |= (gpio_mask & ~BIT(0)); 2328c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x0e, ret); 2338c2ecf20Sopenharmony_ci if (ret < 0) { 2348c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "Failed to enable gpio (%d)\n", ret); 2358c2ecf20Sopenharmony_ci return ret; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci return 0; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_enable_gpios); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ciint max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci int ret; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x0e); 2498c2ecf20Sopenharmony_ci if (ret < 0) 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* BIT(0) reserved: GPO cannot be disabled */ 2538c2ecf20Sopenharmony_ci ret &= ~(gpio_mask | BIT(0)); 2548c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x0e, ret); 2558c2ecf20Sopenharmony_ci if (ret < 0) { 2568c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "Failed to disable gpio (%d)\n", ret); 2578c2ecf20Sopenharmony_ci return ret; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci return 0; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_disable_gpios); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ciint max9271_verify_id(struct max9271_device *dev) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci int ret; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci ret = max9271_read(dev, 0x1e); 2718c2ecf20Sopenharmony_ci if (ret < 0) { 2728c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "MAX9271 ID read failed (%d)\n", 2738c2ecf20Sopenharmony_ci ret); 2748c2ecf20Sopenharmony_ci return ret; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (ret != MAX9271_ID) { 2788c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, "MAX9271 ID mismatch (0x%02x)\n", 2798c2ecf20Sopenharmony_ci ret); 2808c2ecf20Sopenharmony_ci return -ENXIO; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci return 0; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_verify_id); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ciint max9271_set_address(struct max9271_device *dev, u8 addr) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci int ret; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x00, addr << 1); 2928c2ecf20Sopenharmony_ci if (ret < 0) { 2938c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, 2948c2ecf20Sopenharmony_ci "MAX9271 I2C address change failed (%d)\n", ret); 2958c2ecf20Sopenharmony_ci return ret; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return 0; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_set_address); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ciint max9271_set_deserializer_address(struct max9271_device *dev, u8 addr) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci int ret; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x01, addr << 1); 3088c2ecf20Sopenharmony_ci if (ret < 0) { 3098c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, 3108c2ecf20Sopenharmony_ci "MAX9271 deserializer address set failed (%d)\n", ret); 3118c2ecf20Sopenharmony_ci return ret; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return 0; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_set_deserializer_address); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ciint max9271_set_translation(struct max9271_device *dev, u8 source, u8 dest) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci int ret; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x09, source << 1); 3248c2ecf20Sopenharmony_ci if (ret < 0) { 3258c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, 3268c2ecf20Sopenharmony_ci "MAX9271 I2C translation setup failed (%d)\n", ret); 3278c2ecf20Sopenharmony_ci return ret; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci ret = max9271_write(dev, 0x0a, dest << 1); 3328c2ecf20Sopenharmony_ci if (ret < 0) { 3338c2ecf20Sopenharmony_ci dev_err(&dev->client->dev, 3348c2ecf20Sopenharmony_ci "MAX9271 I2C translation setup failed (%d)\n", ret); 3358c2ecf20Sopenharmony_ci return ret; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci usleep_range(3500, 5000); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(max9271_set_translation); 342