You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
Merge commit '3aa3879e5e9d97a18cd1e735045f5ea42896d2e1'
* commit '3aa3879e5e9d97a18cd1e735045f5ea42896d2e1': media: i2c: maxim: local: maxim2c: driver version v3.00.00 arm64: dts: rockchip: rk3399-evb-ind-lpddr4-v13-android-avb: add tc35874x configuration arm64: dts: rockchip: rk3399-evb-ind-lpddr4-android-avb: add tc35874x configuration arm64: dts: rockchip: rk3399-ind: tc358749x use dummy codec ARM: fiq_glue: save/restore r6 in fiq_glue_setup media: i2c: techpoint: fix tp9951 2 lane ecc error Change-Id: Ic1705a7ccf3ad23071ab44f130754cfcd4f192cb
This commit is contained in:
@@ -117,6 +117,7 @@ fiq_glue_end:
|
||||
|
||||
ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */
|
||||
stmfd sp!, {r4}
|
||||
THUMB( stmfd sp!, {r6} )
|
||||
mrs r4, cpsr
|
||||
THUMB( mov r6, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) )
|
||||
THUMB( msr cpsr_c, r6 )
|
||||
@@ -128,6 +129,7 @@ ENTRY(fiq_glue_setup) /* func, data, sp, smc call number */
|
||||
moveq r10, #0
|
||||
movne r10, #1
|
||||
msr cpsr_c, r4
|
||||
THUMB( ldmfd sp!, {r6} )
|
||||
ldmfd sp!, {r4}
|
||||
bx lr
|
||||
|
||||
|
||||
@@ -31,6 +31,13 @@
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
ext_cam_clk: external-camera-clock {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <27000000>;
|
||||
clock-output-names = "CLK_CAMERA_27MHZ";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "simple-panel";
|
||||
backlight = <&backlight>;
|
||||
@@ -223,6 +230,35 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/delete-node/ tc358749x@0f;
|
||||
|
||||
tc35874x: tc35874x@0f {
|
||||
status = "disabled";
|
||||
reg = <0x0f>;
|
||||
compatible = "toshiba,tc358749";
|
||||
clocks = <&ext_cam_clk>;
|
||||
clock-names = "refclk";
|
||||
reset-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
|
||||
/* interrupt-parent = <&gpio2>; */
|
||||
/* interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&tc35874x_gpios>;
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "TC358749XBG";
|
||||
rockchip,camera-module-lens-name = "NC";
|
||||
|
||||
port {
|
||||
hdmiin_out0: endpoint {
|
||||
remote-endpoint = <&hdmi_to_mipi_in>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
clock-noncontinuous;
|
||||
link-frequencies =
|
||||
/bits/ 64 <297000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2s2 {
|
||||
@@ -282,6 +318,11 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi_to_mipi_in: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&hdmiin_out0>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
mipi_in_ucam1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&ucam_out1>;
|
||||
@@ -382,6 +423,19 @@
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
hdmiin {
|
||||
tc35874x_gpios: tc35874x_gpios {
|
||||
rockchip,pins =
|
||||
/* PWREN_3.3 */
|
||||
<0 RK_PB5 RK_FUNC_GPIO &pcfg_output_high>,
|
||||
/* HDMIIN_RST */
|
||||
<0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
/* HDMIIN_STBY */
|
||||
<3 RK_PD1 RK_FUNC_GPIO &pcfg_output_high>,
|
||||
/* HDMIIN_INT */
|
||||
<4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
lcd-panel {
|
||||
lcd_panel_reset: lcd-panel-reset {
|
||||
rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
|
||||
@@ -42,6 +42,13 @@
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
ext_cam_clk: external-camera-clock {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <27000000>;
|
||||
clock-output-names = "CLK_CAMERA_27MHZ";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "simple-panel";
|
||||
backlight = <&backlight>;
|
||||
@@ -234,6 +241,35 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/delete-node/ tc358749x@0f;
|
||||
|
||||
tc35874x: tc35874x@0f {
|
||||
status = "disabled";
|
||||
reg = <0x0f>;
|
||||
compatible = "toshiba,tc358749";
|
||||
clocks = <&ext_cam_clk>;
|
||||
clock-names = "refclk";
|
||||
reset-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
|
||||
/* interrupt-parent = <&gpio2>; */
|
||||
/* interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&tc35874x_gpios>;
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "TC358749XBG";
|
||||
rockchip,camera-module-lens-name = "NC";
|
||||
|
||||
port {
|
||||
hdmiin_out0: endpoint {
|
||||
remote-endpoint = <&hdmi_to_mipi_in>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
clock-noncontinuous;
|
||||
link-frequencies =
|
||||
/bits/ 64 <297000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2s2 {
|
||||
@@ -293,6 +329,11 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hdmi_to_mipi_in: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&hdmiin_out0>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
mipi_in_ucam1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&ucam_out1>;
|
||||
@@ -418,6 +459,19 @@
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
hdmiin {
|
||||
tc35874x_gpios: tc35874x_gpios {
|
||||
rockchip,pins =
|
||||
/* PWREN_3.3 */
|
||||
<0 RK_PB5 RK_FUNC_GPIO &pcfg_output_high>,
|
||||
/* HDMIIN_RST */
|
||||
<0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
/* HDMIIN_STBY */
|
||||
<3 RK_PD1 RK_FUNC_GPIO &pcfg_output_high>,
|
||||
/* HDMIIN_INT */
|
||||
<4 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
lcd-panel {
|
||||
lcd_panel_reset: lcd-panel-reset {
|
||||
rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
|
||||
@@ -205,6 +205,11 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dummy_codec: dummy-codec {
|
||||
compatible = "rockchip,dummy-codec";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
||||
tc358749x_sound:tc358749x-sound {
|
||||
status = "okay";
|
||||
compatible = "simple-audio-card";
|
||||
@@ -213,10 +218,10 @@
|
||||
simple-audio-card,bitclock-master = <&sound0_master>;
|
||||
simple-audio-card,frame-master = <&sound0_master>;
|
||||
simple-audio-card,cpu {
|
||||
sound-dai = <&i2s0>;
|
||||
sound-dai = <&i2s0>;
|
||||
};
|
||||
sound0_master: simple-audio-card,codec {
|
||||
sound-dai = <&tc358749x>;
|
||||
sound-dai = <&dummy_codec>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2902,7 +2902,6 @@ config VIDEO_VPX3220
|
||||
|
||||
source "drivers/media/i2c/rk628/Kconfig"
|
||||
|
||||
source "drivers/media/i2c/maxim2c/Kconfig"
|
||||
source "drivers/media/i2c/maxim/Kconfig"
|
||||
|
||||
comment "Video and audio decoders"
|
||||
|
||||
@@ -37,7 +37,6 @@ obj-$(CONFIG_VIDEO_CS3308) += cs3308.o
|
||||
obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
|
||||
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
|
||||
obj-$(CONFIG_VIDEO_CX25840) += cx25840/
|
||||
obj-$(CONFIG_VIDEO_DES_MAXIM2C) += maxim2c/
|
||||
obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim/
|
||||
obj-$(CONFIG_VIDEO_DW9714) += dw9714.o
|
||||
obj-$(CONFIG_VIDEO_DW9763) += dw9763.o
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
menu "Maxim Deserializer devices support"
|
||||
visible if VIDEO_MAXIM_SERDES
|
||||
|
||||
source "drivers/media/i2c/maxim/local/maxim2c/Kconfig"
|
||||
source "drivers/media/i2c/maxim/local/maxim4c/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_VIDEO_MAXIM_DES_MAXIM2C) += maxim2c/
|
||||
obj-$(CONFIG_VIDEO_MAXIM_DES_MAXIM4C) += maxim4c/
|
||||
|
||||
12
drivers/media/i2c/maxim/local/maxim2c/Kconfig
Normal file
12
drivers/media/i2c/maxim/local/maxim2c/Kconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Maxim Dual GMSL deserializer devices
|
||||
#
|
||||
config VIDEO_MAXIM_DES_MAXIM2C
|
||||
tristate "Maxim Dual GMSL deserializer support"
|
||||
depends on VIDEO_MAXIM_SERDES
|
||||
help
|
||||
This driver supports the Maxim Dual GMSL2/GMSL1 deserializer.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called maxim2c.
|
||||
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_VIDEO_DES_MAXIM2C) += maxim2c.o
|
||||
obj-$(CONFIG_VIDEO_MAXIM_DES_MAXIM2C) += maxim2c.o
|
||||
maxim2c-objs += maxim2c_i2c.o \
|
||||
maxim2c_mipi_txphy.o \
|
||||
maxim2c_video_pipe.o \
|
||||
@@ -8,7 +8,3 @@ maxim2c-objs += maxim2c_i2c.o \
|
||||
maxim2c_pattern.o \
|
||||
maxim2c_v4l2.o \
|
||||
maxim2c_drv.o
|
||||
|
||||
obj-$(CONFIG_MAXIM2C_SER_MAX9295) += remote_max9295.o
|
||||
obj-$(CONFIG_MAXIM2C_SER_MAX96715) += remote_max96715.o
|
||||
obj-$(CONFIG_MAXIM2C_SER_MAX96717) += remote_max96717.o
|
||||
@@ -10,11 +10,13 @@
|
||||
#ifndef __MAXIM2C_API_H__
|
||||
#define __MAXIM2C_API_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
|
||||
#include "maxim2c_i2c.h"
|
||||
#include "maxim2c_link.h"
|
||||
#include "maxim2c_video_pipe.h"
|
||||
#include "maxim2c_mipi_txphy.h"
|
||||
#include "maxim2c_remote.h"
|
||||
#include "maxim2c_pattern.h"
|
||||
#include "maxim2c_drv.h"
|
||||
|
||||
@@ -26,28 +28,11 @@
|
||||
/* Maxim Deserializer pwdn on/off enable */
|
||||
#define MAXIM2C_LOCAL_DES_ON_OFF_EN 0
|
||||
|
||||
/* maxim2c i2c api */
|
||||
int maxim2c_i2c_write_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u16 val_len, u32 reg_val);
|
||||
int maxim2c_i2c_read_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u16 val_len, u32 *reg_val);
|
||||
int maxim2c_i2c_update_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len,
|
||||
u32 val_len, u32 val_mask, u32 reg_val);
|
||||
|
||||
int maxim2c_i2c_write_byte(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u8 reg_val);
|
||||
int maxim2c_i2c_read_byte(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u8 *reg_val);
|
||||
int maxim2c_i2c_update_byte(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u8 val_mask, u8 reg_val);
|
||||
|
||||
int maxim2c_i2c_write_array(struct i2c_client *client,
|
||||
const struct maxim2c_i2c_regval *regs);
|
||||
int maxim2c_i2c_load_init_seq(struct device *dev,
|
||||
struct device_node *node, struct maxim2c_i2c_init_seq *init_seq);
|
||||
int maxim2c_i2c_run_init_seq(struct i2c_client *client,
|
||||
struct maxim2c_i2c_init_seq *init_seq);
|
||||
/* maxim2c i2c mux api */
|
||||
int maxim2c_i2c_mux_enable(maxim2c_t *maxim2c, u8 def_mask);
|
||||
int maxim2c_i2c_mux_disable(maxim2c_t *maxim2c);
|
||||
int maxim2c_i2c_mux_init(maxim2c_t *maxim2c);
|
||||
int maxim2c_i2c_mux_deinit(maxim2c_t *maxim2c);
|
||||
|
||||
/* maxim2c link api */
|
||||
u8 maxim2c_link_get_lock_state(maxim2c_t *maxim2c, u8 link_mask);
|
||||
@@ -76,15 +61,8 @@ int maxim2c_dphy_dpll_predef_set(maxim2c_t *maxim2c, s64 link_freq_hz);
|
||||
int maxim2c_mipi_csi_output(maxim2c_t *maxim2c, bool enable);
|
||||
|
||||
/* maxim2c remote api */
|
||||
int maxim2c_remote_mfd_add_devices(maxim2c_t *maxim2c);
|
||||
int maxim2c_remote_devices_init(maxim2c_t *maxim2c, u8 link_init_mask);
|
||||
int maxim2c_remote_devices_deinit(maxim2c_t *maxim2c, u8 link_init_mask);
|
||||
int maxim2c_remote_load_init_seq(maxim2c_remote_t *remote_device);
|
||||
int maxim2c_remote_i2c_addr_select(maxim2c_remote_t *remote_device, u32 i2c_id);
|
||||
int maxim2c_remote_i2c_client_init(maxim2c_remote_t *remote_device,
|
||||
struct i2c_client *des_client);
|
||||
int maxim2c_remote_device_register(maxim2c_t *maxim2c,
|
||||
maxim2c_remote_t *remote_device);
|
||||
int maxim2c_remote_devices_power(maxim2c_t *maxim2c, u8 link_mask, int on);
|
||||
int maxim2c_remote_devices_s_stream(maxim2c_t *maxim2c, u8 link_mask, int enable);
|
||||
|
||||
/* maxim2c v4l2 subdev api */
|
||||
int maxim2c_v4l2_subdev_init(maxim2c_t *maxim2c);
|
||||
@@ -19,6 +19,11 @@
|
||||
* 1. MIPI TXPHY add tunnel mode support
|
||||
* 2. MIPI TXPHY mode only support 2x4Lanes and 2x2Lanes
|
||||
*
|
||||
* V3.00.00
|
||||
* 1. deserializer and serializer are associated through i2c-mux
|
||||
* 2. remote serializer is abstracted as v4l2 subdev
|
||||
* 3. remote camera is bound to remote serializer
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
@@ -42,16 +47,19 @@
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
#include "maxim2c_api.h"
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(2, 0x00, 0x01)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(3, 0x00, 0x00)
|
||||
|
||||
#define MAXIM2C_XVCLK_FREQ 25000000
|
||||
|
||||
static const char *const maxim2c_supply_names[MAXIM2C_NUM_SUPPLIES] = {
|
||||
"vcc1v2",
|
||||
"vcc1v8",
|
||||
};
|
||||
|
||||
static int maxim2c_check_local_chipid(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
@@ -65,9 +73,7 @@ static int maxim2c_check_local_chipid(maxim2c_t *maxim2c)
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
ret = maxim2c_i2c_read_byte(client,
|
||||
MAXIM2C_REG_CHIP_ID, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&chipid);
|
||||
ret = maxim2c_i2c_read_reg(client, MAXIM2C_REG_CHIP_ID, &chipid);
|
||||
if (ret == 0) {
|
||||
if (chipid == maxim2c->chipid) {
|
||||
if (chipid == MAX96716_CHIP_ID) {
|
||||
@@ -93,7 +99,7 @@ static int maxim2c_check_local_chipid(maxim2c_t *maxim2c)
|
||||
|
||||
static irqreturn_t maxim2c_hot_plug_detect_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct maxim2c *maxim2c = dev_id;
|
||||
maxim2c_t *maxim2c = dev_id;
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
int lock_gpio_level = 0;
|
||||
|
||||
@@ -150,7 +156,7 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work)
|
||||
{
|
||||
struct maxim2c_hot_plug_work *hot_plug_work =
|
||||
container_of(work, struct maxim2c_hot_plug_work, state_d_work.work);
|
||||
struct maxim2c *maxim2c =
|
||||
maxim2c_t *maxim2c =
|
||||
container_of(hot_plug_work, struct maxim2c, hot_plug_work);
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
u8 curr_lock_state = 0, last_lock_state = 0, link_lock_change = 0;
|
||||
@@ -168,7 +174,8 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work)
|
||||
last_lock_state = maxim2c->link_lock_state;
|
||||
if ((maxim2c->hot_plug_state == MAXIM2C_HOT_PLUG_OUT)
|
||||
&& (last_lock_state == link_enable_mask)) {
|
||||
maxim2c_link_select_remote_control(maxim2c, 0);
|
||||
// i2c mux enable: disable all remote channel
|
||||
maxim2c_i2c_mux_enable(maxim2c, 0x00);
|
||||
}
|
||||
|
||||
curr_lock_state = maxim2c_link_get_lock_state(maxim2c, link_enable_mask);
|
||||
@@ -189,7 +196,8 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work)
|
||||
if (maxim2c->hot_plug_irq > 0)
|
||||
disable_irq(maxim2c->hot_plug_irq);
|
||||
|
||||
maxim2c_remote_devices_init(maxim2c, MAXIM2C_LINK_MASK_A);
|
||||
// Link A remote device start stream
|
||||
maxim2c_remote_devices_s_stream(maxim2c, MAXIM2C_LINK_MASK_A, 1);
|
||||
|
||||
if (maxim2c->hot_plug_irq > 0)
|
||||
enable_irq(maxim2c->hot_plug_irq);
|
||||
@@ -198,6 +206,9 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work)
|
||||
} else {
|
||||
dev_info(dev, "Link A plug out\n");
|
||||
|
||||
// Link A remote device stop stream
|
||||
maxim2c_remote_devices_s_stream(maxim2c, MAXIM2C_LINK_MASK_A, 0);
|
||||
|
||||
maxim2c_video_pipe_linkid_enable(maxim2c, link_id, false);
|
||||
}
|
||||
}
|
||||
@@ -211,7 +222,8 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work)
|
||||
if (maxim2c->hot_plug_irq > 0)
|
||||
disable_irq(maxim2c->hot_plug_irq);
|
||||
|
||||
maxim2c_remote_devices_init(maxim2c, MAXIM2C_LINK_MASK_B);
|
||||
// Link B remote device start stream
|
||||
maxim2c_remote_devices_s_stream(maxim2c, MAXIM2C_LINK_MASK_B, 1);
|
||||
|
||||
if (maxim2c->hot_plug_irq > 0)
|
||||
enable_irq(maxim2c->hot_plug_irq);
|
||||
@@ -220,13 +232,16 @@ static void maxim2c_hot_plug_state_check_work(struct work_struct *work)
|
||||
} else {
|
||||
dev_info(dev, "Link B plug out\n");
|
||||
|
||||
// Link B remote device stop stream
|
||||
maxim2c_remote_devices_s_stream(maxim2c, MAXIM2C_LINK_MASK_B, 0);
|
||||
|
||||
maxim2c_video_pipe_linkid_enable(maxim2c, link_id, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (curr_lock_state == link_enable_mask) {
|
||||
// remote control mask enable
|
||||
maxim2c_link_select_remote_control(maxim2c, link_enable_mask);
|
||||
// i2c mux enable: enable all enabled link for remote control
|
||||
maxim2c_i2c_mux_enable(maxim2c, link_enable_mask);
|
||||
} else {
|
||||
queue_delayed_work(maxim2c->hot_plug_work.state_check_wq,
|
||||
&maxim2c->hot_plug_work.state_d_work,
|
||||
@@ -291,91 +306,71 @@ static inline u32 maxim2c_cal_delay(u32 cycles)
|
||||
return DIV_ROUND_UP(cycles, MAXIM2C_XVCLK_FREQ / 1000 / 1000);
|
||||
}
|
||||
|
||||
static int maxim2c_local_device_power_on(maxim2c_t *maxim2c)
|
||||
static int maxim2c_device_power_on(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
int ret = 0;
|
||||
|
||||
if (!IS_ERR(maxim2c->pwdn_gpio)) {
|
||||
dev_info(dev, "local device pwdn gpio on\n");
|
||||
ret = regulator_bulk_enable(MAXIM2C_NUM_SUPPLIES, maxim2c->supplies);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable regulators\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(maxim2c->pwdn_gpio, 1);
|
||||
|
||||
usleep_range(20000, 20100);
|
||||
ret = regulator_enable(maxim2c->pwdn_regulator);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Unable to turn pwdn regulator on\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void maxim2c_local_device_power_off(maxim2c_t *maxim2c)
|
||||
static void maxim2c_device_power_off(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
int ret = 0;
|
||||
|
||||
if (!IS_ERR(maxim2c->pwdn_gpio)) {
|
||||
dev_info(dev, "local device pwdn gpio off\n");
|
||||
ret = regulator_disable(maxim2c->pwdn_regulator);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Unable to turn pwdn regulator off\n");
|
||||
|
||||
gpiod_set_value_cansleep(maxim2c->pwdn_gpio, 0);
|
||||
ret = regulator_bulk_disable(MAXIM2C_NUM_SUPPLIES, maxim2c->supplies);
|
||||
if (ret < 0) {
|
||||
dev_warn(dev, "Failed to disable regulators\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int maxim2c_remote_device_power_on(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
|
||||
// remote PoC enable
|
||||
if (!IS_ERR(maxim2c->pocen_gpio)) {
|
||||
dev_info(dev, "remote device pocen gpio on\n");
|
||||
|
||||
gpiod_set_value_cansleep(maxim2c->pocen_gpio, 1);
|
||||
usleep_range(5000, 10000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maxim2c_remote_device_power_off(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
|
||||
// remote PoC enable
|
||||
if (!IS_ERR(maxim2c->pocen_gpio)) {
|
||||
dev_info(dev, "remote device pocen gpio off\n");
|
||||
|
||||
gpiod_set_value_cansleep(maxim2c->pocen_gpio, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int maxim2c_runtime_resume(struct device *dev)
|
||||
{
|
||||
#if MAXIM2C_LOCAL_DES_ON_OFF_EN
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct maxim2c *maxim2c = v4l2_get_subdevdata(sd);
|
||||
maxim2c_t *maxim2c = v4l2_get_subdevdata(sd);
|
||||
int ret = 0;
|
||||
|
||||
#if MAXIM2C_LOCAL_DES_ON_OFF_EN
|
||||
ret |= maxim2c_local_device_power_on(maxim2c);
|
||||
#endif /* MAXIM2C_LOCAL_DES_ON_OFF_EN */
|
||||
|
||||
ret |= maxim2c_remote_device_power_on(maxim2c);
|
||||
ret |= maxim2c_device_power_on(maxim2c);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif /* MAXIM2C_LOCAL_DES_ON_OFF_EN */
|
||||
}
|
||||
|
||||
static int maxim2c_runtime_suspend(struct device *dev)
|
||||
{
|
||||
#if MAXIM2C_LOCAL_DES_ON_OFF_EN
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct maxim2c *maxim2c = v4l2_get_subdevdata(sd);
|
||||
maxim2c_t *maxim2c = v4l2_get_subdevdata(sd);
|
||||
int ret = 0;
|
||||
|
||||
ret |= maxim2c_remote_device_power_off(maxim2c);
|
||||
|
||||
#if MAXIM2C_LOCAL_DES_ON_OFF_EN
|
||||
maxim2c_local_device_power_off(maxim2c);
|
||||
#endif /* MAXIM2C_LOCAL_DES_ON_OFF_EN */
|
||||
maxim2c_device_power_off(maxim2c);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif /* MAXIM2C_LOCAL_DES_ON_OFF_EN */
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops maxim2c_pm_ops = {
|
||||
@@ -386,7 +381,9 @@ static const struct dev_pm_ops maxim2c_pm_ops = {
|
||||
static void maxim2c_module_data_init(maxim2c_t *maxim2c)
|
||||
{
|
||||
maxim2c_link_data_init(maxim2c);
|
||||
|
||||
maxim2c_video_pipe_data_init(maxim2c);
|
||||
|
||||
maxim2c_mipi_txphy_data_init(maxim2c);
|
||||
}
|
||||
|
||||
@@ -480,30 +477,22 @@ static int maxim2c_module_hw_previnit(maxim2c_t *maxim2c)
|
||||
int ret = 0;
|
||||
|
||||
// Disable data transmission through video pipe.
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0002, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xF0, 0x00);
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0002, 0xF0, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
// Video Pipe Y/Z Disable
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0160, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
BIT(1) | BIT(0), 0);
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0160, BIT(1) | BIT(0), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
// MIPI CSI output disable.
|
||||
ret = maxim2c_i2c_write_byte(client,
|
||||
0x0313, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x00);
|
||||
ret = maxim2c_i2c_write_reg(client, 0x0313, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
// MIPI TXPHY standby
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0332, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xF0, 0x00);
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0332, 0xF0, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -516,17 +505,13 @@ static int maxim2c_module_hw_postinit(maxim2c_t *maxim2c)
|
||||
int ret = 0;
|
||||
|
||||
// video pipe disable all
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
0x0160, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0);
|
||||
ret |= maxim2c_i2c_write_reg(client, 0x0160, 0);
|
||||
|
||||
// remote control disable all
|
||||
ret |= maxim2c_link_select_remote_control(maxim2c, 0);
|
||||
|
||||
// Enable data transmission through video pipe.
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0002, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xF0, 0xF0);
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0002, 0xF0, 0xF0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -577,6 +562,18 @@ int maxim2c_module_hw_init(maxim2c_t *maxim2c)
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_module_hw_init);
|
||||
|
||||
static int maxim2c_configure_regulators(maxim2c_t *maxim2c)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAXIM2C_NUM_SUPPLIES; i++)
|
||||
maxim2c->supplies[i].supply = maxim2c_supply_names[i];
|
||||
|
||||
return devm_regulator_bulk_get(&maxim2c->client->dev,
|
||||
MAXIM2C_NUM_SUPPLIES,
|
||||
maxim2c->supplies);
|
||||
}
|
||||
|
||||
static int maxim2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@@ -621,15 +618,24 @@ static int maxim2c_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
maxim2c->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(maxim2c->pwdn_gpio))
|
||||
dev_warn(dev, "Failed to get pwdn-gpios, maybe no use\n");
|
||||
else
|
||||
usleep_range(1000, 1100);
|
||||
ret = maxim2c_configure_regulators(maxim2c);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get power regulators\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
maxim2c->pocen_gpio = devm_gpiod_get(dev, "pocen", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(maxim2c->pocen_gpio))
|
||||
dev_warn(dev, "Failed to get pocen-gpios\n");
|
||||
maxim2c->pwdn_regulator = devm_regulator_get(dev, "pwdn");
|
||||
if (IS_ERR(maxim2c->pwdn_regulator)) {
|
||||
if (PTR_ERR(maxim2c->pwdn_regulator) != -EPROBE_DEFER)
|
||||
dev_err(dev, "Unable to get pwdn regulator (%ld)\n",
|
||||
PTR_ERR(maxim2c->pwdn_regulator));
|
||||
else
|
||||
dev_err(dev, "Get pwdn regulator deferred\n");
|
||||
|
||||
ret = PTR_ERR(maxim2c->pwdn_regulator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
maxim2c->lock_gpio = devm_gpiod_get(dev, "lock", GPIOD_IN);
|
||||
if (IS_ERR(maxim2c->lock_gpio))
|
||||
@@ -637,22 +643,29 @@ static int maxim2c_probe(struct i2c_client *client,
|
||||
|
||||
mutex_init(&maxim2c->mutex);
|
||||
|
||||
ret = maxim2c_local_device_power_on(maxim2c);
|
||||
ret = maxim2c_device_power_on(maxim2c);
|
||||
if (ret)
|
||||
goto err_destroy_mutex;
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = maxim2c_check_local_chipid(maxim2c);
|
||||
if (ret)
|
||||
goto err_power_off;
|
||||
|
||||
// client->dev->driver_data = subdev
|
||||
// subdev->dev->driver_data = maxim2c
|
||||
/*
|
||||
* client->dev->driver_data = subdev
|
||||
* subdev->dev->driver_data = maxim2c
|
||||
*/
|
||||
ret = maxim2c_v4l2_subdev_init(maxim2c);
|
||||
if (ret) {
|
||||
dev_err(dev, "maxim2c probe v4l2 subdev init error\n");
|
||||
goto err_power_off;
|
||||
}
|
||||
|
||||
/* maxim2c test pattern */
|
||||
#if MAXIM2C_TEST_PATTERN
|
||||
ret = maxim2c_pattern_data_init(maxim2c);
|
||||
if (ret)
|
||||
@@ -664,9 +677,10 @@ static int maxim2c_probe(struct i2c_client *client,
|
||||
goto err_power_off;
|
||||
#endif /* MAXIM2C_LOCAL_DES_ON_OFF_EN */
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_idle(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 1000);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
#endif /* MAXIM2C_TEST_PATTERN */
|
||||
@@ -680,23 +694,31 @@ static int maxim2c_probe(struct i2c_client *client,
|
||||
goto err_subdev_deinit;
|
||||
#endif /* MAXIM2C_LOCAL_DES_ON_OFF_EN */
|
||||
|
||||
ret = maxim2c_remote_mfd_add_devices(maxim2c);
|
||||
ret = maxim2c_i2c_mux_init(maxim2c);
|
||||
if (ret)
|
||||
goto err_subdev_deinit;
|
||||
|
||||
// i2c mux enable: default disable all remote channel
|
||||
maxim2c_i2c_mux_enable(maxim2c, 0x00);
|
||||
|
||||
maxim2c_lock_irq_init(maxim2c);
|
||||
maxim2c_lock_state_work_init(maxim2c);
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_idle(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 1000);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_subdev_deinit:
|
||||
maxim2c_v4l2_subdev_deinit(maxim2c);
|
||||
|
||||
err_power_off:
|
||||
maxim2c_local_device_power_off(maxim2c);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
maxim2c_device_power_off(maxim2c);
|
||||
|
||||
err_destroy_mutex:
|
||||
mutex_destroy(&maxim2c->mutex);
|
||||
|
||||
@@ -705,17 +727,20 @@ err_destroy_mutex:
|
||||
|
||||
static int maxim2c_remove(struct i2c_client *client)
|
||||
{
|
||||
maxim2c_t *maxim2c = i2c_get_clientdata(client);
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
maxim2c_t *maxim2c = v4l2_get_subdevdata(sd);
|
||||
|
||||
maxim2c_lock_state_work_deinit(maxim2c);
|
||||
|
||||
maxim2c_v4l2_subdev_deinit(maxim2c);
|
||||
|
||||
maxim2c_i2c_mux_deinit(maxim2c);
|
||||
|
||||
mutex_destroy(&maxim2c->mutex);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev))
|
||||
maxim2c_local_device_power_off(maxim2c);
|
||||
maxim2c_device_power_off(maxim2c);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
return 0;
|
||||
@@ -7,28 +7,31 @@
|
||||
#ifndef __MAXIM2C_DRV_H__
|
||||
#define __MAXIM2C_DRV_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
#include "maxim2c_i2c.h"
|
||||
#include "maxim2c_link.h"
|
||||
#include "maxim2c_video_pipe.h"
|
||||
#include "maxim2c_mipi_txphy.h"
|
||||
#include "maxim2c_remote.h"
|
||||
#include "maxim2c_pattern.h"
|
||||
|
||||
// max96716/max96718 chip id register and value
|
||||
#define MAXIM2C_REG_CHIP_ID 0x0D
|
||||
#define MAX96716_CHIP_ID 0xBE
|
||||
#define MAX96718_CHIP_ID 0xB8
|
||||
|
||||
/* power supply numbers */
|
||||
#define MAXIM2C_NUM_SUPPLIES 2
|
||||
|
||||
enum {
|
||||
MAXIM2C_HOT_PLUG_OUT = 0,
|
||||
MAXIM2C_HOT_PLUG_IN,
|
||||
@@ -56,9 +59,10 @@ struct maxim2c_mode {
|
||||
|
||||
typedef struct maxim2c {
|
||||
struct i2c_client *client;
|
||||
struct maxim4c_i2c_mux i2c_mux;
|
||||
struct clk *xvclk;
|
||||
struct gpio_desc *pwdn_gpio;
|
||||
struct gpio_desc *pocen_gpio;
|
||||
struct regulator_bulk_data supplies[MAXIM2C_NUM_SUPPLIES];
|
||||
struct regulator *pwdn_regulator;
|
||||
struct gpio_desc *lock_gpio;
|
||||
|
||||
struct mutex mutex;
|
||||
@@ -102,9 +106,6 @@ typedef struct maxim2c {
|
||||
struct maxim2c_pattern pattern;
|
||||
|
||||
struct maxim2c_i2c_init_seq extra_init_seq;
|
||||
|
||||
struct mfd_cell remote_mfd_devs[MAXIM2C_LINK_ID_MAX];
|
||||
maxim2c_remote_t *remote_device[MAXIM2C_LINK_ID_MAX];
|
||||
} maxim2c_t;
|
||||
|
||||
#endif /* __MAXIM2C_DRV_H__ */
|
||||
@@ -7,13 +7,15 @@
|
||||
* Author: Cai Wenzhong <cwz@rock-chips.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include "maxim2c_i2c.h"
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "maxim2c_api.h"
|
||||
|
||||
/* Write registers up to 4 at a time */
|
||||
int maxim2c_i2c_write_reg(struct i2c_client *client,
|
||||
int maxim2c_i2c_write(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u32 val_len, u32 reg_val)
|
||||
{
|
||||
u32 buf_i, val_i;
|
||||
@@ -54,10 +56,10 @@ int maxim2c_i2c_write_reg(struct i2c_client *client,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_write_reg);
|
||||
EXPORT_SYMBOL(maxim2c_i2c_write);
|
||||
|
||||
/* Read registers up to 4 at a time */
|
||||
int maxim2c_i2c_read_reg(struct i2c_client *client,
|
||||
int maxim2c_i2c_read(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u32 val_len, u32 *reg_val)
|
||||
{
|
||||
struct i2c_msg msgs[2];
|
||||
@@ -102,88 +104,88 @@ int maxim2c_i2c_read_reg(struct i2c_client *client,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_read_reg);
|
||||
EXPORT_SYMBOL(maxim2c_i2c_read);
|
||||
|
||||
/* Update registers up to 4 at a time */
|
||||
int maxim2c_i2c_update_reg(struct i2c_client *client,
|
||||
int maxim2c_i2c_update(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u32 val_len, u32 val_mask, u32 reg_val)
|
||||
{
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
ret = maxim2c_i2c_read_reg(client, reg_addr, reg_len, val_len, &value);
|
||||
ret = maxim2c_i2c_read(client, reg_addr, reg_len, val_len, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
value &= ~val_mask;
|
||||
value |= (reg_val & val_mask);
|
||||
ret = maxim2c_i2c_write_reg(client, reg_addr, reg_len, val_len, value);
|
||||
ret = maxim2c_i2c_write(client, reg_addr, reg_len, val_len, value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_update_reg);
|
||||
EXPORT_SYMBOL(maxim2c_i2c_update);
|
||||
|
||||
int maxim2c_i2c_write_byte(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u8 reg_val)
|
||||
int maxim2c_i2c_write_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u8 reg_val)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = maxim2c_i2c_write_reg(client,
|
||||
reg_addr, reg_len,
|
||||
ret = maxim2c_i2c_write(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_08BITS, reg_val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_write_byte);
|
||||
EXPORT_SYMBOL(maxim2c_i2c_write_reg);
|
||||
|
||||
int maxim2c_i2c_read_byte(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u8 *reg_val)
|
||||
int maxim2c_i2c_read_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u8 *reg_val)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 value = 0;
|
||||
u8 *value_be_p = (u8 *)&value;
|
||||
|
||||
ret = maxim2c_i2c_read_reg(client,
|
||||
reg_addr, reg_len,
|
||||
ret = maxim2c_i2c_read(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_08BITS, &value);
|
||||
|
||||
*reg_val = *value_be_p;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_read_byte);
|
||||
EXPORT_SYMBOL(maxim2c_i2c_read_reg);
|
||||
|
||||
int maxim2c_i2c_update_byte(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u8 val_mask, u8 reg_val)
|
||||
int maxim2c_i2c_update_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u8 val_mask, u8 reg_val)
|
||||
{
|
||||
u8 value;
|
||||
int ret;
|
||||
|
||||
ret = maxim2c_i2c_read_byte(client, reg_addr, reg_len, &value);
|
||||
ret = maxim2c_i2c_read_reg(client, reg_addr, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
value &= ~val_mask;
|
||||
value |= (reg_val & val_mask);
|
||||
ret = maxim2c_i2c_write_byte(client, reg_addr, reg_len, value);
|
||||
ret = maxim2c_i2c_write_reg(client, reg_addr, value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_update_byte);
|
||||
EXPORT_SYMBOL(maxim2c_i2c_update_reg);
|
||||
|
||||
int maxim2c_i2c_write_array(struct i2c_client *client,
|
||||
const struct maxim2c_i2c_regval *regs)
|
||||
const struct maxim2c_i2c_regval *regs)
|
||||
{
|
||||
u32 i = 0;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; (ret == 0) && (regs[i].reg_addr != MAXIM2C_REG_NULL); i++) {
|
||||
if (regs[i].val_mask != 0)
|
||||
ret = maxim2c_i2c_update_reg(client,
|
||||
ret = maxim2c_i2c_update(client,
|
||||
regs[i].reg_addr, regs[i].reg_len,
|
||||
regs[i].val_len, regs[i].val_mask, regs[i].reg_val);
|
||||
else
|
||||
ret = maxim2c_i2c_write_reg(client,
|
||||
ret = maxim2c_i2c_write(client,
|
||||
regs[i].reg_addr, regs[i].reg_len,
|
||||
regs[i].val_len, regs[i].reg_val);
|
||||
|
||||
@@ -402,6 +404,184 @@ int maxim2c_i2c_run_init_seq(struct i2c_client *client,
|
||||
|
||||
ret = maxim2c_i2c_write_array(client,
|
||||
init_seq->reg_init_seq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_run_init_seq);
|
||||
|
||||
static int __maybe_unused maxim2c_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
maxim2c_t *maxim2c = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(dev, "maxim2c i2c mux select chan = %d\n", chan);
|
||||
|
||||
/* Channel select is disabled when configured in the disabled state. */
|
||||
if (maxim2c->i2c_mux.mux_disable) {
|
||||
dev_err(dev, "maxim2c i2c mux is disabled, select error\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxim2c->i2c_mux.mux_channel == chan)
|
||||
return 0;
|
||||
|
||||
maxim2c->i2c_mux.mux_channel = chan;
|
||||
|
||||
ret = maxim2c_link_select_remote_control(maxim2c, BIT(chan));
|
||||
if (ret) {
|
||||
dev_err(dev, "maxim2c link select remote control error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused maxim2c_i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
maxim2c_t *maxim2c = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(dev, "maxim2c i2c mux deselect chan = %d\n", chan);
|
||||
|
||||
/* Channel deselect is disabled when configured in the disabled state. */
|
||||
if (maxim2c->i2c_mux.mux_disable) {
|
||||
dev_err(dev, "maxim2c i2c mux is disabled, deselect error\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = maxim2c_link_select_remote_control(maxim2c, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "maxim2c link select remote control error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int maxim2c_i2c_mux_disable(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
int ret = 0;
|
||||
|
||||
dev_info(dev, "maxim2c i2c mux disable\n");
|
||||
|
||||
ret = maxim2c_link_select_remote_control(maxim2c, 0xff);
|
||||
if (ret) {
|
||||
dev_err(dev, "maxim2c link select remote control error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
maxim2c->i2c_mux.mux_disable = true;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_mux_disable);
|
||||
|
||||
int maxim2c_i2c_mux_enable(maxim2c_t *maxim2c, u8 def_mask)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
int ret = 0;
|
||||
|
||||
dev_info(dev, "maxim2c i2c mux enable, mask = 0x%02x\n", def_mask);
|
||||
|
||||
ret = maxim2c_link_select_remote_control(maxim2c, def_mask);
|
||||
if (ret) {
|
||||
dev_err(dev, "maxim2c link select remote control error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
maxim2c->i2c_mux.mux_disable = false;
|
||||
maxim2c->i2c_mux.mux_channel = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_mux_enable);
|
||||
|
||||
static u32 maxim2c_i2c_mux_mask(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct device *dev = &maxim2c->client->dev;
|
||||
struct device_node *i2c_mux;
|
||||
struct device_node *node = NULL;
|
||||
u32 i2c_mux_mask = 0;
|
||||
|
||||
/* Balance the of_node_put() performed by of_find_node_by_name(). */
|
||||
of_node_get(dev->of_node);
|
||||
i2c_mux = of_find_node_by_name(dev->of_node, "i2c-mux");
|
||||
if (!i2c_mux) {
|
||||
dev_err(dev, "Failed to find i2c-mux node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Identify which i2c-mux channels are enabled */
|
||||
for_each_child_of_node(i2c_mux, node) {
|
||||
u32 id = 0;
|
||||
|
||||
of_property_read_u32(node, "reg", &id);
|
||||
if (id >= MAXIM2C_LINK_ID_MAX)
|
||||
continue;
|
||||
|
||||
if (!of_device_is_available(node)) {
|
||||
dev_dbg(dev, "Skipping disabled I2C bus port %u\n", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
i2c_mux_mask |= BIT(id);
|
||||
}
|
||||
of_node_put(node);
|
||||
of_node_put(i2c_mux);
|
||||
|
||||
return i2c_mux_mask;
|
||||
}
|
||||
|
||||
int maxim2c_i2c_mux_init(maxim2c_t *maxim2c)
|
||||
{
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
u32 i2c_mux_mask = 0;
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
|
||||
dev_info(dev, "maxim2c i2c mux init\n");
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
maxim2c->i2c_mux.muxc = i2c_mux_alloc(client->adapter, dev,
|
||||
MAXIM2C_LINK_ID_MAX, 0, I2C_MUX_LOCKED,
|
||||
maxim2c_i2c_mux_select, NULL);
|
||||
if (!maxim2c->i2c_mux.muxc)
|
||||
return -ENOMEM;
|
||||
maxim2c->i2c_mux.muxc->priv = maxim2c;
|
||||
|
||||
for (i = 0; i < MAXIM2C_LINK_ID_MAX; i++) {
|
||||
ret = i2c_mux_add_adapter(maxim2c->i2c_mux.muxc, 0, i, 0);
|
||||
if (ret) {
|
||||
i2c_mux_del_adapters(maxim2c->i2c_mux.muxc);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_mux_mask = maxim2c_i2c_mux_mask(maxim2c);
|
||||
maxim2c->i2c_mux.i2c_mux_mask = i2c_mux_mask;
|
||||
dev_info(dev, "maxim2c i2c mux mask = 0x%x\n", i2c_mux_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_mux_init);
|
||||
|
||||
int maxim2c_i2c_mux_deinit(maxim2c_t *maxim2c)
|
||||
{
|
||||
if (maxim2c->i2c_mux.muxc)
|
||||
i2c_mux_del_adapters(maxim2c->i2c_mux.muxc);
|
||||
|
||||
maxim2c->i2c_mux.i2c_mux_mask = 0;
|
||||
maxim2c->i2c_mux.mux_disable = false;
|
||||
maxim2c->i2c_mux.mux_channel = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_i2c_mux_deinit);
|
||||
@@ -8,6 +8,7 @@
|
||||
#define __MAXIM2C_I2C_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
|
||||
/* register address: 8bit or 16bit */
|
||||
#define MAXIM2C_I2C_REG_ADDR_08BITS 1
|
||||
@@ -31,6 +32,13 @@ enum {
|
||||
MAXIM2C_I2C_DEV_MAX,
|
||||
};
|
||||
|
||||
struct maxim4c_i2c_mux {
|
||||
struct i2c_mux_core *muxc;
|
||||
u32 i2c_mux_mask;
|
||||
u32 mux_channel;
|
||||
bool mux_disable;
|
||||
};
|
||||
|
||||
/* i2c register array end */
|
||||
#define MAXIM2C_REG_NULL 0xFFFF
|
||||
|
||||
@@ -52,4 +60,27 @@ struct maxim2c_i2c_init_seq {
|
||||
u32 val_len;
|
||||
};
|
||||
|
||||
/* maxim2c i2c read/write api */
|
||||
int maxim2c_i2c_write(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u32 val_len, u32 reg_val);
|
||||
int maxim2c_i2c_read(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len, u32 val_len, u32 *reg_val);
|
||||
int maxim2c_i2c_update(struct i2c_client *client,
|
||||
u16 reg_addr, u16 reg_len,
|
||||
u32 val_len, u32 val_mask, u32 reg_val);
|
||||
|
||||
int maxim2c_i2c_write_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u8 reg_val);
|
||||
int maxim2c_i2c_read_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u8 *reg_val);
|
||||
int maxim2c_i2c_update_reg(struct i2c_client *client,
|
||||
u16 reg_addr, u8 val_mask, u8 reg_val);
|
||||
|
||||
int maxim2c_i2c_write_array(struct i2c_client *client,
|
||||
const struct maxim2c_i2c_regval *regs);
|
||||
int maxim2c_i2c_load_init_seq(struct device *dev,
|
||||
struct device_node *node, struct maxim2c_i2c_init_seq *init_seq);
|
||||
int maxim2c_i2c_run_init_seq(struct i2c_client *client,
|
||||
struct maxim2c_i2c_init_seq *init_seq);
|
||||
|
||||
#endif /* __MAXIM2C_I2C_H__ */
|
||||
@@ -19,10 +19,8 @@ static int maxim2c_link_enable_vdd_ldo1(maxim2c_t *maxim2c)
|
||||
* CTRL0: Enable REG_ENABLE
|
||||
* CTRL2: Enable REG_MNL
|
||||
*/
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0010, MAXIM2C_I2C_REG_ADDR_16BITS, BIT(2), BIT(2));
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0012, MAXIM2C_I2C_REG_ADDR_16BITS, BIT(4), BIT(4));
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0010, BIT(2), BIT(2));
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0012, BIT(4), BIT(4));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -45,9 +43,7 @@ static int maxim2c_link_set_rate(maxim2c_t *maxim2c)
|
||||
else
|
||||
link_rate |= (0x2 << 0);
|
||||
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0001, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x0F, link_rate);
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0001, 0x0F, link_rate);
|
||||
}
|
||||
|
||||
/* Link B rate setting */
|
||||
@@ -60,9 +56,7 @@ static int maxim2c_link_set_rate(maxim2c_t *maxim2c)
|
||||
else
|
||||
link_rate |= (0x2 << 0);
|
||||
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0004, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x0F, link_rate);
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0004, 0x0F, link_rate);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -118,9 +112,7 @@ static int maxim2c_link_status_init(maxim2c_t *maxim2c)
|
||||
}
|
||||
}
|
||||
}
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0006, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0006, reg_mask, reg_value);
|
||||
|
||||
// AUTO_LINK disable, LINK_CFG for Link A and Link B select
|
||||
reg_mask = BIT(4) | BIT(1) | BIT(0);
|
||||
@@ -130,34 +122,26 @@ static int maxim2c_link_status_init(maxim2c_t *maxim2c)
|
||||
if (link_cfg->link_enable)
|
||||
reg_value |= BIT(link_idx);
|
||||
}
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0010, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0010, reg_mask, reg_value);
|
||||
|
||||
// GMSL1 Link disable forward and reverse control channel
|
||||
reg_mask = BIT(1) | BIT(0);
|
||||
reg_value = 0;
|
||||
for (link_idx = 0; link_idx < MAXIM2C_LINK_ID_MAX; link_idx++) {
|
||||
reg_addr = 0x0B04 + 0x100 * link_idx;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client, reg_addr, reg_mask, reg_value);
|
||||
}
|
||||
|
||||
// GMSL2 Link disable remote control channel
|
||||
reg_mask = BIT(4);
|
||||
reg_value = BIT(4);
|
||||
reg_addr = 0x0001;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client, reg_addr, reg_mask, reg_value);
|
||||
|
||||
reg_mask = BIT(2);
|
||||
reg_value = BIT(2);
|
||||
reg_addr = 0x0003;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client, reg_addr, reg_mask, reg_value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -176,18 +160,14 @@ u8 maxim2c_link_get_lock_state(maxim2c_t *maxim2c, u8 link_mask)
|
||||
link_type = gmsl_link->link_cfg[MAXIM2C_LINK_ID_A].link_type;
|
||||
if (link_type == MAXIM2C_GMSL2) {
|
||||
// GMSL2 Link A
|
||||
maxim2c_i2c_read_byte(client,
|
||||
0x0013, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&link_lock);
|
||||
maxim2c_i2c_read_reg(client, 0x0013, &link_lock);
|
||||
if (link_lock & BIT(3)) {
|
||||
lock_state |= MAXIM2C_LINK_MASK_A;
|
||||
dev_dbg(dev, "GMSL2 Link A locked\n");
|
||||
}
|
||||
} else {
|
||||
// GMSL1 Link A
|
||||
maxim2c_i2c_read_byte(client,
|
||||
0x0BCB, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&link_lock);
|
||||
maxim2c_i2c_read_reg(client, 0x0BCB, &link_lock);
|
||||
if (link_lock & BIT(0)) {
|
||||
lock_state |= MAXIM2C_LINK_MASK_A;
|
||||
dev_dbg(dev, "GMSL1 Link A locked\n");
|
||||
@@ -206,18 +186,14 @@ u8 maxim2c_link_get_lock_state(maxim2c_t *maxim2c, u8 link_mask)
|
||||
link_type = gmsl_link->link_cfg[MAXIM2C_LINK_ID_B].link_type;
|
||||
if (link_type == MAXIM2C_GMSL2) {
|
||||
// GMSL2 Link B
|
||||
maxim2c_i2c_read_byte(client,
|
||||
0x5009, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&link_lock);
|
||||
maxim2c_i2c_read_reg(client, 0x5009, &link_lock);
|
||||
if (link_lock & BIT(3)) {
|
||||
lock_state |= MAXIM2C_LINK_MASK_B;
|
||||
dev_dbg(dev, "GMSL2 Link B locked\n");
|
||||
}
|
||||
} else {
|
||||
// GMSL1 Link B
|
||||
maxim2c_i2c_read_byte(client,
|
||||
0x0CCB, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&link_lock);
|
||||
maxim2c_i2c_read_reg(client, 0x0CCB, &link_lock);
|
||||
if (link_lock & BIT(0)) {
|
||||
lock_state |= MAXIM2C_LINK_MASK_B;
|
||||
dev_dbg(dev, "GMSL1 Link B locked\n");
|
||||
@@ -235,7 +211,7 @@ u8 maxim2c_link_get_lock_state(maxim2c_t *maxim2c, u8 link_mask)
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_link_get_lock_state);
|
||||
|
||||
int maxim2c_link_oneshot_reset(struct maxim2c *maxim2c, u8 link_mask)
|
||||
int maxim2c_link_oneshot_reset(maxim2c_t *maxim2c, u8 link_mask)
|
||||
{
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
@@ -250,9 +226,7 @@ int maxim2c_link_oneshot_reset(struct maxim2c *maxim2c, u8 link_mask)
|
||||
link_idx = MAXIM2C_LINK_ID_A;
|
||||
link_cfg = &gmsl_link->link_cfg[link_idx];
|
||||
if (link_cfg->link_enable && (link_mask & BIT(link_idx))) {
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0010, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
BIT(5), BIT(5));
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0010, BIT(5), BIT(5));
|
||||
if (ret) {
|
||||
dev_err(dev, "Link A oneshot reset error\n");
|
||||
return ret;
|
||||
@@ -265,9 +239,7 @@ int maxim2c_link_oneshot_reset(struct maxim2c *maxim2c, u8 link_mask)
|
||||
link_idx = MAXIM2C_LINK_ID_B;
|
||||
link_cfg = &gmsl_link->link_cfg[link_idx];
|
||||
if (link_cfg->link_enable && (link_mask & BIT(link_idx))) {
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0012, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
BIT(5), BIT(5));
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0012, BIT(5), BIT(5));
|
||||
if (ret) {
|
||||
dev_err(dev, "Link B oneshot reset error\n");
|
||||
return ret;
|
||||
@@ -279,13 +251,13 @@ int maxim2c_link_oneshot_reset(struct maxim2c *maxim2c, u8 link_mask)
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_link_oneshot_reset);
|
||||
|
||||
int maxim2c_link_mask_enable(struct maxim2c *maxim2c, u8 link_mask, bool enable)
|
||||
int maxim2c_link_mask_enable(maxim2c_t *maxim2c, u8 link_mask, bool enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_link_mask_enable);
|
||||
|
||||
int maxim2c_link_wait_linklock(struct maxim2c *maxim2c, u8 link_mask)
|
||||
int maxim2c_link_wait_linklock(maxim2c_t *maxim2c, u8 link_mask)
|
||||
{
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
@@ -335,7 +307,7 @@ int maxim2c_link_wait_linklock(struct maxim2c *maxim2c, u8 link_mask)
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_link_wait_linklock);
|
||||
|
||||
int maxim2c_link_select_remote_enable(struct maxim2c *maxim2c, u8 link_mask)
|
||||
int maxim2c_link_select_remote_enable(maxim2c_t *maxim2c, u8 link_mask)
|
||||
{
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
@@ -365,7 +337,7 @@ int maxim2c_link_select_remote_enable(struct maxim2c *maxim2c, u8 link_mask)
|
||||
}
|
||||
EXPORT_SYMBOL(maxim2c_link_select_remote_enable);
|
||||
|
||||
int maxim2c_link_select_remote_control(struct maxim2c *maxim2c, u8 link_mask)
|
||||
int maxim2c_link_select_remote_control(maxim2c_t *maxim2c, u8 link_mask)
|
||||
{
|
||||
struct i2c_client *client = maxim2c->client;
|
||||
struct device *dev = &client->dev;
|
||||
@@ -394,9 +366,8 @@ int maxim2c_link_select_remote_control(struct maxim2c *maxim2c, u8 link_mask)
|
||||
reg_value = 0;
|
||||
|
||||
reg_addr = 0x0B04 + 0x100 * link_idx;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_value);
|
||||
} else {
|
||||
// GMSL2 Link remote control channel
|
||||
if (link_idx == MAXIM2C_LINK_ID_A) {
|
||||
@@ -407,9 +378,8 @@ int maxim2c_link_select_remote_control(struct maxim2c *maxim2c, u8 link_mask)
|
||||
reg_value = 0;
|
||||
else
|
||||
reg_value = BIT(4); // Link A remote control channel disabled
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_value);
|
||||
} else {
|
||||
reg_addr = 0x0003;
|
||||
reg_mask = BIT(2);
|
||||
@@ -417,9 +387,8 @@ int maxim2c_link_select_remote_control(struct maxim2c *maxim2c, u8 link_mask)
|
||||
reg_value = 0;
|
||||
else
|
||||
reg_value = BIT(2); // Link B remote control channel disabled
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -433,6 +402,7 @@ static int maxim2c_gmsl_link_config_parse_dt(struct device *dev,
|
||||
struct device_node *parent_node)
|
||||
{
|
||||
struct device_node *node = NULL;
|
||||
struct device_node *remote_cam_node = NULL;
|
||||
struct device_node *init_seq_node = NULL;
|
||||
struct maxim2c_i2c_init_seq *init_seq = NULL;
|
||||
struct maxim2c_link_cfg *link_cfg = NULL;
|
||||
@@ -503,6 +473,15 @@ static int maxim2c_gmsl_link_config_parse_dt(struct device *dev,
|
||||
link_cfg->link_rx_rate = value;
|
||||
}
|
||||
|
||||
/* link get remote camera node */
|
||||
remote_cam_node = of_parse_phandle(node, "link-remote-cam", 0);
|
||||
if (!IS_ERR_OR_NULL(remote_cam_node)) {
|
||||
dev_info(dev, "remote camera node: %pOF\n", remote_cam_node);
|
||||
link_cfg->remote_cam_node = remote_cam_node;
|
||||
} else {
|
||||
dev_warn(dev, "link-remote-cam node isn't exist\n");
|
||||
}
|
||||
|
||||
/* link init sequence */
|
||||
init_seq_node = of_get_child_by_name(node, "link-init-sequence");
|
||||
if (!IS_ERR_OR_NULL(init_seq_node)) {
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef __MAXIM2C_LINK_H__
|
||||
#define __MAXIM2C_LINK_H__
|
||||
|
||||
#include <linux/of_device.h>
|
||||
#include "maxim2c_i2c.h"
|
||||
|
||||
/* Link cable */
|
||||
@@ -65,6 +66,7 @@ struct maxim2c_link_cfg {
|
||||
u8 link_rx_rate;
|
||||
u8 link_tx_rate;
|
||||
|
||||
struct device_node *remote_cam_node;
|
||||
struct maxim2c_i2c_init_seq link_init_seq;
|
||||
};
|
||||
|
||||
@@ -29,9 +29,8 @@ static int maxim2c_txphy_auto_init_deskew(maxim2c_t *maxim2c)
|
||||
phy_cfg = &mipi_txphy->phy_cfg[phy_idx];
|
||||
if (phy_cfg->phy_enable && (phy_cfg->auto_deskew & BIT(7))) {
|
||||
reg_addr = 0x0403 + 0x40 * phy_idx;
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
phy_cfg->auto_deskew);
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
reg_addr, phy_cfg->auto_deskew);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +59,8 @@ static int maxim2c_mipi_txphy_lane_mapping(maxim2c_t *maxim2c)
|
||||
reg_value |= (phy_cfg->data_lane_map << 4);
|
||||
}
|
||||
if (reg_mask != 0) {
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0333, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
0x0333, reg_mask, reg_value);
|
||||
}
|
||||
|
||||
// MIPI TXPHY C/D: data lane mapping
|
||||
@@ -79,9 +77,8 @@ static int maxim2c_mipi_txphy_lane_mapping(maxim2c_t *maxim2c)
|
||||
reg_value |= (phy_cfg->data_lane_map << 4);
|
||||
}
|
||||
if (reg_mask != 0) {
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0334, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
0x0334, reg_mask, reg_value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -114,9 +111,8 @@ static int maxim2c_mipi_txphy_type_vcx_lane_num(maxim2c_t *maxim2c)
|
||||
reg_value |= ((phy_cfg->data_lane_num - 1) << 6);
|
||||
|
||||
reg_addr = 0x040A + 0x40 * phy_idx;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -153,18 +149,16 @@ static int maxim2c_mipi_txphy_tunnel_init(maxim2c_t *maxim2c)
|
||||
}
|
||||
|
||||
reg_addr = 0x0434 + 0x40 * phy_idx;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_value);
|
||||
|
||||
if (phy_cfg->tunnel_enable) {
|
||||
reg_addr = 0x0433 + 0x40 * phy_idx;
|
||||
reg_mask = (BIT(7) | BIT(6) | BIT(5));
|
||||
reg_value = ((phy_cfg->tunnel_vs_wait & 0x07) << 5);
|
||||
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +186,8 @@ int maxim2c_mipi_txphy_enable(maxim2c_t *maxim2c, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0332, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
0x0332, reg_mask, reg_value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -232,21 +225,15 @@ int maxim2c_dphy_dpll_predef_set(maxim2c_t *maxim2c, s64 link_freq_hz)
|
||||
|
||||
// Hold DPLL in reset (config_soft_rst_n = 0) before changing the rate
|
||||
reg_addr = 0x1C00 + 0x100 * phy_idx;
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xf4);
|
||||
ret |= maxim2c_i2c_write_reg(client, reg_addr, 0xf4);
|
||||
|
||||
// Set dpll data rate
|
||||
reg_addr = 0x031D + 0x03 * phy_idx;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x3F, dpll_val);
|
||||
ret |= maxim2c_i2c_update_reg(client, reg_addr, 0x3F, dpll_val);
|
||||
|
||||
// Release reset to DPLL (config_soft_rst_n = 1)
|
||||
reg_addr = 0x1C00 + 0x100 * phy_idx;
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xf5);
|
||||
ret |= maxim2c_i2c_write_reg(client, reg_addr, 0xf5);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
@@ -255,12 +242,10 @@ int maxim2c_dphy_dpll_predef_set(maxim2c_t *maxim2c, s64 link_freq_hz)
|
||||
}
|
||||
|
||||
#if 0
|
||||
ret = read_poll_timeout(maxim2c_i2c_read_byte, ret,
|
||||
ret = read_poll_timeout(maxim2c_i2c_read_reg, ret,
|
||||
!(ret < 0) && (dpll_lock & dpll_mask),
|
||||
1000, 10000, false,
|
||||
client,
|
||||
0x0308, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&dpll_lock);
|
||||
client, 0x0308, &dpll_lock);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "DPLL is unlocked: 0x%02x\n", dpll_lock);
|
||||
return ret;
|
||||
@@ -271,9 +256,7 @@ int maxim2c_dphy_dpll_predef_set(maxim2c_t *maxim2c, s64 link_freq_hz)
|
||||
#else
|
||||
// The locking status of DPLL cannot be obtained before csi output
|
||||
usleep_range(1000, 1100);
|
||||
ret = maxim2c_i2c_read_byte(client,
|
||||
0x0308, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
&dpll_lock);
|
||||
ret = maxim2c_i2c_read_reg(client, 0x0308, &dpll_lock);
|
||||
dev_info(dev, "DPLL lock state: 0x%02x\n", dpll_lock);
|
||||
|
||||
return ret;
|
||||
@@ -296,9 +279,8 @@ int maxim2c_mipi_csi_output(maxim2c_t *maxim2c, bool enable)
|
||||
reg_value = enable ? BIT(7) : 0;
|
||||
|
||||
// Force all MIPI clocks running Config
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0330, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
0x0330, reg_mask, reg_value);
|
||||
}
|
||||
|
||||
/* Bit1 of the register 0x0313: CSI_OUT_EN
|
||||
@@ -309,9 +291,8 @@ int maxim2c_mipi_csi_output(maxim2c_t *maxim2c, bool enable)
|
||||
reg_value = enable ? BIT(1) : 0;
|
||||
|
||||
// MIPI CSI output Setting
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0313, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_value);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
0x0313, reg_mask, reg_value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -536,14 +517,10 @@ int maxim2c_mipi_txphy_hw_init(maxim2c_t *maxim2c)
|
||||
}
|
||||
|
||||
// MIPI TXPHY Mode setting
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
0x0330, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
mode);
|
||||
ret |= maxim2c_i2c_write_reg(client, 0x0330, mode);
|
||||
|
||||
// Waits for a frame before generating MIPI Packet requests to the MIPI TX
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0325, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
BIT(7), BIT(7));
|
||||
ret |= maxim2c_i2c_update_reg(client, 0x0325, BIT(7), BIT(7));
|
||||
|
||||
// mipi txphy data lane mapping
|
||||
ret |= maxim2c_mipi_txphy_lane_mapping(maxim2c);
|
||||
@@ -60,9 +60,8 @@ int maxim2c_pattern_enable(maxim2c_t *maxim2c, bool enable)
|
||||
/* Generate gradient pattern. */
|
||||
reg_val = enable ? BIT(5) : 0;
|
||||
}
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0241, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_val);
|
||||
ret = maxim2c_i2c_update_reg(client,
|
||||
0x0241, reg_mask, reg_val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -74,30 +73,22 @@ static int maxim2c_pattern_previnit(maxim2c_t *maxim2c)
|
||||
int ret = 0;
|
||||
|
||||
// Disable data transmission through video pipe.
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0002, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xF0, 0x00);
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0002, 0xF0, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
// video pipe disable.
|
||||
ret = maxim2c_i2c_write_byte(client,
|
||||
0x0160, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x00);
|
||||
ret = maxim2c_i2c_write_reg(client, 0x0160, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
// MIPI CSI output disable.
|
||||
ret = maxim2c_i2c_write_byte(client,
|
||||
0x0313, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x00);
|
||||
ret = maxim2c_i2c_write_reg(client, 0x0313, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
// MIPI TXPHY standby
|
||||
ret = maxim2c_i2c_update_byte(client,
|
||||
0x0332, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xF0, 0x00);
|
||||
ret = maxim2c_i2c_update_reg(client, 0x0332, 0xF0, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -131,9 +122,8 @@ static int maxim2c_pattern_config(maxim2c_t *maxim2c)
|
||||
|
||||
// PATGEN_MODE = 0, Pattern generator disabled
|
||||
// use video from the serializer input
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
0x0241, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
BIT(5) | BIT(4), 0x00);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
0x0241, BIT(5) | BIT(4), 0x00);
|
||||
|
||||
/* Pattern PCLK:
|
||||
* 0b00 - 25MHz
|
||||
@@ -141,9 +131,7 @@ static int maxim2c_pattern_config(maxim2c_t *maxim2c)
|
||||
* 0b1x - (PATGEN_CLK_SRC: 0 - 150MHz, 1 - 600MHz).
|
||||
*/
|
||||
pattern_pclk = (pattern_pclk & 0x03);
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
0x0038, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
pattern_pclk);
|
||||
ret |= maxim2c_i2c_write_reg(client, 0x0038, pattern_pclk);
|
||||
if (pattern_pclk >= PATTERN_PCLK_150M) {
|
||||
reg_mask = BIT(7);
|
||||
if (pattern_pclk == PATTERN_PCLK_600M)
|
||||
@@ -153,82 +141,77 @@ static int maxim2c_pattern_config(maxim2c_t *maxim2c)
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
reg_addr = 0x01FC + i * 0x20;
|
||||
ret |= maxim2c_i2c_update_byte(client,
|
||||
reg_addr, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
reg_mask, reg_val);
|
||||
ret |= maxim2c_i2c_update_reg(client,
|
||||
reg_addr, reg_mask, reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure Video Timing Generator for 1920x1080 @ 30 fps. */
|
||||
// VS_DLY = 0
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0242, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, 0x000000);
|
||||
// VS_HIGH = Vsw * Htot
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0245, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, v_sw * h_tot);
|
||||
// VS_LOW = (Vactive + Vfp + Vbp) * Htot
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0248, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, (v_active + v_fp + v_bp) * h_tot);
|
||||
// V2H = VS_DLY
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x024B, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, 0x000000);
|
||||
// HS_HIGH = Hsw
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x024E, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_16BITS, h_sw);
|
||||
// HS_LOW = Hactive + Hfp + Hbp
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0250, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_16BITS, h_active + h_fp + h_bp);
|
||||
// HS_CNT = Vtot
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0252, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_16BITS, v_tot);
|
||||
// V2D = VS_DLY + Htot * (Vsw + Vbp) + (Hsw + Hbp)
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0254, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, h_tot * (v_sw + v_bp) + (h_sw + h_bp));
|
||||
// DE_HIGH = Hactive
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0257, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_16BITS, h_active);
|
||||
// DE_LOW = Hfp + Hsw + Hbp
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0259, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_16BITS, h_fp + h_sw + h_bp);
|
||||
// DE_CNT = Vactive
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x025B, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_16BITS, v_active);
|
||||
|
||||
/* Generate VS, HS and DE in free-running mode, Invert HS and VS. */
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
0x0240, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0xfb);
|
||||
ret |= maxim2c_i2c_write_reg(client, 0x0240, 0xfb);
|
||||
|
||||
/* Configure Video Pattern Generator. */
|
||||
if (pattern_mode == PATTERN_CHECKERBOARD) {
|
||||
/* Set checkerboard pattern size. */
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0264, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, 0x3c3c3c);
|
||||
|
||||
/* Set checkerboard pattern colors. */
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x025E, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, 0xfecc00);
|
||||
ret |= maxim2c_i2c_write_reg(client,
|
||||
ret |= maxim2c_i2c_write(client,
|
||||
0x0261, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
MAXIM2C_I2C_REG_VALUE_24BITS, 0x006aa7);
|
||||
} else {
|
||||
/* Set gradient increment. */
|
||||
ret |= maxim2c_i2c_write_byte(client,
|
||||
0x025D, MAXIM2C_I2C_REG_ADDR_16BITS,
|
||||
0x10);
|
||||
ret |= maxim2c_i2c_write_reg(client, 0x025D, 0x10);
|
||||
}
|
||||
|
||||
return ret;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user