* [PATCH 0/2] add Silicon Image SiI9234 driver [not found] <CGME20170803074535eucas1p107414859fa54647d1f623c73d0fc17f2@eucas1p1.samsung.com> @ 2017-08-03 7:45 ` Maciej Purski [not found] ` <CGME20170803074538eucas1p1fec88e4f2c3ebc00054fd362a504c03e@eucas1p1.samsung.com> [not found] ` <CGME20170803074541eucas1p2b054d4853a98819fc42f19f7cae7f419@eucas1p2.samsung.com> 0 siblings, 2 replies; 23+ messages in thread From: Maciej Purski @ 2017-08-03 7:45 UTC (permalink / raw) To: dri-devel, devicetree, linux-samsung-soc Cc: mark.rutland, b.zolnierkie, krzk, Maciej Purski, robh+dt, Laurent.pinchart Hi everyone, These patches are a continuation of work by Tomasz Stanislawski on sii9324 driver, which was described in th following letter: https://lists.freedesktop.org/archives/dri-devel/2014-April/057481.html The main differences from the previous code are: * driver moved to /gpu/drm/bridge/ and integrated with drm/bridge subsystem * added filtering-out unsupported display modes * changed gpio interface to up-to-date * changed interrupt handling * improve code style * add hdmi and sii9324 to exynos4412-trats2 device tree All comments are welcome. Regards, Maciej Purski Patch summary: Maciej Purski (2): drm/bridge: add Silicon Image SiI9234 driver ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board .../devicetree/bindings/display/bridge/sii9234.txt | 20 + arch/arm/boot/dts/exynos4412-trats2.dts | 93 ++ drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/sii9234.c | 1019 ++++++++++++++++++++ 5 files changed, 1141 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/sii9234.txt create mode 100644 drivers/gpu/drm/bridge/sii9234.c -- 2.7.4 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
[parent not found: <CGME20170803074538eucas1p1fec88e4f2c3ebc00054fd362a504c03e@eucas1p1.samsung.com>]
* [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver [not found] ` <CGME20170803074538eucas1p1fec88e4f2c3ebc00054fd362a504c03e@eucas1p1.samsung.com> @ 2017-08-03 7:45 ` Maciej Purski 2017-08-03 10:24 ` Laurent Pinchart 2017-08-03 19:36 ` kbuild test robot 0 siblings, 2 replies; 23+ messages in thread From: Maciej Purski @ 2017-08-03 7:45 UTC (permalink / raw) To: dri-devel, devicetree, linux-samsung-soc Cc: airlied, robh+dt, mark.rutland, architt, a.hajda, Laurent.pinchart, krzk, b.zolnierkie, Maciej Purski SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. It is controlled via I2C bus. Its interaction with other devices in video pipeline is performed mainly on HW level. The only interaction it does on device driver level is filtering-out unsupported video modes, it exposes drm_bridge interface to perform this operation. This patch is based on the code refactored by Tomasz Stanislawski <t.stanislaws@samsung.com>, which was initially developed by: Adam Hampson <ahampson@sta.samsung.com> Erik Gilling <konkers@android.com> Shankar Bandal <shankar.b@samsung.com> Dharam Kumar <dharam.kr@samsung.com> Signed-off-by: Maciej Purski <m.purski@samsung.com> --- .../devicetree/bindings/display/bridge/sii9234.txt | 20 + drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/sii9234.c | 1019 ++++++++++++++++++++ 4 files changed, 1048 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/sii9234.txt create mode 100644 drivers/gpu/drm/bridge/sii9234.c diff --git a/Documentation/devicetree/bindings/display/bridge/sii9234.txt b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file mode 100644 index 0000000..2cdf286 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt @@ -0,0 +1,20 @@ +SiI9234 Mobile HD Link Transmitter + +Required properties: +- compatible : "sil,sii9234". +- reg : I2C address for TPI interface, use 0x39 +- vcc-supply : regulator that supplies the chip +- interrupts, interrupt-parent: interrupt specifier of INT pin +- reset-gpios: gpio specifier of RESET pin + +Additional compatible properties are also allowed. + +Example: + sii9234@39 { + compatible = "sil,sii9234"; + reg = <0x39>; + vcc-supply = <&vsil>; + reset-gpios = <&gpf3 4 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpf3>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + }; diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index adf9ae0..f5784e5 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -100,6 +100,14 @@ config DRM_TI_TFP410 ---help--- Texas Instruments TFP410 DVI/HDMI Transmitter driver +config DRM_SII9234 + tristate "Silicon Image SII9234 Driver" + depends on I2C + help + Say Y here if you want support for the MHL interface. + It is an I2C driver, that detects connection of MHL bridge + and starts encapsulation of HDMI signal. + source "drivers/gpu/drm/bridge/analogix/Kconfig" source "drivers/gpu/drm/bridge/adv7511/Kconfig" diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index defcf1e..e3d5eb0 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o obj-$(CONFIG_DRM_SII902X) += sii902x.o +obj-$(CONFIG_DRM_SII9234) += sii9234.o obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c new file mode 100644 index 0000000..9c436e7 --- /dev/null +++ b/drivers/gpu/drm/bridge/sii9234.c @@ -0,0 +1,1019 @@ +/* + * Copyright (C) 2014 Samsung Electronics + * + * Author: Tomasz Stanislawski <t.stanislaws@samsung.com> + * + * Based on sii9234 driver created by: + * Adam Hampson <ahampson@sta.samsung.com> + * Erik Gilling <konkers@android.com> + * Shankar Bandal <shankar.b@samsung.com> + * Dharam Kumar <dharam.kr@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program + * + */ +#include <drm/bridge/mhl.h> +#include <drm/drm_crtc.h> +#include <drm/drm_edid.h> + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/wait.h> +#include <linux/file.h> +#include <linux/uaccess.h> +#include <linux/proc_fs.h> +#include <linux/extcon.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/extcon.h> +#include <linux/regulator/machine.h> + +/* MHL Tx registers and bits */ +#define MHL_TX_SRST 0x05 +#define MHL_TX_SYSSTAT_REG 0x09 +#define MHL_TX_INTR1_REG 0x71 +#define MHL_TX_INTR4_REG 0x74 +#define MHL_TX_INTR1_ENABLE_REG 0x75 +#define MHL_TX_INTR4_ENABLE_REG 0x78 +#define MHL_TX_INT_CTRL_REG 0x79 +#define MHL_TX_TMDS_CCTRL 0x80 +#define MHL_TX_DISC_CTRL1_REG 0x90 +#define MHL_TX_DISC_CTRL2_REG 0x91 +#define MHL_TX_DISC_CTRL3_REG 0x92 +#define MHL_TX_DISC_CTRL4_REG 0x93 +#define MHL_TX_DISC_CTRL5_REG 0x94 +#define MHL_TX_DISC_CTRL6_REG 0x95 +#define MHL_TX_DISC_CTRL7_REG 0x96 +#define MHL_TX_DISC_CTRL8_REG 0x97 +#define MHL_TX_STAT2_REG 0x99 +#define MHL_TX_MHLTX_CTL1_REG 0xA0 +#define MHL_TX_MHLTX_CTL2_REG 0xA1 +#define MHL_TX_MHLTX_CTL4_REG 0xA3 +#define MHL_TX_MHLTX_CTL6_REG 0xA5 +#define MHL_TX_MHLTX_CTL7_REG 0xA6 + + +#define RSEN_STATUS BIT(2) +#define HPD_CHANGE_INT BIT(6) +#define RSEN_CHANGE_INT BIT(5) +#define RGND_READY_INT BIT(6) +#define VBUS_LOW_INT BIT(5) +#define CBUS_LKOUT_INT BIT(4) +#define MHL_DISC_FAIL_INT BIT(3) +#define MHL_EST_INT BIT(2) +#define HPD_CHANGE_INT_MASK BIT(6) +#define RSEN_CHANGE_INT_MASK BIT(5) + +#define RGND_READY_MASK BIT(6) +#define CBUS_LKOUT_MASK BIT(4) +#define MHL_DISC_FAIL_MASK BIT(3) +#define MHL_EST_MASK BIT(2) + +#define SKIP_GND BIT(6) + +#define ATT_THRESH_SHIFT 0x04 +#define ATT_THRESH_MASK (0x03 << ATT_THRESH_SHIFT) +#define USB_D_OEN BIT(3) +#define DEGLITCH_TIME_MASK 0x07 +#define DEGLITCH_TIME_2MS 0 +#define DEGLITCH_TIME_4MS 1 +#define DEGLITCH_TIME_8MS 2 +#define DEGLITCH_TIME_16MS 3 +#define DEGLITCH_TIME_40MS 4 +#define DEGLITCH_TIME_50MS 5 +#define DEGLITCH_TIME_60MS 6 +#define DEGLITCH_TIME_128MS 7 + +#define USB_D_OVR BIT(7) +#define USB_ID_OVR BIT(6) +#define DVRFLT_SEL BIT(5) +#define BLOCK_RGND_INT BIT(4) +#define SKIP_DEG BIT(3) +#define CI2CA_POL BIT(2) +#define CI2CA_WKUP BIT(1) +#define SINGLE_ATT BIT(0) + +#define USB_D_ODN BIT(5) +#define VBUS_CHECK BIT(2) +#define RGND_INTP_MASK 0x03 +#define RGND_INTP_OPEN 0 +#define RGND_INTP_2K 1 +#define RGND_INTP_1K 2 +#define RGND_INTP_SHORT 3 + + +/* HDMI registers */ +#define HDMI_RX_TMDS0_CCTRL1_REG 0x10 +#define HDMI_RX_TMDS_CLK_EN_REG 0x11 +#define HDMI_RX_TMDS_CH_EN_REG 0x12 +#define HDMI_RX_PLL_CALREFSEL_REG 0x17 +#define HDMI_RX_PLL_VCOCAL_REG 0x1A +#define HDMI_RX_EQ_DATA0_REG 0x22 +#define HDMI_RX_EQ_DATA1_REG 0x23 +#define HDMI_RX_EQ_DATA2_REG 0x24 +#define HDMI_RX_EQ_DATA3_REG 0x25 +#define HDMI_RX_EQ_DATA4_REG 0x26 +#define HDMI_RX_TMDS_ZONE_CTRL_REG 0x4C +#define HDMI_RX_TMDS_MODE_CTRL_REG 0x4D + +/* CBUS registers */ +#define CBUS_INT_STATUS_1_REG 0x08 +#define CBUS_INTR1_ENABLE_REG 0x09 +#define CBUS_MSC_REQ_ABORT_REASON_REG 0x0D +#define SET_HPD_DOWNSTREAM (1<<6) +#define CBUS_INT_STATUS_2_REG 0x1E +#define CBUS_INTR2_ENABLE_REG 0x1F +#define CBUS_LINK_CONTROL_2_REG 0x31 +#define CBUS_DEVCAP_DEV_STATE 0x80 +#define CBUS_DEVCAP_MHL_VERSION 0x81 +#define CBUS_DEVCAP_DEV_CAT 0x82 +#define CBUS_DEVCAP_ADOPTER_ID_H 0x83 +#define CBUS_DEVCAP_ADOPTER_ID_L 0x84 +#define CBUS_DEVCAP_VID_LINK_MODE 0x85 +#define CBUS_DEVCAP_AUD_LINK_MODE 0x86 +#define CBUS_DEVCAP_VIDEO_TYPE 0x87 +#define CBUS_DEVCAP_LOG_DEV_MAP 0x88 +#define CBUS_DEVCAP_BANDWIDTH 0x89 +#define CBUS_DEVCAP_DEV_FEATURE_FLAG 0x8A +#define CBUS_DEVCAP_DEVICE_ID_H 0x8B +#define CBUS_DEVCAP_DEVICE_ID_L 0x8C +#define CBUS_DEVCAP_SCRATCHPAD_SIZE 0x8D +#define CBUS_DEVCAP_INT_STAT_SIZE 0x8E +#define CBUS_DEVCAP_RESERVED 0x8F +#define CBUS_MHL_STATUS_REG_0 0xB0 +#define CBUS_MHL_STATUS_REG_1 0xB1 + +/* TPI registers */ +#define TPI_DPD_REG 0x3D + +/* timeouts */ +#define T_SRC_VBUS_CBUS_TO_STABLE 200 +#define T_SRC_CBUS_FLOAT 100 +#define T_SRC_CBUS_DEGLITCH 2 +#define T_SRC_RXSENSE_DEGLITCH 110 +#define MHL1_MAX_CLK 75000 + +enum sii9234_state { + ST_OFF, + ST_D3, + ST_RGND_INIT, + ST_RGND_1K, + ST_RSEN_HIGH, + ST_MHL_ESTABLISHED, + ST_FAILURE_DISCOVERY, + ST_FAILURE, +}; + +struct sii9234 { + struct i2c_client *client[4]; + struct drm_bridge bridge; + struct device *dev; + struct gpio_desc *gpio_reset; + int i2c_error; + struct regulator *vcc_supply; + + enum sii9234_state state; + struct mutex lock; +}; + +enum sii9234_client_id { + I2C_MHL, + I2C_TPI, + I2C_HDMI, + I2C_CBUS, +}; + +static char *sii9234_client_name[] = { + [I2C_MHL] = "MHL", + [I2C_TPI] = "TPI", + [I2C_HDMI] = "HDMI", + [I2C_CBUS] = "CBUS", +}; + +static int sii9234_writeb(struct sii9234 *ctx, int id, int offset, + int value) +{ + int ret; + struct i2c_client *client = ctx->client[id]; + + if (ctx->i2c_error) + return ctx->i2c_error; + + ret = i2c_smbus_write_byte_data(client, offset, value); + if (ret < 0) + dev_err(ctx->dev, "writeb: %4s[0x%02x] <- 0x%02x\n", + sii9234_client_name[id], offset, value); + ctx->i2c_error = ret; + return ret; +} + +static int sii9234_writebm(struct sii9234 *ctx, int id, int offset, + int value, int mask) +{ + int ret; + struct i2c_client *client = ctx->client[id]; + + if (ctx->i2c_error) + return ctx->i2c_error; + + ret = i2c_smbus_write_byte(client, offset); + if (ret < 0) { + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", + sii9234_client_name[id], offset, value); + ctx->i2c_error = ret; + return ret; + } + + ret = i2c_smbus_read_byte(client); + if (ret < 0) { + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", + sii9234_client_name[id], offset, value); + ctx->i2c_error = ret; + return ret; + } + + value = (value & mask) | (ret & ~mask); + + ret = i2c_smbus_write_byte_data(client, offset, value); + if (ret < 0) { + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", + sii9234_client_name[id], offset, value); + ctx->i2c_error = ret; + } + return ret; +} + +static int sii9234_readb(struct sii9234 *ctx, int id, int offset) +{ + int ret; + struct i2c_client *client = ctx->client[id]; + + if (ctx->i2c_error) + return ctx->i2c_error; + + ret = i2c_smbus_write_byte(client, offset); + if (ret < 0) { + dev_err(ctx->dev, "readb: %4s[0x%02x]\n", + sii9234_client_name[id], offset); + ctx->i2c_error = ret; + return ret; + } + + ret = i2c_smbus_read_byte(client); + if (ret < 0) { + dev_err(ctx->dev, "readb: %4s[0x%02x]\n", + sii9234_client_name[id], offset); + ctx->i2c_error = ret; + } + + return ret; +} + +static int sii9234_clear_error(struct sii9234 *ctx) +{ + int ret = ctx->i2c_error; + + ctx->i2c_error = 0; + return ret; +} + +#define mhl_tx_writeb(sii9234, offset, value) \ + sii9234_writeb(sii9234, I2C_MHL, offset, value) +#define mhl_tx_writebm(sii9234, offset, value, mask) \ + sii9234_writebm(sii9234, I2C_MHL, offset, value, mask) +#define mhl_tx_readb(sii9234, offset) \ + sii9234_readb(sii9234, I2C_MHL, offset) +#define cbus_writeb(sii9234, offset, value) \ + sii9234_writeb(sii9234, I2C_CBUS, offset, value) +#define cbus_writebm(sii9234, offset, value, mask) \ + sii9234_writebm(sii9234, I2C_CBUS, offset, value, mask) +#define cbus_readb(sii9234, offset) \ + sii9234_readb(sii9234, I2C_CBUS, offset) +#define hdmi_writeb(sii9234, offset, value) \ + sii9234_writeb(sii9234, I2C_HDMI, offset, value) +#define hdmi_writebm(sii9234, offset, value, mask) \ + sii9234_writebm(sii9234, I2C_HDMI, offset, value, mask) +#define hdmi_readb(sii9234, offset) \ + sii9234_readb(sii9234, I2C_HDMI, offset) +#define tpi_writeb(sii9234, offset, value) \ + sii9234_writeb(sii9234, I2C_TPI, offset, value) +#define tpi_writebm(sii9234, offset, value, mask) \ + sii9234_writebm(sii9234, I2C_TPI, offset, value, mask) +#define tpi_readb(sii9234, offset) \ + sii9234_readb(sii9234, I2C_TPI, offset) + +static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable) +{ + mhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0, 0x10); + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0, 0x30); + return sii9234_clear_error(ctx); +} + +static int sii9234_cbus_reset(struct sii9234 *ctx) +{ + int i; + + /* Reset CBUS */ + mhl_tx_writebm(ctx, MHL_TX_SRST, ~0, 1 << 3); + /* CBUS deglitch - 2ms */ + msleep(T_SRC_CBUS_DEGLITCH); + mhl_tx_writebm(ctx, MHL_TX_SRST, 0, 1 << 3); + + for (i = 0; i < 4; i++) { + /* Enable WRITE_STAT interrupt for writes to all + * 4 MSC Status registers. + */ + cbus_writeb(ctx, 0xE0 + i, 0xF2); + /* Enable SET_INT interrupt for writes to all + * 4 MSC Interrupt registers. + */ + cbus_writeb(ctx, 0xF0 + i, 0xF2); + } + + return sii9234_clear_error(ctx); +} + +/* require to chek mhl imformation of samsung in cbus_init_register*/ +static int sii9234_cbus_init(struct sii9234 *ctx) +{ + cbus_writeb(ctx, 0x07, 0xF2); + cbus_writeb(ctx, 0x40, 0x03); + cbus_writeb(ctx, 0x42, 0x06); + cbus_writeb(ctx, 0x36, 0x0C); + cbus_writeb(ctx, 0x3D, 0xFD); + cbus_writeb(ctx, 0x1C, 0x01); + cbus_writeb(ctx, 0x1D, 0x0F); + cbus_writeb(ctx, 0x44, 0x02); + /* Setup our devcap */ + /* To meet cts 6.3.10.1 spec */ + cbus_writeb(ctx, CBUS_DEVCAP_DEV_STATE, 0x00); + /* mhl version 1.1 */ + cbus_writeb(ctx, CBUS_DEVCAP_MHL_VERSION, 0x11); + cbus_writeb(ctx, CBUS_DEVCAP_DEV_CAT, 0x02); + cbus_writeb(ctx, CBUS_DEVCAP_ADOPTER_ID_H, 0x01); + cbus_writeb(ctx, CBUS_DEVCAP_ADOPTER_ID_L, 0x41); + /* YCbCr444, RGB444 */ + cbus_writeb(ctx, CBUS_DEVCAP_VID_LINK_MODE, 0x03); + cbus_writeb(ctx, CBUS_DEVCAP_VIDEO_TYPE, 0); + cbus_writeb(ctx, CBUS_DEVCAP_LOG_DEV_MAP, 0x80); + cbus_writeb(ctx, CBUS_DEVCAP_BANDWIDTH, 0x0F); + cbus_writeb(ctx, CBUS_DEVCAP_DEV_FEATURE_FLAG, 0x07); + cbus_writeb(ctx, CBUS_DEVCAP_DEVICE_ID_H, 0x0); + cbus_writeb(ctx, CBUS_DEVCAP_DEVICE_ID_L, 0x0); + cbus_writeb(ctx, CBUS_DEVCAP_SCRATCHPAD_SIZE, 0x10); + cbus_writeb(ctx, CBUS_DEVCAP_INT_STAT_SIZE, 0x33); + cbus_writeb(ctx, CBUS_DEVCAP_RESERVED, 0); + cbus_writebm(ctx, 0x31, 0x0C, 0x0C); + cbus_writeb(ctx, 0x30, 0x01); + cbus_writebm(ctx, 0x3C, 0x30, 0x38); + cbus_writebm(ctx, 0x22, 0x0D, 0x0F); + cbus_writebm(ctx, 0x2E, 0x15, 0x15); + cbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0); + cbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0); + + return sii9234_clear_error(ctx); +} + +static void force_usb_id_switch_open(struct sii9234 *ctx) +{ + /*Disable CBUS discovery */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01); + /*Force USB ID switch to open */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR); + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86); + /*Force upstream HPD to 0 when not in MHL mode. */ + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30); +} + +static void release_usb_id_switch_open(struct sii9234 *ctx) +{ + msleep(T_SRC_CBUS_FLOAT); + /* clear USB ID switch to open */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR); + /* Enable CBUS discovery */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01); +} + +static int sii9234_power_init(struct sii9234 *ctx) +{ + /* Force the SiI9234 into the D0 state. */ + tpi_writeb(ctx, TPI_DPD_REG, 0x3F); + /* Enable TxPLL Clock */ + hdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01); + /* Enable Tx Clock Path & Equalizer */ + hdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15); + /* Power Up TMDS */ + mhl_tx_writeb(ctx, 0x08, 0x35); + return sii9234_clear_error(ctx); +} + +static int sii9234_hdmi_init(struct sii9234 *ctx) +{ + /* Analog PLL Control bits 5:4 = 2b00 as per char. team. */ + hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1); + /* PLL Calrefsel */ + hdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03); + /* VCO Cal */ + hdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20); + /* Auto EQ */ + hdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A); + /* Auto EQ */ + hdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A); + /* Auto EQ */ + hdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA); + /* Auto EQ */ + hdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA); + /* Auto EQ */ + hdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA); + /* Manual zone */ + hdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0); + /* PLL Mode Value */ + hdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00); + mhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34); + hdmi_writeb(ctx, 0x45, 0x44); + /* Rx PLL BW ~ 4MHz */ + hdmi_writeb(ctx, 0x31, 0x0A); + /* Analog PLL Control * bits 5:4 = 2b00 as per char. team. */ + hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1); + + return sii9234_clear_error(ctx); +} + +static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx) +{ + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0); + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC); + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB); + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C); + return sii9234_clear_error(ctx); +} + +static int sii9234_reset(struct sii9234 *ctx) +{ + int ret; + + sii9234_clear_error(ctx); + + ret = sii9234_power_init(ctx); + if (ret < 0) + return ret; + ret = sii9234_cbus_reset(ctx); + if (ret < 0) + return ret; + ret = sii9234_hdmi_init(ctx); + if (ret < 0) + return ret; + ret = sii9234_mhl_tx_ctl_int(ctx); + if (ret < 0) + return ret; + + /* Enable HDCP Compliance safety */ + mhl_tx_writeb(ctx, 0x2B, 0x01); + /* CBUS discovery cycle time for each drive and float = 150us */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06); + /* Clear bit 6 (reg_skip_rgnd) */ + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7) /* Reserved */ + | 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS); + /* Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel */ + /* 1.8V CBUS VTH & GND threshold */ + /*To meet CTS 3.3.7.2 spec */ + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77); + /* set bit 2 and 3, which is Initiator Timeout */ + cbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, 0x0C); + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0); + /* RGND & single discovery attempt (RGND blocking) */ + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT | + DVRFLT_SEL | SINGLE_ATT); + /* Use VBUS path of discovery state machine */ + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0); + /* 0x92[3] sets the CBUS / ID switch */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR); + /* To allow RGND engine to operate correctly. + * When moving the chip from D2 to D0 (power up, init regs) + * the values should be + * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k + * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be + * set for 10k (default) + * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default) + */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86); + /* change from CC to 8C to match 5K */ + /*To meet CTS 3.3.72 spec */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C); + /* Configure the interrupt as active high */ + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06); + + msleep(25); + + /* release usb_id switch */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR); + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27); + + ret = sii9234_clear_error(ctx); + if (ret < 0) + return ret; + ret = sii9234_cbus_init(ctx); + if (ret < 0) + return ret; + + /* Enable Auto soft reset on SCDT = 0 */ + mhl_tx_writeb(ctx, 0x05, 0x04); + /* HDMI Transcode mode enable */ + mhl_tx_writeb(ctx, 0x0D, 0x1C); + mhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG, + RGND_READY_MASK | CBUS_LKOUT_MASK | + MHL_DISC_FAIL_MASK | MHL_EST_MASK); + mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60); + + /* this point is very importand before megsure RGND impedance */ + force_usb_id_switch_open(ctx); + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0); + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03); + release_usb_id_switch_open(ctx); + /*end of this */ + + /* Force upstream HPD to 0 when not in MHL mode */ + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5); + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4); + + return sii9234_clear_error(ctx); +} + +static int sii9234_goto_d3(struct sii9234 *ctx) +{ + int ret; + + dev_dbg(ctx->dev, "sii9234: detection started d3\n"); + + ret = sii9234_reset(ctx); + if (ret < 0) + goto exit; + + hdmi_writeb(ctx, 0x01, 0x03); + tpi_writebm(ctx, TPI_DPD_REG, 0, 1); + /* I2C above is expected to fail because power goes down */ + sii9234_clear_error(ctx); + + ctx->state = ST_D3; + + return 0; + exit: + dev_err(ctx->dev, "%s failed\n", __func__); + return -1; +} + +#define sii9234_hw_on(sii9234) \ + regulator_enable((sii9234)->vcc_supply) + +static void sii9234_hw_off(struct sii9234 *ctx) +{ + gpiod_set_value(ctx->gpio_reset, 0); + usleep_range(10000, 20000); + gpiod_set_value(ctx->gpio_reset, 1); + regulator_disable(ctx->vcc_supply); + gpiod_set_value(ctx->gpio_reset, 0); +} + +static void sii9234_hw_reset(struct sii9234 *ctx) +{ + gpiod_set_value(ctx->gpio_reset, 0); + usleep_range(10000, 20000); + gpiod_set_value(ctx->gpio_reset, 1); +} + +static void sii9234_cable_in(struct sii9234 *ctx) +{ + int ret; + + mutex_lock(&ctx->lock); + if (ctx->state != ST_OFF) + goto unlock; + ret = sii9234_hw_on(ctx); + if (ret < 0) + goto unlock; + + sii9234_hw_reset(ctx); + sii9234_goto_d3(ctx); + enable_irq(to_i2c_client(ctx->dev)->irq); + +unlock: + mutex_unlock(&ctx->lock); +} + +static void sii9234_cable_out(struct sii9234 *ctx) +{ + mutex_lock(&ctx->lock); + + if (ctx->state == ST_OFF) + goto unlock; + + disable_irq(to_i2c_client(ctx->dev)->irq); + tpi_writeb(ctx, TPI_DPD_REG, 0); + /*turn on&off hpd festure for only QCT HDMI */ + sii9234_hw_off(ctx); + + ctx->state = ST_OFF; + +unlock: + mutex_unlock(&ctx->lock); +} + +static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx) +{ + int value; + + if (ctx->state == ST_D3) { + int ret; + + dev_dbg(ctx->dev, "RGND_READY_INT\n"); + sii9234_hw_reset(ctx); + + ret = sii9234_reset(ctx); + if (ret < 0) { + dev_err(ctx->dev, "sii9234_reset() failed\n"); + return ST_FAILURE; + } + + return ST_RGND_INIT; + } + + /* got interrupt in inappropriate state */ + if (ctx->state != ST_RGND_INIT) + return ST_FAILURE; + + value = mhl_tx_readb(ctx, MHL_TX_STAT2_REG); + if (sii9234_clear_error(ctx)) + return ST_FAILURE; + + if ((value & RGND_INTP_MASK) != RGND_INTP_1K) { + dev_warn(ctx->dev, "RGND is not 1k\n"); + return ST_RGND_INIT; + } + dev_dbg(ctx->dev, "RGND 1K!!\n"); + /* After applying RGND patch, there is some issue + * about discovry failure + * This point is add to fix that problem + */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C); + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77); + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05); + if (sii9234_clear_error(ctx)) + return ST_FAILURE; + + usleep_range(T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC, + T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC); + + return ST_RGND_1K; +} + +static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx) +{ + dev_dbg(ctx->dev, "mhl est interrupt\n"); + + /* discovery override */ + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10); + /* increase DDC translation layer timer (byte mode) */ + cbus_writeb(ctx, 0x07, 0x32); + cbus_writebm(ctx, 0x44, ~0, 1 << 1); + /* Keep the discovery enabled. Need RGND interrupt */ + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1); + mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, + RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK); + + if (sii9234_clear_error(ctx)) + return ST_FAILURE; + + return ST_MHL_ESTABLISHED; +} + +static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx) +{ + int value; + + value = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG); + if (sii9234_clear_error(ctx)) + return ST_FAILURE; + + if (value & SET_HPD_DOWNSTREAM) { + dev_info(ctx->dev, "HPD High\n"); + /* Downstream HPD High, Enable TMDS */ + sii9234_tmds_control(ctx, true); + /*turn on&off hpd festure for only QCT HDMI */ + } else { + dev_info(ctx->dev, "HPD Low\n"); + /* Downstream HPD Low, Disable TMDS */ + sii9234_tmds_control(ctx, false); + } + + return ctx->state; +} + +static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx) +{ + int value; + + /* work_around code to handle worng interrupt */ + if (ctx->state != ST_RGND_1K) { + dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n"); + return ST_FAILURE; + } + value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG); + if (value < 0) + return ST_FAILURE; + + if (value & RSEN_STATUS) { + dev_info(ctx->dev, "MHL cable connected.. RSEN High\n"); + return ST_RSEN_HIGH; + } + dev_info(ctx->dev, "RSEN lost\n"); + /* Once RSEN loss is confirmed,we need to check + * based on cable status and chip power status,whether + * it is SINK Loss(HDMI cable not connected, TV Off) + * or MHL cable disconnection + * TODO: Define the below mhl_disconnection() + */ + msleep(T_SRC_RXSENSE_DEGLITCH); + value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG); + if (value < 0) + return ST_FAILURE; + dev_dbg(ctx->dev, "sys_stat: %x\n", value); + + if (value & RSEN_STATUS) { + dev_info(ctx->dev, "RSEN recovery\n"); + return ST_RSEN_HIGH; + } + dev_info(ctx->dev, "RSEN Really LOW\n"); + /*To meet CTS 3.3.22.2 spec */ + sii9234_tmds_control(ctx, false); + force_usb_id_switch_open(ctx); + release_usb_id_switch_open(ctx); + + return ST_FAILURE; +} + +static irqreturn_t sii9234_irq_thread(int irq, void *data) +{ + struct sii9234 *ctx = data; + int intr1, intr4; + int intr1_en, intr4_en; + int cbus_intr1, cbus_intr2; + + dev_dbg(ctx->dev, "%s\n", __func__); + + msleep(30); + + mutex_lock(&ctx->lock); + + intr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG); + intr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG); + intr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG); + intr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG); + cbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG); + cbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG); + + if (sii9234_clear_error(ctx)) + goto done; + + dev_dbg(ctx->dev, "irq %02x/%02x %02x/%02x %02x/%02x\n", + intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2); + + if (intr4 & RGND_READY_INT) + ctx->state = sii9234_rgnd_ready_irq(ctx); + if (intr1 & RSEN_CHANGE_INT) + ctx->state = sii9234_rsen_change(ctx); + if (intr4 & MHL_EST_INT) + ctx->state = sii9234_mhl_established(ctx); + if (intr1 & HPD_CHANGE_INT) + ctx->state = sii9234_hpd_change(ctx); + if (intr4 & CBUS_LKOUT_INT) + ctx->state = ST_FAILURE; + if (intr4 & MHL_DISC_FAIL_INT) + ctx->state = ST_FAILURE_DISCOVERY; + + done: + /* clean interrupt status and pending flags */ + mhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1); + mhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4); + cbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF); + cbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF); + cbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1); + cbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2); + + sii9234_clear_error(ctx); + + if (ctx->state == ST_FAILURE) { + dev_info(ctx->dev, "try to reset after failure\n"); + sii9234_hw_reset(ctx); + sii9234_goto_d3(ctx); + } + + if (ctx->state == ST_FAILURE_DISCOVERY) { + dev_err(ctx->dev, "discovery failed, no power for MHL?\n"); + tpi_writebm(ctx, TPI_DPD_REG, 0, 1); + ctx->state = ST_D3; + } + + mutex_unlock(&ctx->lock); + + return IRQ_HANDLED; +} + + +static int sii9234_init_resources(struct sii9234 *ctx, + struct i2c_client *client) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + + if (!ctx->dev->of_node) { + dev_err(ctx->dev, "not DT device\n"); + return -ENODEV; + } + + ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->gpio_reset)) { + dev_err(ctx->dev, "failed to get reset gpio from DT\n"); + return PTR_ERR(ctx->gpio_reset); + } + + ctx->vcc_supply = devm_regulator_get(ctx->dev, "vcc"); + if (IS_ERR(ctx->vcc_supply)) { + dev_err(ctx->dev, "failed to acquire regulator vcc\n"); + return PTR_ERR(ctx->vcc_supply); + } + + ctx->client[I2C_MHL] = client; + + ctx->client[I2C_TPI] = i2c_new_dummy(adapter, 0x7A >> 1); + if (!ctx->client[I2C_TPI]) { + dev_err(ctx->dev, "failed to create TPI client\n"); + return -ENODEV; + } + + ctx->client[I2C_HDMI] = i2c_new_dummy(adapter, 0x92 >> 1); + if (!ctx->client[I2C_HDMI]) { + dev_err(ctx->dev, "failed to create HDMI RX client\n"); + goto fail_tpi; + } + + ctx->client[I2C_CBUS] = i2c_new_dummy(adapter, 0xC8 >> 1); + if (!ctx->client[I2C_CBUS]) { + dev_err(ctx->dev, "failed to create CBUS client\n"); + goto fail_hdmi; + } + + return 0; + +fail_hdmi: + i2c_unregister_device(ctx->client[I2C_HDMI]); +fail_tpi: + i2c_unregister_device(ctx->client[I2C_TPI]); + + return -ENODEV; +} + +static void sii9234_deinit_resources(struct sii9234 *ctx) +{ + i2c_unregister_device(ctx->client[I2C_CBUS]); + i2c_unregister_device(ctx->client[I2C_HDMI]); + i2c_unregister_device(ctx->client[I2C_TPI]); +} + +static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge) +{ + return container_of(bridge, struct sii9234, bridge); +} + +static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge, + const struct drm_display_mode *mode) +{ + struct sii9234 *ctx = bridge_to_sii9234(bridge); + + if (mode->clock > MHL1_MAX_CLK) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +static const struct drm_bridge_funcs sii9234_bridge_funcs = { + .mode_valid = sii9234_mode_valid, +}; + +static int sii9234_mhl_tx_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct sii9234 *ctx; + struct device *dev = &client->dev; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->dev = dev; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(dev, "I2C adapter lacks SMBUS feature\n"); + return -EIO; + } + + mutex_init(&ctx->lock); + + ret = sii9234_init_resources(ctx, client); + if (ret < 0) { + dev_err(&client->dev, "failed to initialize sii9234 resources\n"); + return ret; + } + ret = sii9234_hw_on(ctx); + if (ret) { + dev_err(&client->dev, "failed to enable power\n"); + goto err_resource; + } + sii9234_hw_reset(ctx); + + if (!client->irq) { + dev_err(dev, "no irq provided\n"); + return -EINVAL; + } + irq_set_status_flags(client->irq, IRQ_NOAUTOEN); + ret = devm_request_threaded_irq(dev, client->irq, NULL, + sii9234_irq_thread, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "sii9234", ctx); + if (ret < 0) { + dev_err(dev, "failed to install IRQ handler\n"); + return ret; + } + + i2c_set_clientdata(client, ctx); + + ctx->bridge.funcs = &sii9234_bridge_funcs; + ctx->bridge.of_node = dev->of_node; + drm_bridge_add(&ctx->bridge); + + sii9234_cable_in(ctx); + + return 0; + +err_resource: + sii9234_deinit_resources(ctx); + + return ret; +} + +static int sii9234_mhl_tx_i2c_remove(struct i2c_client *client) +{ + struct sii9234 *ctx = i2c_get_clientdata(client); + + sii9234_cable_out(ctx); + drm_bridge_remove(&ctx->bridge); + sii9234_deinit_resources(ctx); + + return 0; +} + +static const struct of_device_id sii9234_dt_match[] = { + { .compatible = "sil,sii9234" }, + { }, +}; +MODULE_DEVICE_TABLE(of, sii9234_dt_match); + +static const struct i2c_device_id sii9234_id[] = { + { "SII9234", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, sii9234_id); +static struct i2c_driver sii9234_driver = { + .driver = { + .name = "sii9234", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(sii9234_dt_match), + }, + .probe = sii9234_mhl_tx_i2c_probe, + .remove = sii9234_mhl_tx_i2c_remove, + .id_table = sii9234_id, +}; + +module_i2c_driver(sii9234_driver); +MODULE_LICENSE("GPL"); -- 2.7.4 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-03 7:45 ` [PATCH 1/2] drm/bridge: " Maciej Purski @ 2017-08-03 10:24 ` Laurent Pinchart 2017-08-04 6:55 ` Marek Szyprowski 2017-08-03 19:36 ` kbuild test robot 1 sibling, 1 reply; 23+ messages in thread From: Laurent Pinchart @ 2017-08-03 10:24 UTC (permalink / raw) To: Maciej Purski Cc: dri-devel, devicetree, linux-samsung-soc, airlied, robh+dt, mark.rutland, architt, a.hajda, krzk, b.zolnierkie Hi Maciej, Thank you for the patch. On Thursday 03 Aug 2017 09:45:22 Maciej Purski wrote: > SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. > It is controlled via I2C bus. Its interaction with other > devices in video pipeline is performed mainly on HW level. > The only interaction it does on device driver level is > filtering-out unsupported video modes, it exposes drm_bridge > interface to perform this operation. > > This patch is based on the code refactored by Tomasz Stanislawski > <t.stanislaws@samsung.com>, which was initially developed by: > Adam Hampson <ahampson@sta.samsung.com> > Erik Gilling <konkers@android.com> > Shankar Bandal <shankar.b@samsung.com> > Dharam Kumar <dharam.kr@samsung.com> > > Signed-off-by: Maciej Purski <m.purski@samsung.com> > --- > .../devicetree/bindings/display/bridge/sii9234.txt | 20 + > drivers/gpu/drm/bridge/Kconfig | 8 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/sii9234.c | 1019 +++++++++++++++++ > 4 files changed, 1048 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/bridge/sii9234.txt create mode > 100644 drivers/gpu/drm/bridge/sii9234.c > > diff --git a/Documentation/devicetree/bindings/display/bridge/sii9234.txt > b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file > mode 100644 > index 0000000..2cdf286 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt DT reviewers might ask you to submit DT bindings as a separate patch. > @@ -0,0 +1,20 @@ > +SiI9234 Mobile HD Link Transmitter > + > +Required properties: > +- compatible : "sil,sii9234". > +- reg : I2C address for TPI interface, use 0x39 > +- vcc-supply : regulator that supplies the chip Is there a single power supply only ? Transceivers usually have at least one digital and one analog power supply. > +- interrupts, interrupt-parent: interrupt specifier of INT pin > +- reset-gpios: gpio specifier of RESET pin Is this mandatory to connect the reset pin to the SoC ? You should use the OF graph DT bindings (a.k.a. ports) to describe the data connections with the rest of the system. I'm not familiar with this chip, but I assume it should have one input port connected to the SoC and one output port connected to an HDMI connector DT node. > +Additional compatible properties are also allowed. How so ? :-) > + > +Example: > + sii9234@39 { > + compatible = "sil,sii9234"; > + reg = <0x39>; > + vcc-supply = <&vsil>; > + reset-gpios = <&gpf3 4 GPIO_ACTIVE_HIGH>; > + interrupt-parent = <&gpf3>; > + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; > + }; > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index adf9ae0..f5784e5 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -100,6 +100,14 @@ config DRM_TI_TFP410 > ---help--- > Texas Instruments TFP410 DVI/HDMI Transmitter driver > > +config DRM_SII9234 > + tristate "Silicon Image SII9234 Driver" > + depends on I2C You can depend on OF too as the driver doesn't currently support any other method. > + help > + Say Y here if you want support for the MHL interface. > + It is an I2C driver, that detects connection of MHL bridge > + and starts encapsulation of HDMI signal. > + > source "drivers/gpu/drm/bridge/analogix/Kconfig" > > source "drivers/gpu/drm/bridge/adv7511/Kconfig" > diff --git a/drivers/gpu/drm/bridge/Makefile > b/drivers/gpu/drm/bridge/Makefile index defcf1e..e3d5eb0 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o > obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o > obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o > obj-$(CONFIG_DRM_SII902X) += sii902x.o > +obj-$(CONFIG_DRM_SII9234) += sii9234.o > obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o > obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ > obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ > diff --git a/drivers/gpu/drm/bridge/sii9234.c > b/drivers/gpu/drm/bridge/sii9234.c new file mode 100644 > index 0000000..9c436e7 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/sii9234.c > @@ -0,0 +1,1019 @@ > +/* > + * Copyright (C) 2014 Samsung Electronics > + * > + * Author: Tomasz Stanislawski <t.stanislaws@samsung.com> > + * > + * Based on sii9234 driver created by: > + * Adam Hampson <ahampson@sta.samsung.com> > + * Erik Gilling <konkers@android.com> > + * Shankar Bandal <shankar.b@samsung.com> > + * Dharam Kumar <dharam.kr@samsung.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program > + * > + */ > +#include <drm/bridge/mhl.h> > +#include <drm/drm_crtc.h> > +#include <drm/drm_edid.h> > + > +#include <linux/delay.h> > +#include <linux/err.h> > +#include <linux/gpio.h> > +#include <linux/i2c.h> > +#include <linux/interrupt.h> > +#include <linux/irq.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/mutex.h> > +#include <linux/platform_device.h> > +#include <linux/slab.h> > +#include <linux/wait.h> > +#include <linux/file.h> > +#include <linux/uaccess.h> > +#include <linux/proc_fs.h> > +#include <linux/extcon.h> > +#include <linux/of.h> > +#include <linux/of_gpio.h> > +#include <linux/extcon.h> > +#include <linux/regulator/machine.h> Could you please order these alphabetically ? > + > +/* MHL Tx registers and bits */ > +#define MHL_TX_SRST 0x05 > +#define MHL_TX_SYSSTAT_REG 0x09 > +#define MHL_TX_INTR1_REG 0x71 > +#define MHL_TX_INTR4_REG 0x74 > +#define MHL_TX_INTR1_ENABLE_REG 0x75 > +#define MHL_TX_INTR4_ENABLE_REG 0x78 > +#define MHL_TX_INT_CTRL_REG 0x79 > +#define MHL_TX_TMDS_CCTRL 0x80 > +#define MHL_TX_DISC_CTRL1_REG 0x90 > +#define MHL_TX_DISC_CTRL2_REG 0x91 > +#define MHL_TX_DISC_CTRL3_REG 0x92 > +#define MHL_TX_DISC_CTRL4_REG 0x93 > +#define MHL_TX_DISC_CTRL5_REG 0x94 > +#define MHL_TX_DISC_CTRL6_REG 0x95 > +#define MHL_TX_DISC_CTRL7_REG 0x96 > +#define MHL_TX_DISC_CTRL8_REG 0x97 > +#define MHL_TX_STAT2_REG 0x99 > +#define MHL_TX_MHLTX_CTL1_REG 0xA0 > +#define MHL_TX_MHLTX_CTL2_REG 0xA1 > +#define MHL_TX_MHLTX_CTL4_REG 0xA3 > +#define MHL_TX_MHLTX_CTL6_REG 0xA5 > +#define MHL_TX_MHLTX_CTL7_REG 0xA6 > + > + > +#define RSEN_STATUS BIT(2) > +#define HPD_CHANGE_INT BIT(6) > +#define RSEN_CHANGE_INT BIT(5) > +#define RGND_READY_INT BIT(6) > +#define VBUS_LOW_INT BIT(5) > +#define CBUS_LKOUT_INT BIT(4) > +#define MHL_DISC_FAIL_INT BIT(3) > +#define MHL_EST_INT BIT(2) > +#define HPD_CHANGE_INT_MASK BIT(6) > +#define RSEN_CHANGE_INT_MASK BIT(5) > + > +#define RGND_READY_MASK BIT(6) > +#define CBUS_LKOUT_MASK BIT(4) > +#define MHL_DISC_FAIL_MASK BIT(3) > +#define MHL_EST_MASK BIT(2) > + > +#define SKIP_GND BIT(6) > + > +#define ATT_THRESH_SHIFT 0x04 > +#define ATT_THRESH_MASK (0x03 << ATT_THRESH_SHIFT) > +#define USB_D_OEN BIT(3) > +#define DEGLITCH_TIME_MASK 0x07 > +#define DEGLITCH_TIME_2MS 0 > +#define DEGLITCH_TIME_4MS 1 > +#define DEGLITCH_TIME_8MS 2 > +#define DEGLITCH_TIME_16MS 3 > +#define DEGLITCH_TIME_40MS 4 > +#define DEGLITCH_TIME_50MS 5 > +#define DEGLITCH_TIME_60MS 6 > +#define DEGLITCH_TIME_128MS 7 > + > +#define USB_D_OVR BIT(7) > +#define USB_ID_OVR BIT(6) > +#define DVRFLT_SEL BIT(5) > +#define BLOCK_RGND_INT BIT(4) > +#define SKIP_DEG BIT(3) > +#define CI2CA_POL BIT(2) > +#define CI2CA_WKUP BIT(1) > +#define SINGLE_ATT BIT(0) > + > +#define USB_D_ODN BIT(5) > +#define VBUS_CHECK BIT(2) > +#define RGND_INTP_MASK 0x03 > +#define RGND_INTP_OPEN 0 > +#define RGND_INTP_2K 1 > +#define RGND_INTP_1K 2 > +#define RGND_INTP_SHORT 3 > + > + > +/* HDMI registers */ > +#define HDMI_RX_TMDS0_CCTRL1_REG 0x10 > +#define HDMI_RX_TMDS_CLK_EN_REG 0x11 > +#define HDMI_RX_TMDS_CH_EN_REG 0x12 > +#define HDMI_RX_PLL_CALREFSEL_REG 0x17 > +#define HDMI_RX_PLL_VCOCAL_REG 0x1A > +#define HDMI_RX_EQ_DATA0_REG 0x22 > +#define HDMI_RX_EQ_DATA1_REG 0x23 > +#define HDMI_RX_EQ_DATA2_REG 0x24 > +#define HDMI_RX_EQ_DATA3_REG 0x25 > +#define HDMI_RX_EQ_DATA4_REG 0x26 > +#define HDMI_RX_TMDS_ZONE_CTRL_REG 0x4C > +#define HDMI_RX_TMDS_MODE_CTRL_REG 0x4D > + > +/* CBUS registers */ > +#define CBUS_INT_STATUS_1_REG 0x08 > +#define CBUS_INTR1_ENABLE_REG 0x09 > +#define CBUS_MSC_REQ_ABORT_REASON_REG 0x0D > +#define SET_HPD_DOWNSTREAM (1<<6) > +#define CBUS_INT_STATUS_2_REG 0x1E > +#define CBUS_INTR2_ENABLE_REG 0x1F > +#define CBUS_LINK_CONTROL_2_REG 0x31 > +#define CBUS_DEVCAP_DEV_STATE 0x80 > +#define CBUS_DEVCAP_MHL_VERSION 0x81 > +#define CBUS_DEVCAP_DEV_CAT 0x82 > +#define CBUS_DEVCAP_ADOPTER_ID_H 0x83 > +#define CBUS_DEVCAP_ADOPTER_ID_L 0x84 > +#define CBUS_DEVCAP_VID_LINK_MODE 0x85 > +#define CBUS_DEVCAP_AUD_LINK_MODE 0x86 > +#define CBUS_DEVCAP_VIDEO_TYPE 0x87 > +#define CBUS_DEVCAP_LOG_DEV_MAP 0x88 > +#define CBUS_DEVCAP_BANDWIDTH 0x89 > +#define CBUS_DEVCAP_DEV_FEATURE_FLAG 0x8A > +#define CBUS_DEVCAP_DEVICE_ID_H 0x8B > +#define CBUS_DEVCAP_DEVICE_ID_L 0x8C > +#define CBUS_DEVCAP_SCRATCHPAD_SIZE 0x8D > +#define CBUS_DEVCAP_INT_STAT_SIZE 0x8E > +#define CBUS_DEVCAP_RESERVED 0x8F > +#define CBUS_MHL_STATUS_REG_0 0xB0 > +#define CBUS_MHL_STATUS_REG_1 0xB1 > + > +/* TPI registers */ > +#define TPI_DPD_REG 0x3D > + > +/* timeouts */ > +#define T_SRC_VBUS_CBUS_TO_STABLE 200 > +#define T_SRC_CBUS_FLOAT 100 > +#define T_SRC_CBUS_DEGLITCH 2 > +#define T_SRC_RXSENSE_DEGLITCH 110 > +#define MHL1_MAX_CLK 75000 > + > +enum sii9234_state { > + ST_OFF, > + ST_D3, > + ST_RGND_INIT, > + ST_RGND_1K, > + ST_RSEN_HIGH, > + ST_MHL_ESTABLISHED, > + ST_FAILURE_DISCOVERY, > + ST_FAILURE, > +}; > + > +struct sii9234 { > + struct i2c_client *client[4]; > + struct drm_bridge bridge; > + struct device *dev; > + struct gpio_desc *gpio_reset; > + int i2c_error; > + struct regulator *vcc_supply; > + > + enum sii9234_state state; > + struct mutex lock; > +}; > + > +enum sii9234_client_id { > + I2C_MHL, > + I2C_TPI, > + I2C_HDMI, > + I2C_CBUS, > +}; > + > +static char *sii9234_client_name[] = { > + [I2C_MHL] = "MHL", > + [I2C_TPI] = "TPI", > + [I2C_HDMI] = "HDMI", > + [I2C_CBUS] = "CBUS", > +}; > + > +static int sii9234_writeb(struct sii9234 *ctx, int id, int offset, > + int value) > +{ > + int ret; > + struct i2c_client *client = ctx->client[id]; > + > + if (ctx->i2c_error) > + return ctx->i2c_error; > + > + ret = i2c_smbus_write_byte_data(client, offset, value); > + if (ret < 0) > + dev_err(ctx->dev, "writeb: %4s[0x%02x] <- 0x%02x\n", > + sii9234_client_name[id], offset, value); > + ctx->i2c_error = ret; > + return ret; > +} > + > +static int sii9234_writebm(struct sii9234 *ctx, int id, int offset, > + int value, int mask) > +{ > + int ret; > + struct i2c_client *client = ctx->client[id]; > + > + if (ctx->i2c_error) > + return ctx->i2c_error; > + > + ret = i2c_smbus_write_byte(client, offset); > + if (ret < 0) { > + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", > + sii9234_client_name[id], offset, value); > + ctx->i2c_error = ret; > + return ret; > + } > + > + ret = i2c_smbus_read_byte(client); > + if (ret < 0) { > + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", > + sii9234_client_name[id], offset, value); > + ctx->i2c_error = ret; > + return ret; > + } > + > + value = (value & mask) | (ret & ~mask); > + > + ret = i2c_smbus_write_byte_data(client, offset, value); > + if (ret < 0) { > + dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n", > + sii9234_client_name[id], offset, value); > + ctx->i2c_error = ret; > + } > + return ret; > +} > + > +static int sii9234_readb(struct sii9234 *ctx, int id, int offset) > +{ > + int ret; > + struct i2c_client *client = ctx->client[id]; > + > + if (ctx->i2c_error) > + return ctx->i2c_error; > + > + ret = i2c_smbus_write_byte(client, offset); > + if (ret < 0) { > + dev_err(ctx->dev, "readb: %4s[0x%02x]\n", > + sii9234_client_name[id], offset); > + ctx->i2c_error = ret; > + return ret; > + } > + > + ret = i2c_smbus_read_byte(client); > + if (ret < 0) { > + dev_err(ctx->dev, "readb: %4s[0x%02x]\n", > + sii9234_client_name[id], offset); > + ctx->i2c_error = ret; > + } > + > + return ret; > +} > + > +static int sii9234_clear_error(struct sii9234 *ctx) > +{ > + int ret = ctx->i2c_error; > + > + ctx->i2c_error = 0; > + return ret; > +} > + > +#define mhl_tx_writeb(sii9234, offset, value) \ > + sii9234_writeb(sii9234, I2C_MHL, offset, value) > +#define mhl_tx_writebm(sii9234, offset, value, mask) \ > + sii9234_writebm(sii9234, I2C_MHL, offset, value, mask) > +#define mhl_tx_readb(sii9234, offset) \ > + sii9234_readb(sii9234, I2C_MHL, offset) > +#define cbus_writeb(sii9234, offset, value) \ > + sii9234_writeb(sii9234, I2C_CBUS, offset, value) > +#define cbus_writebm(sii9234, offset, value, mask) \ > + sii9234_writebm(sii9234, I2C_CBUS, offset, value, mask) > +#define cbus_readb(sii9234, offset) \ > + sii9234_readb(sii9234, I2C_CBUS, offset) > +#define hdmi_writeb(sii9234, offset, value) \ > + sii9234_writeb(sii9234, I2C_HDMI, offset, value) > +#define hdmi_writebm(sii9234, offset, value, mask) \ > + sii9234_writebm(sii9234, I2C_HDMI, offset, value, mask) > +#define hdmi_readb(sii9234, offset) \ > + sii9234_readb(sii9234, I2C_HDMI, offset) > +#define tpi_writeb(sii9234, offset, value) \ > + sii9234_writeb(sii9234, I2C_TPI, offset, value) > +#define tpi_writebm(sii9234, offset, value, mask) \ > + sii9234_writebm(sii9234, I2C_TPI, offset, value, mask) > +#define tpi_readb(sii9234, offset) \ > + sii9234_readb(sii9234, I2C_TPI, offset) > + > +static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable) > +{ > + mhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0, 0x10); > + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0, 0x30); > + return sii9234_clear_error(ctx); > +} > + > +static int sii9234_cbus_reset(struct sii9234 *ctx) > +{ > + int i; i is never negative, you can make it an unsigned int. > + > + /* Reset CBUS */ > + mhl_tx_writebm(ctx, MHL_TX_SRST, ~0, 1 << 3); > + /* CBUS deglitch - 2ms */ > + msleep(T_SRC_CBUS_DEGLITCH); > + mhl_tx_writebm(ctx, MHL_TX_SRST, 0, 1 << 3); > + > + for (i = 0; i < 4; i++) { > + /* Enable WRITE_STAT interrupt for writes to all > + * 4 MSC Status registers. > + */ > + cbus_writeb(ctx, 0xE0 + i, 0xF2); > + /* Enable SET_INT interrupt for writes to all > + * 4 MSC Interrupt registers. > + */ > + cbus_writeb(ctx, 0xF0 + i, 0xF2); > + } > + > + return sii9234_clear_error(ctx); > +} > + > +/* require to chek mhl imformation of samsung in cbus_init_register*/ You need a space before */, here and everywhere else in the driver. > +static int sii9234_cbus_init(struct sii9234 *ctx) > +{ > + cbus_writeb(ctx, 0x07, 0xF2); > + cbus_writeb(ctx, 0x40, 0x03); > + cbus_writeb(ctx, 0x42, 0x06); > + cbus_writeb(ctx, 0x36, 0x0C); > + cbus_writeb(ctx, 0x3D, 0xFD); > + cbus_writeb(ctx, 0x1C, 0x01); > + cbus_writeb(ctx, 0x1D, 0x0F); > + cbus_writeb(ctx, 0x44, 0x02); > + /* Setup our devcap */ > + /* To meet cts 6.3.10.1 spec */ > + cbus_writeb(ctx, CBUS_DEVCAP_DEV_STATE, 0x00); > + /* mhl version 1.1 */ > + cbus_writeb(ctx, CBUS_DEVCAP_MHL_VERSION, 0x11); > + cbus_writeb(ctx, CBUS_DEVCAP_DEV_CAT, 0x02); > + cbus_writeb(ctx, CBUS_DEVCAP_ADOPTER_ID_H, 0x01); > + cbus_writeb(ctx, CBUS_DEVCAP_ADOPTER_ID_L, 0x41); > + /* YCbCr444, RGB444 */ > + cbus_writeb(ctx, CBUS_DEVCAP_VID_LINK_MODE, 0x03); > + cbus_writeb(ctx, CBUS_DEVCAP_VIDEO_TYPE, 0); > + cbus_writeb(ctx, CBUS_DEVCAP_LOG_DEV_MAP, 0x80); > + cbus_writeb(ctx, CBUS_DEVCAP_BANDWIDTH, 0x0F); > + cbus_writeb(ctx, CBUS_DEVCAP_DEV_FEATURE_FLAG, 0x07); > + cbus_writeb(ctx, CBUS_DEVCAP_DEVICE_ID_H, 0x0); > + cbus_writeb(ctx, CBUS_DEVCAP_DEVICE_ID_L, 0x0); > + cbus_writeb(ctx, CBUS_DEVCAP_SCRATCHPAD_SIZE, 0x10); > + cbus_writeb(ctx, CBUS_DEVCAP_INT_STAT_SIZE, 0x33); > + cbus_writeb(ctx, CBUS_DEVCAP_RESERVED, 0); > + cbus_writebm(ctx, 0x31, 0x0C, 0x0C); > + cbus_writeb(ctx, 0x30, 0x01); > + cbus_writebm(ctx, 0x3C, 0x30, 0x38); > + cbus_writebm(ctx, 0x22, 0x0D, 0x0F); > + cbus_writebm(ctx, 0x2E, 0x15, 0x15); > + cbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0); > + cbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0); > + > + return sii9234_clear_error(ctx); > +} > + > +static void force_usb_id_switch_open(struct sii9234 *ctx) > +{ > + /*Disable CBUS discovery */ You need a space after /*, here and everywhere else in the driver. > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01); > + /*Force USB ID switch to open */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR); > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86); > + /*Force upstream HPD to 0 when not in MHL mode. */ > + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30); > +} > + > +static void release_usb_id_switch_open(struct sii9234 *ctx) > +{ > + msleep(T_SRC_CBUS_FLOAT); > + /* clear USB ID switch to open */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR); > + /* Enable CBUS discovery */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01); > +} > + > +static int sii9234_power_init(struct sii9234 *ctx) > +{ > + /* Force the SiI9234 into the D0 state. */ > + tpi_writeb(ctx, TPI_DPD_REG, 0x3F); > + /* Enable TxPLL Clock */ > + hdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01); > + /* Enable Tx Clock Path & Equalizer */ > + hdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15); > + /* Power Up TMDS */ > + mhl_tx_writeb(ctx, 0x08, 0x35); > + return sii9234_clear_error(ctx); > +} > + > +static int sii9234_hdmi_init(struct sii9234 *ctx) > +{ > + /* Analog PLL Control bits 5:4 = 2b00 as per char. team. */ > + hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1); No magic value, please define macros for register bits. > + /* PLL Calrefsel */ All those comments won't be needed once you replace numerical values with explicitly named macros. > + hdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03); > + /* VCO Cal */ > + hdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20); > + /* Auto EQ */ > + hdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A); > + /* Auto EQ */ > + hdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A); > + /* Auto EQ */ > + hdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA); > + /* Auto EQ */ > + hdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA); > + /* Auto EQ */ > + hdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA); > + /* Manual zone */ > + hdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0); > + /* PLL Mode Value */ > + hdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00); > + mhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34); > + hdmi_writeb(ctx, 0x45, 0x44); > + /* Rx PLL BW ~ 4MHz */ > + hdmi_writeb(ctx, 0x31, 0x0A); > + /* Analog PLL Control * bits 5:4 = 2b00 as per char. team. */ > + hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1); > + > + return sii9234_clear_error(ctx); > +} > + > +static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx) > +{ > + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0); > + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC); > + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB); > + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C); > + return sii9234_clear_error(ctx); > +} > + > +static int sii9234_reset(struct sii9234 *ctx) > +{ > + int ret; > + > + sii9234_clear_error(ctx); > + > + ret = sii9234_power_init(ctx); > + if (ret < 0) > + return ret; > + ret = sii9234_cbus_reset(ctx); > + if (ret < 0) > + return ret; > + ret = sii9234_hdmi_init(ctx); > + if (ret < 0) > + return ret; > + ret = sii9234_mhl_tx_ctl_int(ctx); > + if (ret < 0) > + return ret; > + > + /* Enable HDCP Compliance safety */ > + mhl_tx_writeb(ctx, 0x2B, 0x01); > + /* CBUS discovery cycle time for each drive and float = 150us */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06); > + /* Clear bit 6 (reg_skip_rgnd) */ > + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7) /* Reserved */ > + | 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS); > + /* Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel */ > + /* 1.8V CBUS VTH & GND threshold */ > + /*To meet CTS 3.3.7.2 spec */ > + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77); > + /* set bit 2 and 3, which is Initiator Timeout */ > + cbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, 0x0C); > + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0); > + /* RGND & single discovery attempt (RGND blocking) */ > + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT | > + DVRFLT_SEL | SINGLE_ATT); > + /* Use VBUS path of discovery state machine */ > + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0); > + /* 0x92[3] sets the CBUS / ID switch */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR); > + /* To allow RGND engine to operate correctly. > + * When moving the chip from D2 to D0 (power up, init regs) > + * the values should be > + * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k > + * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be > + * set for 10k (default) > + * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default) > + */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86); > + /* change from CC to 8C to match 5K */ > + /*To meet CTS 3.3.72 spec */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C); > + /* Configure the interrupt as active high */ > + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06); > + > + msleep(25); > + > + /* release usb_id switch */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR); > + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27); > + > + ret = sii9234_clear_error(ctx); > + if (ret < 0) > + return ret; > + ret = sii9234_cbus_init(ctx); > + if (ret < 0) > + return ret; > + > + /* Enable Auto soft reset on SCDT = 0 */ > + mhl_tx_writeb(ctx, 0x05, 0x04); > + /* HDMI Transcode mode enable */ > + mhl_tx_writeb(ctx, 0x0D, 0x1C); > + mhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG, > + RGND_READY_MASK | CBUS_LKOUT_MASK | > + MHL_DISC_FAIL_MASK | MHL_EST_MASK); > + mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60); > + > + /* this point is very importand before megsure RGND impedance */ s/megsure/measuring/ > + force_usb_id_switch_open(ctx); > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0); > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03); > + release_usb_id_switch_open(ctx); > + /*end of this */ End of what ? > + > + /* Force upstream HPD to 0 when not in MHL mode */ > + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5); > + mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4); > + > + return sii9234_clear_error(ctx); > +} > + > +static int sii9234_goto_d3(struct sii9234 *ctx) > +{ > + int ret; > + > + dev_dbg(ctx->dev, "sii9234: detection started d3\n"); > + > + ret = sii9234_reset(ctx); > + if (ret < 0) > + goto exit; > + > + hdmi_writeb(ctx, 0x01, 0x03); > + tpi_writebm(ctx, TPI_DPD_REG, 0, 1); > + /* I2C above is expected to fail because power goes down */ > + sii9234_clear_error(ctx); > + > + ctx->state = ST_D3; > + > + return 0; > + exit: > + dev_err(ctx->dev, "%s failed\n", __func__); > + return -1; > +} > + > +#define sii9234_hw_on(sii9234) \ > + regulator_enable((sii9234)->vcc_supply) > + > +static void sii9234_hw_off(struct sii9234 *ctx) > +{ > + gpiod_set_value(ctx->gpio_reset, 0); > + usleep_range(10000, 20000); > + gpiod_set_value(ctx->gpio_reset, 1); > + regulator_disable(ctx->vcc_supply); > + gpiod_set_value(ctx->gpio_reset, 0); > +} > + > +static void sii9234_hw_reset(struct sii9234 *ctx) > +{ > + gpiod_set_value(ctx->gpio_reset, 0); > + usleep_range(10000, 20000); > + gpiod_set_value(ctx->gpio_reset, 1); > +} > + > +static void sii9234_cable_in(struct sii9234 *ctx) > +{ > + int ret; > + > + mutex_lock(&ctx->lock); > + if (ctx->state != ST_OFF) > + goto unlock; > + ret = sii9234_hw_on(ctx); > + if (ret < 0) > + goto unlock; > + > + sii9234_hw_reset(ctx); > + sii9234_goto_d3(ctx); > + enable_irq(to_i2c_client(ctx->dev)->irq); That looks like a hack. You should enable/disable IRQs in the SII9234, there should be no need to enable/disable them in the SoC IRQ controller. If there's really a need to do so, you should document why. > + > +unlock: > + mutex_unlock(&ctx->lock); > +} > + > +static void sii9234_cable_out(struct sii9234 *ctx) > +{ > + mutex_lock(&ctx->lock); > + > + if (ctx->state == ST_OFF) > + goto unlock; > + > + disable_irq(to_i2c_client(ctx->dev)->irq); > + tpi_writeb(ctx, TPI_DPD_REG, 0); > + /*turn on&off hpd festure for only QCT HDMI */ Some of your comments start with a capitalized word, others don't. I'd capitalize them all for consistency. > + sii9234_hw_off(ctx); > + > + ctx->state = ST_OFF; > + > +unlock: > + mutex_unlock(&ctx->lock); > +} > + > +static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx) > +{ > + int value; > + > + if (ctx->state == ST_D3) { > + int ret; > + > + dev_dbg(ctx->dev, "RGND_READY_INT\n"); > + sii9234_hw_reset(ctx); > + > + ret = sii9234_reset(ctx); > + if (ret < 0) { > + dev_err(ctx->dev, "sii9234_reset() failed\n"); > + return ST_FAILURE; > + } > + > + return ST_RGND_INIT; > + } > + > + /* got interrupt in inappropriate state */ > + if (ctx->state != ST_RGND_INIT) > + return ST_FAILURE; > + > + value = mhl_tx_readb(ctx, MHL_TX_STAT2_REG); > + if (sii9234_clear_error(ctx)) > + return ST_FAILURE; > + > + if ((value & RGND_INTP_MASK) != RGND_INTP_1K) { > + dev_warn(ctx->dev, "RGND is not 1k\n"); > + return ST_RGND_INIT; > + } > + dev_dbg(ctx->dev, "RGND 1K!!\n"); > + /* After applying RGND patch, there is some issue > + * about discovry failure > + * This point is add to fix that problem > + */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C); > + mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77); > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05); > + if (sii9234_clear_error(ctx)) > + return ST_FAILURE; > + > + usleep_range(T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC, > + T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC); > + > + return ST_RGND_1K; > +} > + > +static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx) > +{ > + dev_dbg(ctx->dev, "mhl est interrupt\n"); > + > + /* discovery override */ > + mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10); > + /* increase DDC translation layer timer (byte mode) */ > + cbus_writeb(ctx, 0x07, 0x32); > + cbus_writebm(ctx, 0x44, ~0, 1 << 1); > + /* Keep the discovery enabled. Need RGND interrupt */ > + mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1); > + mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, > + RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK); > + > + if (sii9234_clear_error(ctx)) > + return ST_FAILURE; > + > + return ST_MHL_ESTABLISHED; > +} > + > +static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx) > +{ > + int value; > + > + value = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG); > + if (sii9234_clear_error(ctx)) > + return ST_FAILURE; > + > + if (value & SET_HPD_DOWNSTREAM) { > + dev_info(ctx->dev, "HPD High\n"); You don't want to spam the kernel log every time a cable is plugged or unplugged. Use dev_dbg() if you want to keep those messages for debugging, or remove them altogether. > + /* Downstream HPD High, Enable TMDS */ > + sii9234_tmds_control(ctx, true); > + /*turn on&off hpd festure for only QCT HDMI */ I'm not sure what the comment relates to as there's no line of code after it. > + } else { > + dev_info(ctx->dev, "HPD Low\n"); > + /* Downstream HPD Low, Disable TMDS */ > + sii9234_tmds_control(ctx, false); > + } > + > + return ctx->state; > +} > + > +static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx) > +{ > + int value; > + > + /* work_around code to handle worng interrupt */ s/worng/wrong/ > + if (ctx->state != ST_RGND_1K) { > + dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n"); > + return ST_FAILURE; > + } > + value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG); > + if (value < 0) > + return ST_FAILURE; > + > + if (value & RSEN_STATUS) { > + dev_info(ctx->dev, "MHL cable connected.. RSEN High\n"); > + return ST_RSEN_HIGH; > + } > + dev_info(ctx->dev, "RSEN lost\n"); Ditto, dev_dbg() > + /* Once RSEN loss is confirmed,we need to check > + * based on cable status and chip power status,whether > + * it is SINK Loss(HDMI cable not connected, TV Off) > + * or MHL cable disconnection > + * TODO: Define the below mhl_disconnection() > + */ > + msleep(T_SRC_RXSENSE_DEGLITCH); > + value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG); > + if (value < 0) > + return ST_FAILURE; > + dev_dbg(ctx->dev, "sys_stat: %x\n", value); > + > + if (value & RSEN_STATUS) { > + dev_info(ctx->dev, "RSEN recovery\n"); > + return ST_RSEN_HIGH; > + } > + dev_info(ctx->dev, "RSEN Really LOW\n"); Same here, and everywhere else in the driver. > + /*To meet CTS 3.3.22.2 spec */ > + sii9234_tmds_control(ctx, false); > + force_usb_id_switch_open(ctx); > + release_usb_id_switch_open(ctx); > + > + return ST_FAILURE; > +} > + > +static irqreturn_t sii9234_irq_thread(int irq, void *data) > +{ > + struct sii9234 *ctx = data; > + int intr1, intr4; > + int intr1_en, intr4_en; > + int cbus_intr1, cbus_intr2; > + > + dev_dbg(ctx->dev, "%s\n", __func__); > + > + msleep(30); If this is really needed you should add a comment to explain why. > + mutex_lock(&ctx->lock); > + > + intr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG); > + intr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG); > + intr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG); > + intr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG); > + cbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG); > + cbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG); > + > + if (sii9234_clear_error(ctx)) > + goto done; > + > + dev_dbg(ctx->dev, "irq %02x/%02x %02x/%02x %02x/%02x\n", > + intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2); > + > + if (intr4 & RGND_READY_INT) > + ctx->state = sii9234_rgnd_ready_irq(ctx); > + if (intr1 & RSEN_CHANGE_INT) > + ctx->state = sii9234_rsen_change(ctx); > + if (intr4 & MHL_EST_INT) > + ctx->state = sii9234_mhl_established(ctx); > + if (intr1 & HPD_CHANGE_INT) > + ctx->state = sii9234_hpd_change(ctx); > + if (intr4 & CBUS_LKOUT_INT) > + ctx->state = ST_FAILURE; > + if (intr4 & MHL_DISC_FAIL_INT) > + ctx->state = ST_FAILURE_DISCOVERY; > + > + done: > + /* clean interrupt status and pending flags */ > + mhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1); > + mhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4); > + cbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF); > + cbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF); > + cbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1); > + cbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2); > + > + sii9234_clear_error(ctx); > + > + if (ctx->state == ST_FAILURE) { > + dev_info(ctx->dev, "try to reset after failure\n"); > + sii9234_hw_reset(ctx); > + sii9234_goto_d3(ctx); > + } > + > + if (ctx->state == ST_FAILURE_DISCOVERY) { > + dev_err(ctx->dev, "discovery failed, no power for MHL?\n"); > + tpi_writebm(ctx, TPI_DPD_REG, 0, 1); > + ctx->state = ST_D3; > + } > + > + mutex_unlock(&ctx->lock); > + > + return IRQ_HANDLED; > +} > + > + > +static int sii9234_init_resources(struct sii9234 *ctx, > + struct i2c_client *client) > +{ > + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); > + > + if (!ctx->dev->of_node) { > + dev_err(ctx->dev, "not DT device\n"); > + return -ENODEV; > + } > + > + ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_HIGH); > + if (IS_ERR(ctx->gpio_reset)) { > + dev_err(ctx->dev, "failed to get reset gpio from DT\n"); > + return PTR_ERR(ctx->gpio_reset); > + } > + > + ctx->vcc_supply = devm_regulator_get(ctx->dev, "vcc"); > + if (IS_ERR(ctx->vcc_supply)) { > + dev_err(ctx->dev, "failed to acquire regulator vcc\n"); > + return PTR_ERR(ctx->vcc_supply); > + } > + > + ctx->client[I2C_MHL] = client; > + > + ctx->client[I2C_TPI] = i2c_new_dummy(adapter, 0x7A >> 1); Please define macros for the secondary I2C addresses instead of using numerical values directly. > + if (!ctx->client[I2C_TPI]) { > + dev_err(ctx->dev, "failed to create TPI client\n"); > + return -ENODEV; > + } > + > + ctx->client[I2C_HDMI] = i2c_new_dummy(adapter, 0x92 >> 1); > + if (!ctx->client[I2C_HDMI]) { > + dev_err(ctx->dev, "failed to create HDMI RX client\n"); > + goto fail_tpi; > + } > + > + ctx->client[I2C_CBUS] = i2c_new_dummy(adapter, 0xC8 >> 1); > + if (!ctx->client[I2C_CBUS]) { > + dev_err(ctx->dev, "failed to create CBUS client\n"); > + goto fail_hdmi; > + } > + > + return 0; > + > +fail_hdmi: > + i2c_unregister_device(ctx->client[I2C_HDMI]); > +fail_tpi: > + i2c_unregister_device(ctx->client[I2C_TPI]); > + > + return -ENODEV; > +} > + > +static void sii9234_deinit_resources(struct sii9234 *ctx) > +{ > + i2c_unregister_device(ctx->client[I2C_CBUS]); > + i2c_unregister_device(ctx->client[I2C_HDMI]); > + i2c_unregister_device(ctx->client[I2C_TPI]); > +} > + > +static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct sii9234, bridge); > +} > + > +static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge, > + const struct drm_display_mode *mode) > +{ > + struct sii9234 *ctx = bridge_to_sii9234(bridge); > + > + if (mode->clock > MHL1_MAX_CLK) > + return MODE_CLOCK_HIGH; > + > + return MODE_OK; > +} > + > +static const struct drm_bridge_funcs sii9234_bridge_funcs = { > + .mode_valid = sii9234_mode_valid, > +}; > + > +static int sii9234_mhl_tx_i2c_probe(struct i2c_client *client, > + const struct i2c_device_id *id) > +{ > + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); > + struct sii9234 *ctx; > + struct device *dev = &client->dev; > + int ret; > + > + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); > + if (!ctx) > + return -ENOMEM; > + > + ctx->dev = dev; > + > + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { > + dev_err(dev, "I2C adapter lacks SMBUS feature\n"); > + return -EIO; > + } > + > + mutex_init(&ctx->lock); > + > + ret = sii9234_init_resources(ctx, client); > + if (ret < 0) { > + dev_err(&client->dev, "failed to initialize sii9234 resources\n"); No need for an error message here as all error paths in sii9234_init_resources() print a message already. > + return ret; > + } > + ret = sii9234_hw_on(ctx); > + if (ret) { > + dev_err(&client->dev, "failed to enable power\n"); > + goto err_resource; > + } > + sii9234_hw_reset(ctx); > + > + if (!client->irq) { > + dev_err(dev, "no irq provided\n"); > + return -EINVAL; No need for clean up in the error path ? You can just move this check with the I2C functionality check to avoid the need to clean up. > + } > + irq_set_status_flags(client->irq, IRQ_NOAUTOEN); > + ret = devm_request_threaded_irq(dev, client->irq, NULL, > + sii9234_irq_thread, > + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > + "sii9234", ctx); > + if (ret < 0) { > + dev_err(dev, "failed to install IRQ handler\n"); > + return ret; > + } > + > + i2c_set_clientdata(client, ctx); > + > + ctx->bridge.funcs = &sii9234_bridge_funcs; > + ctx->bridge.of_node = dev->of_node; > + drm_bridge_add(&ctx->bridge); > + > + sii9234_cable_in(ctx); > + > + return 0; > + > +err_resource: > + sii9234_deinit_resources(ctx); > + > + return ret; > +} > + > +static int sii9234_mhl_tx_i2c_remove(struct i2c_client *client) > +{ > + struct sii9234 *ctx = i2c_get_clientdata(client); > + > + sii9234_cable_out(ctx); > + drm_bridge_remove(&ctx->bridge); > + sii9234_deinit_resources(ctx); > + > + return 0; > +} > + > +static const struct of_device_id sii9234_dt_match[] = { > + { .compatible = "sil,sii9234" }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, sii9234_dt_match); > + > +static const struct i2c_device_id sii9234_id[] = { > + { "SII9234", 0 }, > + { }, > +}; > + Nitpicking, I'd move this blank line after MODULE_DEVICE_TABLE(i2c, sii9234_id); > +MODULE_DEVICE_TABLE(i2c, sii9234_id); > +static struct i2c_driver sii9234_driver = { > + .driver = { > + .name = "sii9234", > + .owner = THIS_MODULE, > + .of_match_table = of_match_ptr(sii9234_dt_match), As the driver requires OF support the of_match_ptr() macro isn't needed. > + }, > + .probe = sii9234_mhl_tx_i2c_probe, > + .remove = sii9234_mhl_tx_i2c_remove, > + .id_table = sii9234_id, > +}; > + > +module_i2c_driver(sii9234_driver); > +MODULE_LICENSE("GPL"); -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-03 10:24 ` Laurent Pinchart @ 2017-08-04 6:55 ` Marek Szyprowski 2017-08-10 14:51 ` Laurent Pinchart 0 siblings, 1 reply; 23+ messages in thread From: Marek Szyprowski @ 2017-08-04 6:55 UTC (permalink / raw) To: Laurent Pinchart, Maciej Purski Cc: mark.rutland, devicetree, linux-samsung-soc, b.zolnierkie, dri-devel, robh+dt, krzk Hi Laurent, Thanks for your detailed comments. Maciej resurrected some orphaned code, which is still useful today (Tomasz has left Samsung a few years ago). I'm not sure we will be able to answer all your questions without deep investigation, especially about the driver operation details, but we will try. On 2017-08-03 12:24, Laurent Pinchart wrote: > Hi Maciej, > > Thank you for the patch. > > On Thursday 03 Aug 2017 09:45:22 Maciej Purski wrote: >> SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. >> It is controlled via I2C bus. Its interaction with other >> devices in video pipeline is performed mainly on HW level. >> The only interaction it does on device driver level is >> filtering-out unsupported video modes, it exposes drm_bridge >> interface to perform this operation. >> >> This patch is based on the code refactored by Tomasz Stanislawski >> <t.stanislaws@samsung.com>, which was initially developed by: >> Adam Hampson <ahampson@sta.samsung.com> >> Erik Gilling <konkers@android.com> >> Shankar Bandal <shankar.b@samsung.com> >> Dharam Kumar <dharam.kr@samsung.com> >> >> Signed-off-by: Maciej Purski <m.purski@samsung.com> >> --- >> .../devicetree/bindings/display/bridge/sii9234.txt | 20 + >> drivers/gpu/drm/bridge/Kconfig | 8 + >> drivers/gpu/drm/bridge/Makefile | 1 + >> drivers/gpu/drm/bridge/sii9234.c | 1019 +++++++++++++++++ >> 4 files changed, 1048 insertions(+) >> create mode 100644 >> Documentation/devicetree/bindings/display/bridge/sii9234.txt create mode >> 100644 drivers/gpu/drm/bridge/sii9234.c >> >> diff --git a/Documentation/devicetree/bindings/display/bridge/sii9234.txt >> b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file >> mode 100644 >> index 0000000..2cdf286 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt > DT reviewers might ask you to submit DT bindings as a separate patch. > >> @@ -0,0 +1,20 @@ >> +SiI9234 Mobile HD Link Transmitter >> + >> +Required properties: >> +- compatible : "sil,sii9234". >> +- reg : I2C address for TPI interface, use 0x39 >> +- vcc-supply : regulator that supplies the chip > Is there a single power supply only ? Transceivers usually have at least one > digital and one analog power supply. Acording to the schematic there are four power supplies used for SII9234 MHL chip in Trats2 board: VSIL_1.2A, VSIL_1.2C, VCC_3.3V_MHL and VCC_1.8V_MHL. First two are derived directly from VSIL_1.2 signal, which is modeled as a fixed regulator. The latter two are derived directly from VBAT using some level converter, which is controlled by the same GPIO pin as VSIL fixed regulator. Any idea how this should be represented better in device tree instead of having single vcc-supply? > >> +- interrupts, interrupt-parent: interrupt specifier of INT pin >> +- reset-gpios: gpio specifier of RESET pin > Is this mandatory to connect the reset pin to the SoC ? IMHO yes, the chip has to be reset during the initialization procedure and doesn't work properly without reset. > > [...] Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-04 6:55 ` Marek Szyprowski @ 2017-08-10 14:51 ` Laurent Pinchart 2017-08-11 7:00 ` Marek Szyprowski 0 siblings, 1 reply; 23+ messages in thread From: Laurent Pinchart @ 2017-08-10 14:51 UTC (permalink / raw) To: Marek Szyprowski Cc: Maciej Purski, mark.rutland, devicetree, linux-samsung-soc, b.zolnierkie, dri-devel, robh+dt, krzk Hi Marek, On Friday 04 Aug 2017 08:55:55 Marek Szyprowski wrote: > Hi Laurent, > > Thanks for your detailed comments. Maciej resurrected some orphaned code, > which is still useful today (Tomasz has left Samsung a few years ago). > I'm not sure we will be able to answer all your questions without deep > investigation, especially about the driver operation details, but we > will try. Thank you. > On 2017-08-03 12:24, Laurent Pinchart wrote: > > On Thursday 03 Aug 2017 09:45:22 Maciej Purski wrote: > >> SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. > >> It is controlled via I2C bus. Its interaction with other > >> devices in video pipeline is performed mainly on HW level. > >> The only interaction it does on device driver level is > >> filtering-out unsupported video modes, it exposes drm_bridge > >> interface to perform this operation. > >> > >> This patch is based on the code refactored by Tomasz Stanislawski > >> <t.stanislaws@samsung.com>, which was initially developed by: > >> Adam Hampson <ahampson@sta.samsung.com> > >> Erik Gilling <konkers@android.com> > >> Shankar Bandal <shankar.b@samsung.com> > >> Dharam Kumar <dharam.kr@samsung.com> > >> > >> Signed-off-by: Maciej Purski <m.purski@samsung.com> > >> --- > >> > >> .../devicetree/bindings/display/bridge/sii9234.txt | 20 + > >> drivers/gpu/drm/bridge/Kconfig | 8 + > >> drivers/gpu/drm/bridge/Makefile | 1 + > >> drivers/gpu/drm/bridge/sii9234.c | 1019 +++++++++++++ > >> 4 files changed, 1048 insertions(+) > >> create mode 100644 > >> > >> Documentation/devicetree/bindings/display/bridge/sii9234.txt create mode > >> 100644 drivers/gpu/drm/bridge/sii9234.c > >> > >> diff --git a/Documentation/devicetree/bindings/display/bridge/sii9234.txt > >> b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file > >> mode 100644 > >> index 0000000..2cdf286 > >> --- /dev/null > >> +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt > > > > DT reviewers might ask you to submit DT bindings as a separate patch. > > > >> @@ -0,0 +1,20 @@ > >> +SiI9234 Mobile HD Link Transmitter > >> + > >> +Required properties: > >> +- compatible : "sil,sii9234". > >> +- reg : I2C address for TPI interface, use 0x39 > >> +- vcc-supply : regulator that supplies the chip > > > > Is there a single power supply only ? Transceivers usually have at least > > one digital and one analog power supply. > > Acording to the schematic there are four power supplies used for SII9234 > MHL chip in Trats2 board: VSIL_1.2A, VSIL_1.2C, VCC_3.3V_MHL and > VCC_1.8V_MHL. First two are derived directly from VSIL_1.2 signal, which is > modeled as a fixed regulator. The latter two are derived directly from VBAT > using some level converter, which is controlled by the same GPIO pin as VSIL > fixed regulator. Any idea how this should be represented better in device > tree instead of having single vcc-supply? Without access to the documentation I can only guess, but it looks like VSIL_1.2A and VSIL_1.2C are supposed to be powered from the same power supply rail, possibly with different filters. I think they can be grouped together from a DT binding point of view. The last two supplies seem independent. We should thus probably model this as three separate supplies. It would be useful to check in the SII9234 datasheet what power sequence the chip expects. Is there any chance you could find that document ? > >> +- interrupts, interrupt-parent: interrupt specifier of INT pin > >> +- reset-gpios: gpio specifier of RESET pin > > > > Is this mandatory to connect the reset pin to the SoC ? > > IMHO yes, the chip has to be reset during the initialization procedure > and doesn't work properly without reset. OK, I have no issue making the property mandatory then. -- Regards, Laurent Pinchart ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-10 14:51 ` Laurent Pinchart @ 2017-08-11 7:00 ` Marek Szyprowski 2017-08-11 8:59 ` Laurent Pinchart 2017-08-11 9:00 ` Laurent Pinchart 0 siblings, 2 replies; 23+ messages in thread From: Marek Szyprowski @ 2017-08-11 7:00 UTC (permalink / raw) To: Laurent Pinchart Cc: Maciej Purski, mark.rutland, devicetree, linux-samsung-soc, b.zolnierkie, dri-devel, robh+dt, krzk Hi Laurent, On 2017-08-10 16:51, Laurent Pinchart wrote: > Hi Marek, > > On Friday 04 Aug 2017 08:55:55 Marek Szyprowski wrote: >> Hi Laurent, >> >> Thanks for your detailed comments. Maciej resurrected some orphaned code, >> which is still useful today (Tomasz has left Samsung a few years ago). >> I'm not sure we will be able to answer all your questions without deep >> investigation, especially about the driver operation details, but we >> will try. > Thank you. > >> On 2017-08-03 12:24, Laurent Pinchart wrote: >>> On Thursday 03 Aug 2017 09:45:22 Maciej Purski wrote: >>>> SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. >>>> It is controlled via I2C bus. Its interaction with other >>>> devices in video pipeline is performed mainly on HW level. >>>> The only interaction it does on device driver level is >>>> filtering-out unsupported video modes, it exposes drm_bridge >>>> interface to perform this operation. >>>> >>>> This patch is based on the code refactored by Tomasz Stanislawski >>>> <t.stanislaws@samsung.com>, which was initially developed by: >>>> Adam Hampson <ahampson@sta.samsung.com> >>>> Erik Gilling <konkers@android.com> >>>> Shankar Bandal <shankar.b@samsung.com> >>>> Dharam Kumar <dharam.kr@samsung.com> >>>> >>>> Signed-off-by: Maciej Purski <m.purski@samsung.com> >>>> --- >>>> >>>> .../devicetree/bindings/display/bridge/sii9234.txt | 20 + >>>> drivers/gpu/drm/bridge/Kconfig | 8 + >>>> drivers/gpu/drm/bridge/Makefile | 1 + >>>> drivers/gpu/drm/bridge/sii9234.c | 1019 +++++++++++++ >>>> 4 files changed, 1048 insertions(+) >>>> create mode 100644 >>>> >>>> Documentation/devicetree/bindings/display/bridge/sii9234.txt create mode >>>> 100644 drivers/gpu/drm/bridge/sii9234.c >>>> >>>> diff --git a/Documentation/devicetree/bindings/display/bridge/sii9234.txt >>>> b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file >>>> mode 100644 >>>> index 0000000..2cdf286 >>>> --- /dev/null >>>> +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt >>> DT reviewers might ask you to submit DT bindings as a separate patch. >>> >>>> @@ -0,0 +1,20 @@ >>>> +SiI9234 Mobile HD Link Transmitter >>>> + >>>> +Required properties: >>>> +- compatible : "sil,sii9234". >>>> +- reg : I2C address for TPI interface, use 0x39 >>>> +- vcc-supply : regulator that supplies the chip >>> Is there a single power supply only ? Transceivers usually have at least >>> one digital and one analog power supply. >> Acording to the schematic there are four power supplies used for SII9234 >> MHL chip in Trats2 board: VSIL_1.2A, VSIL_1.2C, VCC_3.3V_MHL and >> VCC_1.8V_MHL. First two are derived directly from VSIL_1.2 signal, which is >> modeled as a fixed regulator. The latter two are derived directly from VBAT >> using some level converter, which is controlled by the same GPIO pin as VSIL >> fixed regulator. Any idea how this should be represented better in device >> tree instead of having single vcc-supply? > Without access to the documentation I can only guess, but it looks like > VSIL_1.2A and VSIL_1.2C are supposed to be powered from the same power supply > rail, possibly with different filters. I think they can be grouped together > from a DT binding point of view. The last two supplies seem independent. We > should thus probably model this as three separate supplies. Okay, I see no problem adding support for all those three supplies, but I was wondering how to model them in the device tree, because from the software perspective ALL power supplies needed by this chip are enabled by a single GPIO line switch. I see 3 possible solutions: 1. Keep only single vcc supply for now and use fixed gpio regulator for it as a provider. Add a comment that it fact it provides 3 different power signals. 2. Extend fixed gpio regulator driver and bindings so it will be possible to have more than one fixed regulator controlled by the same gpio pin. 3. Model VCC_3.3V_MHL and VCC_1.8V_MHL providers as "vctrl-regulator" and use this VSIL_1.2 as control voltage for them. Which one do you prefer? > It would be useful to check in the SII9234 datasheet what power sequence the > chip expects. Is there any chance you could find that document ? We have access only to the parts of the SII9234 documentation now and there is no such information there. >>>> +- interrupts, interrupt-parent: interrupt specifier of INT pin >>>> +- reset-gpios: gpio specifier of RESET pin >>> Is this mandatory to connect the reset pin to the SoC ? >> IMHO yes, the chip has to be reset during the initialization procedure >> and doesn't work properly without reset. > OK, I have no issue making the property mandatory then. Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-11 7:00 ` Marek Szyprowski @ 2017-08-11 8:59 ` Laurent Pinchart 2017-08-11 9:00 ` Laurent Pinchart 1 sibling, 0 replies; 23+ messages in thread From: Laurent Pinchart @ 2017-08-11 8:59 UTC (permalink / raw) To: Marek Szyprowski Cc: mark.rutland, devicetree, linux-samsung-soc, b.zolnierkie, Mark Brown, dri-devel, Maciej Purski, robh+dt, krzk Hi Marek, (CC'ing Mark Brown) On Friday 11 Aug 2017 09:00:00 Marek Szyprowski wrote: > On 2017-08-10 16:51, Laurent Pinchart wrote: > > On Friday 04 Aug 2017 08:55:55 Marek Szyprowski wrote: > >> Hi Laurent, > >> > >> Thanks for your detailed comments. Maciej resurrected some orphaned code, > >> which is still useful today (Tomasz has left Samsung a few years ago). > >> I'm not sure we will be able to answer all your questions without deep > >> investigation, especially about the driver operation details, but we > >> will try. > > > > Thank you. > > > >> On 2017-08-03 12:24, Laurent Pinchart wrote: > >>> On Thursday 03 Aug 2017 09:45:22 Maciej Purski wrote: > >>>> SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. > >>>> It is controlled via I2C bus. Its interaction with other > >>>> devices in video pipeline is performed mainly on HW level. > >>>> The only interaction it does on device driver level is > >>>> filtering-out unsupported video modes, it exposes drm_bridge > >>>> interface to perform this operation. > >>>> > >>>> This patch is based on the code refactored by Tomasz Stanislawski > >>>> <t.stanislaws@samsung.com>, which was initially developed by: > >>>> Adam Hampson <ahampson@sta.samsung.com> > >>>> Erik Gilling <konkers@android.com> > >>>> Shankar Bandal <shankar.b@samsung.com> > >>>> Dharam Kumar <dharam.kr@samsung.com> > >>>> > >>>> Signed-off-by: Maciej Purski <m.purski@samsung.com> > >>>> --- > >>>> > >>>> .../devicetree/bindings/display/bridge/sii9234.txt | 20 + > >>>> drivers/gpu/drm/bridge/Kconfig | 8 + > >>>> drivers/gpu/drm/bridge/Makefile | 1 + > >>>> drivers/gpu/drm/bridge/sii9234.c | 1019 ++++++++++ > >>>> 4 files changed, 1048 insertions(+) > >>>> create mode 100644 > >>>> > >>>> Documentation/devicetree/bindings/display/bridge/sii9234.txt create > >>>> mode > >>>> 100644 drivers/gpu/drm/bridge/sii9234.c > >>>> > >>>> diff --git > >>>> a/Documentation/devicetree/bindings/display/bridge/sii9234.txt > >>>> b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file > >>>> mode 100644 > >>>> index 0000000..2cdf286 > >>>> --- /dev/null > >>>> +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt > >>> > >>> DT reviewers might ask you to submit DT bindings as a separate patch. > >>> > >>>> @@ -0,0 +1,20 @@ > >>>> +SiI9234 Mobile HD Link Transmitter > >>>> + > >>>> +Required properties: > >>>> +- compatible : "sil,sii9234". > >>>> +- reg : I2C address for TPI interface, use 0x39 > >>>> +- vcc-supply : regulator that supplies the chip > >>> > >>> Is there a single power supply only ? Transceivers usually have at least > >>> one digital and one analog power supply. > >> > >> Acording to the schematic there are four power supplies used for SII9234 > >> MHL chip in Trats2 board: VSIL_1.2A, VSIL_1.2C, VCC_3.3V_MHL and > >> VCC_1.8V_MHL. First two are derived directly from VSIL_1.2 signal, which > >> is modeled as a fixed regulator. The latter two are derived directly from > >> VBAT using some level converter, which is controlled by the same GPIO pin > >> as VSIL fixed regulator. Any idea how this should be represented better > >> in device tree instead of having single vcc-supply? > > > > Without access to the documentation I can only guess, but it looks like > > VSIL_1.2A and VSIL_1.2C are supposed to be powered from the same power > > supply rail, possibly with different filters. I think they can be grouped > > together from a DT binding point of view. The last two supplies seem > > independent. We should thus probably model this as three separate > > supplies. > > Okay, I see no problem adding support for all those three supplies, but > I was wondering how to model them in the device tree, because from the > software perspective ALL power supplies needed by this chip are enabled by a > single GPIO line switch. > > I see 3 possible solutions: > 1. Keep only single vcc supply for now and use fixed gpio regulator for it > as a provider. Add a comment that it fact it provides 3 different power > signals. > 2. Extend fixed gpio regulator driver and bindings so it will be possible to > have more than one fixed regulator controlled by the same gpio pin. > 3. Model VCC_3.3V_MHL and VCC_1.8V_MHL providers as "vctrl-regulator" and > use this VSIL_1.2 as control voltage for them. > > Which one do you prefer? 2 would be best I think, but that's more work. Mark, what do you think ? > > It would be useful to check in the SII9234 datasheet what power sequence > > the chip expects. Is there any chance you could find that document ? > > We have access only to the parts of the SII9234 documentation now and > there is no > such information there. > > >>>> +- interrupts, interrupt-parent: interrupt specifier of INT pin > >>>> +- reset-gpios: gpio specifier of RESET pin > >>> > >>> Is this mandatory to connect the reset pin to the SoC ? > >> > >> IMHO yes, the chip has to be reset during the initialization procedure > >> and doesn't work properly without reset. > > > > OK, I have no issue making the property mandatory then. > > Best regards -- Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-11 7:00 ` Marek Szyprowski 2017-08-11 8:59 ` Laurent Pinchart @ 2017-08-11 9:00 ` Laurent Pinchart 2017-08-14 16:35 ` Mark Brown 1 sibling, 1 reply; 23+ messages in thread From: Laurent Pinchart @ 2017-08-11 9:00 UTC (permalink / raw) To: Marek Szyprowski Cc: mark.rutland, devicetree, linux-samsung-soc, b.zolnierkie, Mark Brown, dri-devel, Maciej Purski, robh+dt, krzk Hi Marek, (now CC'ing Mark Brown with his correct e-mail address) On Friday 11 Aug 2017 09:00:00 Marek Szyprowski wrote: > On 2017-08-10 16:51, Laurent Pinchart wrote: > > On Friday 04 Aug 2017 08:55:55 Marek Szyprowski wrote: > >> Hi Laurent, > >> > >> Thanks for your detailed comments. Maciej resurrected some orphaned code, > >> which is still useful today (Tomasz has left Samsung a few years ago). > >> I'm not sure we will be able to answer all your questions without deep > >> investigation, especially about the driver operation details, but we > >> will try. > > > > Thank you. > > > >> On 2017-08-03 12:24, Laurent Pinchart wrote: > >>> On Thursday 03 Aug 2017 09:45:22 Maciej Purski wrote: > >>>> SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0. > >>>> It is controlled via I2C bus. Its interaction with other > >>>> devices in video pipeline is performed mainly on HW level. > >>>> The only interaction it does on device driver level is > >>>> filtering-out unsupported video modes, it exposes drm_bridge > >>>> interface to perform this operation. > >>>> > >>>> This patch is based on the code refactored by Tomasz Stanislawski > >>>> <t.stanislaws@samsung.com>, which was initially developed by: > >>>> Adam Hampson <ahampson@sta.samsung.com> > >>>> Erik Gilling <konkers@android.com> > >>>> Shankar Bandal <shankar.b@samsung.com> > >>>> Dharam Kumar <dharam.kr@samsung.com> > >>>> > >>>> Signed-off-by: Maciej Purski <m.purski@samsung.com> > >>>> --- > >>>> > >>>> .../devicetree/bindings/display/bridge/sii9234.txt | 20 + > >>>> drivers/gpu/drm/bridge/Kconfig | 8 + > >>>> drivers/gpu/drm/bridge/Makefile | 1 + > >>>> drivers/gpu/drm/bridge/sii9234.c | 1019 ++++++++++ > >>>> 4 files changed, 1048 insertions(+) > >>>> create mode 100644 > >>>> > >>>> Documentation/devicetree/bindings/display/bridge/sii9234.txt create > >>>> mode > >>>> 100644 drivers/gpu/drm/bridge/sii9234.c > >>>> > >>>> diff --git > >>>> a/Documentation/devicetree/bindings/display/bridge/sii9234.txt > >>>> b/Documentation/devicetree/bindings/display/bridge/sii9234.txt new file > >>>> mode 100644 > >>>> index 0000000..2cdf286 > >>>> --- /dev/null > >>>> +++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt > >>> > >>> DT reviewers might ask you to submit DT bindings as a separate patch. > >>> > >>>> @@ -0,0 +1,20 @@ > >>>> +SiI9234 Mobile HD Link Transmitter > >>>> + > >>>> +Required properties: > >>>> +- compatible : "sil,sii9234". > >>>> +- reg : I2C address for TPI interface, use 0x39 > >>>> +- vcc-supply : regulator that supplies the chip > >>> > >>> Is there a single power supply only ? Transceivers usually have at least > >>> one digital and one analog power supply. > >> > >> Acording to the schematic there are four power supplies used for SII9234 > >> MHL chip in Trats2 board: VSIL_1.2A, VSIL_1.2C, VCC_3.3V_MHL and > >> VCC_1.8V_MHL. First two are derived directly from VSIL_1.2 signal, which > >> is modeled as a fixed regulator. The latter two are derived directly from > >> VBAT using some level converter, which is controlled by the same GPIO pin > >> as VSIL fixed regulator. Any idea how this should be represented better > >> in device tree instead of having single vcc-supply? > > > > Without access to the documentation I can only guess, but it looks like > > VSIL_1.2A and VSIL_1.2C are supposed to be powered from the same power > > supply rail, possibly with different filters. I think they can be grouped > > together from a DT binding point of view. The last two supplies seem > > independent. We should thus probably model this as three separate > > supplies. > > Okay, I see no problem adding support for all those three supplies, but > I was wondering how to model them in the device tree, because from the > software perspective ALL power supplies needed by this chip are enabled by a > single GPIO line switch. > > I see 3 possible solutions: > 1. Keep only single vcc supply for now and use fixed gpio regulator for it > as a provider. Add a comment that it fact it provides 3 different power > signals. > 2. Extend fixed gpio regulator driver and bindings so it will be possible to > have more than one fixed regulator controlled by the same gpio pin. > 3. Model VCC_3.3V_MHL and VCC_1.8V_MHL providers as "vctrl-regulator" and > use this VSIL_1.2 as control voltage for them. > > Which one do you prefer? 2 would be best I think, but that's more work. Mark, what do you think ? > > It would be useful to check in the SII9234 datasheet what power sequence > > the chip expects. Is there any chance you could find that document ? > > We have access only to the parts of the SII9234 documentation now and > there is no > such information there. > > >>>> +- interrupts, interrupt-parent: interrupt specifier of INT pin > >>>> +- reset-gpios: gpio specifier of RESET pin > >>> > >>> Is this mandatory to connect the reset pin to the SoC ? > >> > >> IMHO yes, the chip has to be reset during the initialization procedure > >> and doesn't work properly without reset. > > > > OK, I have no issue making the property mandatory then. > > Best regards -- Regards, Laurent Pinchart _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-11 9:00 ` Laurent Pinchart @ 2017-08-14 16:35 ` Mark Brown 0 siblings, 0 replies; 23+ messages in thread From: Mark Brown @ 2017-08-14 16:35 UTC (permalink / raw) To: Laurent Pinchart Cc: Marek Szyprowski, Maciej Purski, mark.rutland, devicetree, linux-samsung-soc, b.zolnierkie, dri-devel, robh+dt, krzk [-- Attachment #1: Type: text/plain, Size: 1332 bytes --] On Fri, Aug 11, 2017 at 12:00:43PM +0300, Laurent Pinchart wrote: > (now CC'ing Mark Brown with his correct e-mail address) This is a *lot* of quoted discussion... > > Okay, I see no problem adding support for all those three supplies, but > > I was wondering how to model them in the device tree, because from the > > software perspective ALL power supplies needed by this chip are enabled by a > > single GPIO line switch. > > I see 3 possible solutions: > > 1. Keep only single vcc supply for now and use fixed gpio regulator for it > > as a provider. Add a comment that it fact it provides 3 different power > > signals. > > 2. Extend fixed gpio regulator driver and bindings so it will be possible to > > have more than one fixed regulator controlled by the same gpio pin. > > 3. Model VCC_3.3V_MHL and VCC_1.8V_MHL providers as "vctrl-regulator" and > > use this VSIL_1.2 as control voltage for them. > > Which one do you prefer? > 2 would be best I think, but that's more work. Mark, what do you think ? Just model them all individually and let the regulator framework sort it out. It's got the concept of shared GPIO enables already so you should be able to just describe the system directly and the framework will figure things out, and even if it didn't there should be no need to change any of the bindings here. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver 2017-08-03 7:45 ` [PATCH 1/2] drm/bridge: " Maciej Purski 2017-08-03 10:24 ` Laurent Pinchart @ 2017-08-03 19:36 ` kbuild test robot [not found] ` <1501746323-5254-2-git-send-email-m.purski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 1 sibling, 1 reply; 23+ messages in thread From: kbuild test robot @ 2017-08-03 19:36 UTC (permalink / raw) Cc: kbuild-all, dri-devel, devicetree, linux-samsung-soc, mark.rutland, b.zolnierkie, krzk, Maciej Purski, robh+dt, Laurent.pinchart Hi Maciej, [auto build test WARNING on drm/drm-next] [also build test WARNING on v4.13-rc3 next-20170803] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Maciej-Purski/add-Silicon-Image-SiI9234-driver/20170803-200255 base: git://people.freedesktop.org/~airlied/linux.git drm-next coccinelle warnings: (new ones prefixed by >>) >> drivers/gpu/drm/bridge/sii9234.c:1010:3-8: No need to set .owner here. The core will do it. Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation ^ permalink raw reply [flat|nested] 23+ messages in thread
[parent not found: <1501746323-5254-2-git-send-email-m.purski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>]
* [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings [not found] ` <1501746323-5254-2-git-send-email-m.purski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> @ 2017-08-03 19:36 ` kbuild test robot 2017-08-12 22:43 ` [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver kbuild test robot 1 sibling, 0 replies; 23+ messages in thread From: kbuild test robot @ 2017-08-03 19:36 UTC (permalink / raw) Cc: kbuild-all-JC7UmRfGjtg, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8, b.zolnierkie-Sze3O3UU22JBDgjK7y7TUQ, krzk-DgEjT+Ai2ygdnm+yROfE0A, Maciej Purski, robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw drivers/gpu/drm/bridge/sii9234.c:1010:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Fixes: 9d5babbeda8a ("drm/bridge: add Silicon Image SiI9234 driver") CC: Maciej Purski <m.purski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> Signed-off-by: Fengguang Wu <fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> --- sii9234.c | 1 - 1 file changed, 1 deletion(-) --- a/drivers/gpu/drm/bridge/sii9234.c +++ b/drivers/gpu/drm/bridge/sii9234.c @@ -1007,7 +1007,6 @@ MODULE_DEVICE_TABLE(i2c, sii9234_id); static struct i2c_driver sii9234_driver = { .driver = { .name = "sii9234", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(sii9234_dt_match), }, .probe = sii9234_mhl_tx_i2c_probe, -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver [not found] ` <1501746323-5254-2-git-send-email-m.purski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2017-08-03 19:36 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot @ 2017-08-12 22:43 ` kbuild test robot 1 sibling, 0 replies; 23+ messages in thread From: kbuild test robot @ 2017-08-12 22:43 UTC (permalink / raw) Cc: kbuild-all-JC7UmRfGjtg, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, devicetree-u79uwXL29TY76Z2rM5mHXA, linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8, b.zolnierkie-Sze3O3UU22JBDgjK7y7TUQ, krzk-DgEjT+Ai2ygdnm+yROfE0A, Maciej Purski, robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw [-- Attachment #1: Type: text/plain, Size: 8562 bytes --] Hi Maciej, [auto build test ERROR on drm/drm-next] [also build test ERROR on v4.13-rc4 next-20170811] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Maciej-Purski/add-Silicon-Image-SiI9234-driver/20170803-200255 base: git://people.freedesktop.org/~airlied/linux.git drm-next config: i386-randconfig-h0-08130402 (attached as .config) compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901 reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): drivers/gpu//drm/bridge/sii9234.c: In function 'sii9234_mode_valid': drivers/gpu//drm/bridge/sii9234.c:909:18: warning: unused variable 'ctx' [-Wunused-variable] struct sii9234 *ctx = bridge_to_sii9234(bridge); ^~~ drivers/gpu//drm/bridge/sii9234.c: In function 'sii9234_mhl_tx_i2c_probe': >> drivers/gpu//drm/bridge/sii9234.c:971:13: error: 'struct drm_bridge' has no member named 'of_node' ctx->bridge.of_node = dev->of_node; ^ In file included from include/uapi/linux/stddef.h:1:0, from include/linux/stddef.h:4, from include/uapi/linux/posix_types.h:4, from include/uapi/linux/types.h:13, from include/linux/types.h:5, from include/drm/bridge/mhl.h:18, from drivers/gpu//drm/bridge/sii9234.c:26: drivers/gpu//drm/bridge/sii9234.c: At top level: include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'strcpy' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:390:2: note: in expansion of macro 'if' if (p_size == (size_t)-1 && q_size == (size_t)-1) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:380:2: note: in expansion of macro 'if' if (p_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'kmemdup' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:378:2: note: in expansion of macro 'if' if (__builtin_constant_p(size) && p_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:369:2: note: in expansion of macro 'if' if (p_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr_inv' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:367:2: note: in expansion of macro 'if' if (__builtin_constant_p(size) && p_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:358:2: note: in expansion of macro 'if' if (p_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memchr' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:356:2: note: in expansion of macro 'if' if (__builtin_constant_p(size) && p_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:348:2: note: in expansion of macro 'if' if (p_size < size || q_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:345:3: note: in expansion of macro 'if' if (q_size < size) ^~ include/linux/compiler.h:162:4: warning: '______f' is static but declared in inline function 'memcmp' which is not static ______f = { \ ^ include/linux/compiler.h:154:23: note: in expansion of macro '__trace_if' #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) ^~~~~~~~~~ include/linux/string.h:343:3: note: in expansion of macro 'if' if (p_size < size) ^~ vim +971 drivers/gpu//drm/bridge/sii9234.c 905 906 static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge, 907 const struct drm_display_mode *mode) 908 { > 909 struct sii9234 *ctx = bridge_to_sii9234(bridge); 910 911 if (mode->clock > MHL1_MAX_CLK) 912 return MODE_CLOCK_HIGH; 913 914 return MODE_OK; 915 } 916 917 static const struct drm_bridge_funcs sii9234_bridge_funcs = { 918 .mode_valid = sii9234_mode_valid, 919 }; 920 921 static int sii9234_mhl_tx_i2c_probe(struct i2c_client *client, 922 const struct i2c_device_id *id) 923 { 924 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 925 struct sii9234 *ctx; 926 struct device *dev = &client->dev; 927 int ret; 928 929 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 930 if (!ctx) 931 return -ENOMEM; 932 933 ctx->dev = dev; 934 935 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 936 dev_err(dev, "I2C adapter lacks SMBUS feature\n"); 937 return -EIO; 938 } 939 940 mutex_init(&ctx->lock); 941 942 ret = sii9234_init_resources(ctx, client); 943 if (ret < 0) { 944 dev_err(&client->dev, "failed to initialize sii9234 resources\n"); 945 return ret; 946 } 947 ret = sii9234_hw_on(ctx); 948 if (ret) { 949 dev_err(&client->dev, "failed to enable power\n"); 950 goto err_resource; 951 } 952 sii9234_hw_reset(ctx); 953 954 if (!client->irq) { 955 dev_err(dev, "no irq provided\n"); 956 return -EINVAL; 957 } 958 irq_set_status_flags(client->irq, IRQ_NOAUTOEN); 959 ret = devm_request_threaded_irq(dev, client->irq, NULL, 960 sii9234_irq_thread, 961 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 962 "sii9234", ctx); 963 if (ret < 0) { 964 dev_err(dev, "failed to install IRQ handler\n"); 965 return ret; 966 } 967 968 i2c_set_clientdata(client, ctx); 969 970 ctx->bridge.funcs = &sii9234_bridge_funcs; > 971 ctx->bridge.of_node = dev->of_node; 972 drm_bridge_add(&ctx->bridge); 973 974 sii9234_cable_in(ctx); 975 976 return 0; 977 978 err_resource: 979 sii9234_deinit_resources(ctx); 980 981 return ret; 982 } 983 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 25180 bytes --] ^ permalink raw reply [flat|nested] 23+ messages in thread
[parent not found: <CGME20170803074541eucas1p2b054d4853a98819fc42f19f7cae7f419@eucas1p2.samsung.com>]
* [PATCH 2/2] ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board [not found] ` <CGME20170803074541eucas1p2b054d4853a98819fc42f19f7cae7f419@eucas1p2.samsung.com> @ 2017-08-03 7:45 ` Maciej Purski 2017-08-03 19:20 ` Krzysztof Kozlowski 0 siblings, 1 reply; 23+ messages in thread From: Maciej Purski @ 2017-08-03 7:45 UTC (permalink / raw) To: dri-devel, devicetree, linux-samsung-soc Cc: airlied, robh+dt, mark.rutland, architt, a.hajda, Laurent.pinchart, krzk, b.zolnierkie, Maciej Purski This patch adds HDMI and Sil9234 MHL converter to Trats2 board. Based on previous work by: Tomasz Stanislawski <t.stanislaws@samsung.com> Signed-off-by: Maciej Purski <m.purski@samsung.com> --- arch/arm/boot/dts/exynos4412-trats2.dts | 93 +++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 35e9b94..39940f6 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -97,6 +97,16 @@ gpio = <&gpj0 5 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + vsil: voltage-regulator-vsil { + compatible = "regulator-fixed"; + regulator-name = "HDMI_5V"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>; + enable-active-high; + vin-supply = <&buck7_reg>; + }; }; gpio-keys { @@ -229,6 +239,34 @@ }; }; + i2c-mhl { + compatible = "i2c-gpio"; + gpios = <&gpf0 4 GPIO_ACTIVE_HIGH &gpf0 6 GPIO_ACTIVE_HIGH>; + i2c-gpio,delay-us = <100>; + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&i2c_mhl_bus>; + pinctrl-names = "default"; + status = "okay"; + + sii9234: sii9234@39 { + compatible = "sil,sii9234"; + vcc-supply = <&vsil>; + reset-gpios = <&gpf3 4 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpf3>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + reg = <0x39>; + + + port { + mhl_to_hdmi: endpoint { + remote-endpoint = <&hdmi_to_mhl>; + }; + }; + }; + }; + camera: camera { pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; pinctrl-names = "default"; @@ -522,6 +560,31 @@ status = "okay"; }; +&hdmi { + hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_hpd>; + hdmi-en-supply = <&vsil>; + vdd-supply = <&ldo3_reg>; + vdd_osc-supply = <&ldo4_reg>; + vdd_pll-supply = <&ldo3_reg>; + ddc = <&i2c_5>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + hdmi_to_mhl: endpoint { + remote-endpoint = <&mhl_to_hdmi>; + }; + }; + }; + +}; + &hsotg { vusb_d-supply = <&ldo15_reg>; vusb_a-supply = <&ldo12_reg>; @@ -600,6 +663,11 @@ }; }; + +&i2c_5 { + status = "okay"; +}; + &i2c_7 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; @@ -894,12 +962,20 @@ }; }; +&i2c_8 { + status = "okay"; +}; + &i2s0 { pinctrl-0 = <&i2s0_bus>; pinctrl-names = "default"; status = "okay"; }; +&mixer { + status = "okay"; +}; + &mshc_0 { num-slots = <1>; broken-cd; @@ -926,6 +1002,18 @@ pinctrl-names = "default"; pinctrl-0 = <&sleep0>; + mhl_int: mhl-int { + samsung,pins = "gpf3-5"; + samsung,pin-pud = <0>; + }; + + i2c_mhl_bus: i2c-mhl-bus { + samsung,pins = "gpf0-4", "gpf0-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + sleep0: sleep-states { PIN_SLP(gpa0-0, INPUT, NONE); PIN_SLP(gpa0-1, OUT0, NONE); @@ -1029,6 +1117,11 @@ pinctrl-names = "default"; pinctrl-0 = <&sleep1>; + hdmi_hpd: hdmi-hpd { + samsung,pins = "gpx3-7"; + samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>; + }; + sleep1: sleep-states { PIN_SLP(gpk0-0, PREV, NONE); PIN_SLP(gpk0-1, PREV, NONE); -- 2.7.4 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 2/2] ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board 2017-08-03 7:45 ` [PATCH 2/2] ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board Maciej Purski @ 2017-08-03 19:20 ` Krzysztof Kozlowski 2017-08-04 6:32 ` Marek Szyprowski 0 siblings, 1 reply; 23+ messages in thread From: Krzysztof Kozlowski @ 2017-08-03 19:20 UTC (permalink / raw) To: Maciej Purski Cc: dri-devel, devicetree, linux-samsung-soc, airlied, robh+dt, mark.rutland, architt, a.hajda, Laurent.pinchart, b.zolnierkie On Thu, Aug 03, 2017 at 09:45:23AM +0200, Maciej Purski wrote: > This patch adds HDMI and Sil9234 MHL converter to Trats2 board. Just "Add HDMI...", without this patch. Except few minor nitpicks below, looks good. After fixing I will take it once bindings got accepted. > > Based on previous work by: > Tomasz Stanislawski <t.stanislaws@samsung.com> > > Signed-off-by: Maciej Purski <m.purski@samsung.com> > --- > arch/arm/boot/dts/exynos4412-trats2.dts | 93 +++++++++++++++++++++++++++++++++ > 1 file changed, 93 insertions(+) > > diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts > index 35e9b94..39940f6 100644 > --- a/arch/arm/boot/dts/exynos4412-trats2.dts > +++ b/arch/arm/boot/dts/exynos4412-trats2.dts > @@ -97,6 +97,16 @@ > gpio = <&gpj0 5 GPIO_ACTIVE_HIGH>; > enable-active-high; > }; > + > + vsil: voltage-regulator-vsil { > + compatible = "regulator-fixed"; > + regulator-name = "HDMI_5V"; > + regulator-min-microvolt = <5000000>; > + regulator-max-microvolt = <5000000>; > + gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>; > + enable-active-high; > + vin-supply = <&buck7_reg>; I think the supply is V_BAT, not buck7. > + }; > }; > > gpio-keys { > @@ -229,6 +239,34 @@ > }; > }; > > + i2c-mhl { > + compatible = "i2c-gpio"; > + gpios = <&gpf0 4 GPIO_ACTIVE_HIGH &gpf0 6 GPIO_ACTIVE_HIGH>; > + i2c-gpio,delay-us = <100>; > + #address-cells = <1>; > + #size-cells = <0>; > + > + pinctrl-0 = <&i2c_mhl_bus>; > + pinctrl-names = "default"; > + status = "okay"; > + > + sii9234: sii9234@39 { The name of node should be rather generic (ePAPR: "The name of a node should be somewhat generic, reflecting the function of the device and not its precise programming model"). So maybe "sii9234: hdmi-bridge@39"? > + compatible = "sil,sii9234"; > + vcc-supply = <&vsil>; > + reset-gpios = <&gpf3 4 GPIO_ACTIVE_HIGH>; > + interrupt-parent = <&gpf3>; > + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; > + reg = <0x39>; > + > + One empty line instead of two. > + port { > + mhl_to_hdmi: endpoint { > + remote-endpoint = <&hdmi_to_mhl>; > + }; > + }; > + }; > + }; > + > camera: camera { > pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; > pinctrl-names = "default"; > @@ -522,6 +560,31 @@ > status = "okay"; > }; > > +&hdmi { > + hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>; > + pinctrl-names = "default"; > + pinctrl-0 = <&hdmi_hpd>; > + hdmi-en-supply = <&vsil>; > + vdd-supply = <&ldo3_reg>; > + vdd_osc-supply = <&ldo4_reg>; > + vdd_pll-supply = <&ldo3_reg>; > + ddc = <&i2c_5>; > + status = "okay"; > + > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + > + port@1 { > + reg = <1>; > + hdmi_to_mhl: endpoint { > + remote-endpoint = <&mhl_to_hdmi>; > + }; > + }; > + }; > + Unnecessary empty line. > +}; > + > &hsotg { > vusb_d-supply = <&ldo15_reg>; > vusb_a-supply = <&ldo12_reg>; > @@ -600,6 +663,11 @@ > }; > }; > > + > +&i2c_5 { > + status = "okay"; > +}; Could you describe more what is on i2c_5 and i2c_8? Is it relevant to this patch? > + > &i2c_7 { > samsung,i2c-sda-delay = <100>; > samsung,i2c-slave-addr = <0x10>; > @@ -894,12 +962,20 @@ > }; > }; > > +&i2c_8 { > + status = "okay"; > +}; > + > &i2s0 { > pinctrl-0 = <&i2s0_bus>; > pinctrl-names = "default"; > status = "okay"; > }; > > +&mixer { > + status = "okay"; > +}; > + > &mshc_0 { > num-slots = <1>; > broken-cd; > @@ -926,6 +1002,18 @@ > pinctrl-names = "default"; > pinctrl-0 = <&sleep0>; > > + mhl_int: mhl-int { > + samsung,pins = "gpf3-5"; > + samsung,pin-pud = <0>; Please use defines from dt-bindings/pinctrl/samsung.h > + }; > + > + i2c_mhl_bus: i2c-mhl-bus { > + samsung,pins = "gpf0-4", "gpf0-6"; > + samsung,pin-function = <2>; > + samsung,pin-pud = <1>; > + samsung,pin-drv = <0>; The same. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/2] ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board 2017-08-03 19:20 ` Krzysztof Kozlowski @ 2017-08-04 6:32 ` Marek Szyprowski 2017-08-04 6:44 ` Krzysztof Kozlowski 0 siblings, 1 reply; 23+ messages in thread From: Marek Szyprowski @ 2017-08-04 6:32 UTC (permalink / raw) To: Krzysztof Kozlowski, Maciej Purski Cc: dri-devel, devicetree, linux-samsung-soc, airlied, robh+dt, mark.rutland, architt, a.hajda, Laurent.pinchart, b.zolnierkie Hi Krzysztof, On 2017-08-03 21:20, Krzysztof Kozlowski wrote: > On Thu, Aug 03, 2017 at 09:45:23AM +0200, Maciej Purski wrote: >> This patch adds HDMI and Sil9234 MHL converter to Trats2 board. > Just "Add HDMI...", without this patch. > > Except few minor nitpicks below, looks good. After fixing I will take it > once bindings got accepted. > >> Based on previous work by: >> Tomasz Stanislawski <t.stanislaws@samsung.com> >> >> Signed-off-by: Maciej Purski <m.purski@samsung.com> >> --- >> arch/arm/boot/dts/exynos4412-trats2.dts | 93 +++++++++++++++++++++++++++++++++ >> 1 file changed, 93 insertions(+) >> >> diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts >> index 35e9b94..39940f6 100644 >> --- a/arch/arm/boot/dts/exynos4412-trats2.dts >> +++ b/arch/arm/boot/dts/exynos4412-trats2.dts >> @@ -97,6 +97,16 @@ >> gpio = <&gpj0 5 GPIO_ACTIVE_HIGH>; >> enable-active-high; >> }; >> + >> + vsil: voltage-regulator-vsil { >> + compatible = "regulator-fixed"; >> + regulator-name = "HDMI_5V"; >> + regulator-min-microvolt = <5000000>; >> + regulator-max-microvolt = <5000000>; >> + gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>; >> + enable-active-high; >> + vin-supply = <&buck7_reg>; > I think the supply is V_BAT, not buck7. Well, according to the the schematic, VSIL is derived from VCC_SUB_2.0V (buck7) by the RP114K121D-TR chip, which is controlled by gpl0-4 (HDMI_EN) pin. The only thing that has to be fixed is the voltage value for that regulator. VSIL is 1.2V and regulator-name should be adjusted too. The HDMI_V5 name and voltage value seems to be copy/paste error done long time ago... >> + }; >> }; >> >> gpio-keys { >> @@ -229,6 +239,34 @@ >> }; >> }; >> >> + i2c-mhl { >> + compatible = "i2c-gpio"; >> + gpios = <&gpf0 4 GPIO_ACTIVE_HIGH &gpf0 6 GPIO_ACTIVE_HIGH>; >> + i2c-gpio,delay-us = <100>; >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + pinctrl-0 = <&i2c_mhl_bus>; >> + pinctrl-names = "default"; >> + status = "okay"; >> + >> + sii9234: sii9234@39 { > The name of node should be rather generic (ePAPR: "The name of a node > should be somewhat generic, reflecting the function of the device and > not its precise programming model"). > > So maybe "sii9234: hdmi-bridge@39"? > >> + compatible = "sil,sii9234"; >> + vcc-supply = <&vsil>; >> + reset-gpios = <&gpf3 4 GPIO_ACTIVE_HIGH>; >> + interrupt-parent = <&gpf3>; >> + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; >> + reg = <0x39>; >> + >> + > One empty line instead of two. > >> + port { >> + mhl_to_hdmi: endpoint { >> + remote-endpoint = <&hdmi_to_mhl>; >> + }; >> + }; >> + }; >> + }; >> + >> camera: camera { >> pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>; >> pinctrl-names = "default"; >> @@ -522,6 +560,31 @@ >> status = "okay"; >> }; >> >> +&hdmi { >> + hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>; >> + pinctrl-names = "default"; >> + pinctrl-0 = <&hdmi_hpd>; >> + hdmi-en-supply = <&vsil>; >> + vdd-supply = <&ldo3_reg>; >> + vdd_osc-supply = <&ldo4_reg>; >> + vdd_pll-supply = <&ldo3_reg>; >> + ddc = <&i2c_5>; >> + status = "okay"; >> + >> + ports { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + port@1 { >> + reg = <1>; >> + hdmi_to_mhl: endpoint { >> + remote-endpoint = <&mhl_to_hdmi>; >> + }; >> + }; >> + }; >> + > Unnecessary empty line. > >> +}; >> + >> &hsotg { >> vusb_d-supply = <&ldo15_reg>; >> vusb_a-supply = <&ldo12_reg>; >> @@ -600,6 +663,11 @@ >> }; >> }; >> >> + >> +&i2c_5 { >> + status = "okay"; >> +}; > Could you describe more what is on i2c_5 and i2c_8? Is it relevant to > this patch? Yes. i2c_5 is used for HDMI DDC and i2c_8 is used for HDMI_PHY. None of the other exynos*.dts, which enable HDMI has any comment on them... >> + >> &i2c_7 { >> samsung,i2c-sda-delay = <100>; >> samsung,i2c-slave-addr = <0x10>; >> @@ -894,12 +962,20 @@ >> }; >> }; >> >> +&i2c_8 { >> + status = "okay"; >> +}; >> + >> &i2s0 { >> pinctrl-0 = <&i2s0_bus>; >> pinctrl-names = "default"; >> status = "okay"; >> }; >> >> +&mixer { >> + status = "okay"; >> +}; >> + >> &mshc_0 { >> num-slots = <1>; >> broken-cd; >> @@ -926,6 +1002,18 @@ >> pinctrl-names = "default"; >> pinctrl-0 = <&sleep0>; >> >> + mhl_int: mhl-int { >> + samsung,pins = "gpf3-5"; >> + samsung,pin-pud = <0>; > Please use defines from dt-bindings/pinctrl/samsung.h > >> + }; >> + >> + i2c_mhl_bus: i2c-mhl-bus { >> + samsung,pins = "gpf0-4", "gpf0-6"; >> + samsung,pin-function = <2>; >> + samsung,pin-pud = <1>; >> + samsung,pin-drv = <0>; > The same. > Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/2] ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board 2017-08-04 6:32 ` Marek Szyprowski @ 2017-08-04 6:44 ` Krzysztof Kozlowski 0 siblings, 0 replies; 23+ messages in thread From: Krzysztof Kozlowski @ 2017-08-04 6:44 UTC (permalink / raw) To: Marek Szyprowski Cc: Maciej Purski, dri-devel, devicetree, linux-samsung-soc, airlied, robh+dt, mark.rutland, architt, a.hajda, Laurent.pinchart, Bartłomiej Żołnierkiewicz On Fri, Aug 4, 2017 at 8:32 AM, Marek Szyprowski <m.szyprowski@samsung.com> wrote: > > Hi Krzysztof, > > > On 2017-08-03 21:20, Krzysztof Kozlowski wrote: >> >> On Thu, Aug 03, 2017 at 09:45:23AM +0200, Maciej Purski wrote: >>> >>> This patch adds HDMI and Sil9234 MHL converter to Trats2 board. >> >> Just "Add HDMI...", without this patch. >> >> Except few minor nitpicks below, looks good. After fixing I will take it >> once bindings got accepted. >> >>> Based on previous work by: >>> Tomasz Stanislawski <t.stanislaws@samsung.com> >>> >>> Signed-off-by: Maciej Purski <m.purski@samsung.com> >>> --- >>> arch/arm/boot/dts/exynos4412-trats2.dts | 93 +++++++++++++++++++++++++++++++++ >>> 1 file changed, 93 insertions(+) >>> >>> diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts >>> index 35e9b94..39940f6 100644 >>> --- a/arch/arm/boot/dts/exynos4412-trats2.dts >>> +++ b/arch/arm/boot/dts/exynos4412-trats2.dts >>> @@ -97,6 +97,16 @@ >>> gpio = <&gpj0 5 GPIO_ACTIVE_HIGH>; >>> enable-active-high; >>> }; >>> + >>> + vsil: voltage-regulator-vsil { >>> + compatible = "regulator-fixed"; >>> + regulator-name = "HDMI_5V"; >>> + regulator-min-microvolt = <5000000>; >>> + regulator-max-microvolt = <5000000>; >>> + gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>; >>> + enable-active-high; >>> + vin-supply = <&buck7_reg>; >> >> I think the supply is V_BAT, not buck7. > > > Well, according to the the schematic, VSIL is derived from VCC_SUB_2.0V > (buck7) by the RP114K121D-TR chip, which is controlled by gpl0-4 (HDMI_EN) > pin. > The only thing that has to be fixed is the voltage value for that regulator. > VSIL is 1.2V and regulator-name should be adjusted too. The HDMI_V5 name > and voltage value seems to be copy/paste error done long time ago... > OK, thanks for explanation. (...) >> >> Could you describe more what is on i2c_5 and i2c_8? Is it relevant to >> this patch? > > > Yes. i2c_5 is used for HDMI DDC and i2c_8 is used for HDMI_PHY. None of > the other exynos*.dts, which enable HDMI has any comment on them... Actually now I see that this information can be get from the source (see i2c_8 in exyos4.dtsi and here i2c_5 is used in hdmi node as ddc). Still it would be nice to see this information for example in commit message. Best regards, Krzysztof > > >>> + >>> &i2c_7 { >>> samsung,i2c-sda-delay = <100>; >>> samsung,i2c-slave-addr = <0x10>; >>> @@ -894,12 +962,20 @@ >>> }; >>> }; >>> +&i2c_8 { >>> + status = "okay"; >>> +}; >>> + >>> &i2s0 { >>> pinctrl-0 = <&i2s0_bus>; >>> pinctrl-names = "default"; >>> status = "okay"; >>> }; >>> +&mixer { >>> + status = "okay"; >>> +}; >>> + >>> &mshc_0 { >>> num-slots = <1>; >>> broken-cd; >>> @@ -926,6 +1002,18 @@ >>> pinctrl-names = "default"; >>> pinctrl-0 = <&sleep0>; >>> + mhl_int: mhl-int { >>> + samsung,pins = "gpf3-5"; >>> + samsung,pin-pud = <0>; >> >> Please use defines from dt-bindings/pinctrl/samsung.h >> >>> + }; >>> + >>> + i2c_mhl_bus: i2c-mhl-bus { >>> + samsung,pins = "gpf0-4", "gpf0-6"; >>> + samsung,pin-function = <2>; >>> + samsung,pin-pud = <1>; >>> + samsung,pin-drv = <0>; >> >> The same. >> > > Best regards > -- > Marek Szyprowski, PhD > Samsung R&D Institute Poland > ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v4 1/3] drm/bridge: add support for sn65dsi86 bridge driver
@ 2018-04-27 9:39 Sandeep Panda
[not found] ` <1524821982-2778-2-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
0 siblings, 1 reply; 23+ messages in thread
From: Sandeep Panda @ 2018-04-27 9:39 UTC (permalink / raw)
To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: ryadav-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda,
abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
nganji-sgV2jX0FEOL9JmXXK+q4OQ, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
hoegsberg-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
chandanu-sgV2jX0FEOL9JmXXK+q4OQ
Add support for TI's sn65dsi86 dsi2edp bridge chip.
The chip converts DSI transmitted signal to eDP signal,
which is fed to the connected eDP panel.
This chip can be controlled via either i2c interface or
dsi interface. Currently in driver all the control registers
are being accessed through i2c interface only.
Also as of now HPD support has not been added to bridge
chip driver.
Changes in v1:
- Split the dt-bindings and the driver support into separate patches
(Andrzej Hajda).
- Use of gpiod APIs to parse and configure gpios instead of obsolete ones
(Andrzej Hajda).
- Use macros to define the register offsets (Andrzej Hajda).
Changes in v2:
- Separate out edp panel specific HW resource handling from bridge
driver and create a separate edp panel drivers to handle panel
specific mode information and HW resources (Sean Paul).
- Replace pr_* APIs to DRM_* APIs to log error or debug information
(Sean Paul).
- Remove some of the unnecessary structure/variable from driver (Sean
Paul).
- Rename the function and structure prefix "sn65dsi86" to "ti_sn_bridge"
(Sean Paul / Rob Herring).
- Remove most of the hard-coding and modified the bridge init sequence
based on current mode (Sean Paul).
- Remove the existing function to retrieve the EDID data and
implemented this as an i2c_adapter and use drm_get_edid() (Sean Paul).
- Remove the dummy irq handler implementation, will add back the
proper irq handling later (Sean Paul).
- Capture the required enable gpios in a single array based on dt entry
instead of having individual descriptor for each gpio (Sean Paul).
Changes in v3:
- Remove usage of irq_gpio and replace it as "interrupts" property (Rob
Herring).
- Remove the unnecessary header file inclusions (Sean Paul).
- Rearrange the header files in alphabetical order (Sean Paul).
- Use regmap interface to perform i2c transactions.
- Update Copyright/License field and address other review comments
(Jordan Crouse).
Changes in v4:
- Update License/Copyright (Sean Paul).
- Add Kconfig and Makefile changes (Sean Paul).
- Drop i2c gpio handling from this bridge driver, since i2c sda/scl gpios
will be handled by i2c master.
- Remove unnecessary goto statements (Sean Paul).
- Add mutex lock to power_ctrl API to avoid race conditions (Sean
Paul).
- Add support to parse reference clk frequency from dt(optional).
- Update the bridge chip enable/disable sequence.
Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
---
drivers/gpu/drm/bridge/Kconfig | 9 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/ti-sn65dsi86.c | 721 ++++++++++++++++++++++++++++++++++
3 files changed, 731 insertions(+)
create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.c
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 3b99d5a..8153150 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -108,6 +108,15 @@ config DRM_TI_TFP410
---help---
Texas Instruments TFP410 DVI/HDMI Transmitter driver
+config DRM_TI_SN65DSI86
+ tristate "TI SN65DSI86 DSI to eDP bridge"
+ depends on OF
+ select DRM_KMS_HELPER
+ select REGMAP_I2C
+ select DRM_PANEL
+ ---help---
+ Texas Instruments SN65DSI86 DSI to eDP Bridge driver
+
source "drivers/gpu/drm/bridge/analogix/Kconfig"
source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 373eb28..3711be8 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -12,4 +12,5 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
new file mode 100644
index 0000000..28a4be8
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -0,0 +1,721 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define SN_BRIDGE_REVISION_ID 0x2
+
+/* Link Training specific registers */
+#define SN_DEVICE_REV_REG 0x08
+#define SN_REFCLK_FREQ_REG 0x0A
+#define SN_DSI_LANES_REG 0x10
+#define SN_DSIA_CLK_FREQ_REG 0x12
+#define SN_ENH_FRAME_REG 0x5A
+#define SN_SSC_CONFIG_REG 0x93
+#define SN_DATARATE_CONFIG_REG 0x94
+#define SN_PLL_ENABLE_REG 0x0D
+#define SN_SCRAMBLE_CONFIG_REG 0x95
+#define SN_AUX_WDATA0_REG 0x64
+#define SN_AUX_ADDR_19_16_REG 0x74
+#define SN_AUX_ADDR_15_8_REG 0x75
+#define SN_AUX_ADDR_7_0_REG 0x76
+#define SN_AUX_LENGTH_REG 0x77
+#define SN_AUX_CMD_REG 0x78
+#define SN_ML_TX_MODE_REG 0x96
+/* video config specific registers */
+#define SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG 0x20
+#define SN_CHA_ACTIVE_LINE_LENGTH_HIGH_REG 0x21
+#define SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG 0x24
+#define SN_CHA_VERTICAL_DISPLAY_SIZE_HIGH_REG 0x25
+#define SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG 0x2C
+#define SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG 0x2D
+#define SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG 0x30
+#define SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG 0x31
+#define SN_CHA_HORIZONTAL_BACK_PORCH_REG 0x34
+#define SN_CHA_VERTICAL_BACK_PORCH_REG 0x36
+#define SN_CHA_HORIZONTAL_FRONT_PORCH_REG 0x38
+#define SN_CHA_VERTICAL_FRONT_PORCH_REG 0x3A
+#define SN_DATA_FORMAT_REG 0x5B
+
+#define MIN_DSI_CLK_FREQ_MHZ 40
+#define SN_DEFAULT_REF_CLK_KHZ 19200
+
+/* fudge factor required to account for 8b/10b encoding */
+#define DP_CLK_FUDGE_NUM 10
+#define DP_CLK_FUDGE_DEN 8
+
+#define DPPLL_CLK_SRC_REFCLK 0
+#define DPPLL_CLK_SRC_DSICLK 1
+
+#define SN_DSIA_REFCLK_OFFSET 1
+#define SN_DSIA_LANE_OFFSET 3
+#define SN_DP_LANE_OFFSET 4
+#define SN_DP_DATA_RATE_OFFSET 5
+#define SN_TIMING_HIGH_OFFSET 8
+
+#define SN_ENABLE_VID_STREAM_BIT BIT(3)
+#define SN_DSIA_NUM_LANES_BITS (BIT(4) | BIT(3))
+#define SN_DP_NUM_LANES_BITS (BIT(5) | BIT(4))
+#define SN_DP_DATA_RATE_BITS (BIT(7) | BIT(6) | BIT(5))
+
+struct ti_sn_bridge {
+ struct device *dev;
+ struct regmap *regmap;
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+ struct device_node *host_node;
+ struct mipi_dsi_device *dsi;
+ unsigned int refclk_khz;
+ struct drm_panel *panel;
+ struct gpio_desc *enable_gpio;
+ unsigned int num_supplies;
+ struct regulator_bulk_data *supplies;
+ struct i2c_adapter *ddc;
+ unsigned int num_modes;
+ struct drm_display_mode curr_mode;
+ struct mutex lock;
+ unsigned int ctrl_ref_count;
+};
+
+static const struct regmap_range ti_sn_bridge_volatile_ranges[] = {
+ { .range_min = 0, .range_max = 0xff },
+};
+
+static const struct regmap_access_table ti_sn_bridge_volatile_table = {
+ .yes_ranges = ti_sn_bridge_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ti_sn_bridge_volatile_ranges),
+};
+
+static const struct regmap_config ti_sn_bridge_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &ti_sn_bridge_volatile_table,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int ti_sn_bridge_power_ctrl(struct ti_sn_bridge *pdata, bool enable)
+{
+ int ret = 0;
+
+ mutex_lock(&pdata->lock);
+ if (enable)
+ pdata->ctrl_ref_count++;
+ else
+ pdata->ctrl_ref_count--;
+
+ if (enable && (pdata->ctrl_ref_count == 1)) {
+ ret = regulator_bulk_enable(pdata->num_supplies,
+ pdata->supplies);
+ if (ret) {
+ DRM_ERROR("bridge regulator enable failed\n");
+ goto exit;
+ }
+
+ gpiod_set_value(pdata->enable_gpio, 1);
+ } else if (!enable && !pdata->ctrl_ref_count) {
+ gpiod_set_value(pdata->enable_gpio, 0);
+
+ regulator_bulk_disable(pdata->num_supplies, pdata->supplies);
+ } else {
+ DRM_DEBUG("ti_sn_bridge power ctrl: %d refcount: %d\n",
+ enable, pdata->ctrl_ref_count);
+ }
+
+exit:
+ mutex_unlock(&pdata->lock);
+ return ret;
+}
+
+/* Connector funcs */
+static struct ti_sn_bridge *
+connector_to_ti_sn_bridge(struct drm_connector *connector)
+{
+ return container_of(connector, struct ti_sn_bridge, connector);
+}
+
+static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector)
+{
+ struct ti_sn_bridge *pdata = connector_to_ti_sn_bridge(connector);
+ struct drm_panel *panel = pdata->panel;
+ struct edid *edid;
+
+ if (panel) {
+ DRM_DEBUG("get mode from connected drm_panel\n");
+ pdata->num_modes = drm_panel_get_modes(panel);
+ return pdata->num_modes;
+ }
+
+ /* get from EDID */
+ if (!pdata->ddc)
+ return 0;
+
+ ti_sn_bridge_power_ctrl(pdata, true);
+ edid = drm_get_edid(connector, pdata->ddc);
+ ti_sn_bridge_power_ctrl(pdata, false);
+ if (!edid)
+ return 0;
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ pdata->num_modes = drm_add_edid_modes(connector, edid);
+ drm_edid_to_eld(connector, edid);
+ kfree(edid);
+
+ return pdata->num_modes;
+}
+
+static enum drm_mode_status
+ti_sn_bridge_connector_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ /* maximum supported resolution is 4K at 60 fps */
+ if (mode->clock > 594000)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs ti_sn_bridge_connector_helper_funcs = {
+ .get_modes = ti_sn_bridge_connector_get_modes,
+ .mode_valid = ti_sn_bridge_connector_mode_valid,
+};
+
+static enum drm_connector_status
+ti_sn_bridge_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct ti_sn_bridge *pdata = connector_to_ti_sn_bridge(connector);
+
+ /**
+ * TODO: Currently if drm_panel is present, then always
+ * return the status as connected. Need to add support to detect
+ * device state for no panel(hot pluggable) scenarios.
+ */
+ if (pdata->panel)
+ return connector_status_connected;
+ else
+ return connector_status_unknown;
+}
+
+static const struct drm_connector_funcs ti_sn_bridge_connector_funcs = {
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = ti_sn_bridge_connector_detect,
+ .destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct ti_sn_bridge *bridge_to_ti_sn_bridge(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct ti_sn_bridge, bridge);
+}
+
+static int ti_sn_bridge_read_device_rev(struct ti_sn_bridge *pdata)
+{
+ unsigned int rev = 0;
+ int ret = 0;
+
+ ret = regmap_read(pdata->regmap, SN_DEVICE_REV_REG, &rev);
+ if (ret)
+ return ret;
+
+ if (rev != SN_BRIDGE_REVISION_ID) {
+ DRM_ERROR("ti_sn_bridge revision id: 0x%x mismatch\n", rev);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const char * const ti_sn_bridge_supply_names[] = {
+ "vccio",
+ "vpll",
+ "vcca",
+ "vcc",
+};
+
+static int ti_sn_bridge_parse_regulators(struct ti_sn_bridge *pdata)
+{
+ unsigned int i;
+
+ pdata->num_supplies = ARRAY_SIZE(ti_sn_bridge_supply_names);
+
+ pdata->supplies = devm_kcalloc(pdata->dev, pdata->num_supplies,
+ sizeof(*pdata->supplies), GFP_KERNEL);
+ if (!pdata->supplies)
+ return -ENOMEM;
+
+ for (i = 0; i < pdata->num_supplies; i++)
+ pdata->supplies[i].supply = ti_sn_bridge_supply_names[i];
+
+ return devm_regulator_bulk_get(pdata->dev,
+ pdata->num_supplies, pdata->supplies);
+}
+
+static int ti_sn_bridge_attach_panel(struct ti_sn_bridge *pdata)
+{
+ struct device_node *panel_node, *port, *endpoint;
+
+ pdata->panel = NULL;
+ port = of_graph_get_port_by_id(pdata->dev->of_node, 1);
+ if (port) {
+ endpoint = of_get_child_by_name(port, "endpoint");
+ of_node_put(port);
+ if (!endpoint) {
+ DRM_ERROR("no output endpoint found\n");
+ return -EINVAL;
+ }
+
+ panel_node = of_graph_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
+ if (!panel_node) {
+ DRM_ERROR("no output node found\n");
+ return -EINVAL;
+ }
+
+ pdata->panel = of_drm_find_panel(panel_node);
+ of_node_put(panel_node);
+ if (!pdata->panel) {
+ DRM_ERROR("no panel node found\n");
+ return -EINVAL;
+ }
+ drm_panel_attach(pdata->panel, &pdata->connector);
+ DRM_DEBUG("panel attached\n");
+ }
+
+ return 0;
+}
+
+static int ti_sn_bridge_attach(struct drm_bridge *bridge)
+{
+ struct mipi_dsi_host *host;
+ struct mipi_dsi_device *dsi;
+ struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+ int ret;
+ const struct mipi_dsi_device_info info = { .type = "ti_sn_bridge",
+ .channel = 0,
+ .node = NULL,
+ };
+
+ if (!bridge->encoder) {
+ DRM_ERROR("Parent encoder object not found\n");
+ return -ENODEV;
+ }
+
+ /* HPD not supported */
+ pdata->connector.polled = 0;
+
+ ret = drm_connector_init(bridge->dev, &pdata->connector,
+ &ti_sn_bridge_connector_funcs,
+ DRM_MODE_CONNECTOR_eDP);
+ if (ret) {
+ DRM_ERROR("Failed to initialize connector with drm\n");
+ return ret;
+ }
+
+ drm_connector_helper_add(&pdata->connector,
+ &ti_sn_bridge_connector_helper_funcs);
+ drm_mode_connector_attach_encoder(&pdata->connector, bridge->encoder);
+
+ host = of_find_mipi_dsi_host_by_node(pdata->host_node);
+ if (!host) {
+ DRM_ERROR("failed to find dsi host\n");
+ return -ENODEV;
+ }
+
+ dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(dsi)) {
+ DRM_ERROR("failed to create dsi device\n");
+ ret = PTR_ERR(dsi);
+ return ret;
+ }
+
+ /* TODO: setting to 4 lanes always for now */
+ dsi->lanes = 4;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+ MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ DRM_ERROR("failed to attach dsi to host\n");
+ mipi_dsi_device_unregister(dsi);
+ return ret;
+ }
+
+ pdata->dsi = dsi;
+
+ DRM_DEBUG("bridge attached\n");
+ /* attach panel to bridge */
+ ti_sn_bridge_attach_panel(pdata);
+
+ return 0;
+}
+
+static void ti_sn_bridge_mode_set(struct drm_bridge *bridge,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+
+ DRM_DEBUG("mode_set: hdisplay=%d, vdisplay=%d, vrefresh=%d, clock=%d\n",
+ adj_mode->hdisplay, adj_mode->vdisplay,
+ adj_mode->vrefresh, adj_mode->clock);
+
+ drm_mode_copy(&pdata->curr_mode, adj_mode);
+}
+
+static void ti_sn_bridge_disable(struct drm_bridge *bridge)
+{
+ struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+ struct drm_panel *panel = pdata->panel;
+
+ if (panel) {
+ drm_panel_disable(panel);
+ drm_panel_unprepare(panel);
+ }
+
+ /* disable video stream */
+ regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG,
+ SN_ENABLE_VID_STREAM_BIT, 0);
+ /* semi auto link training mode OFF */
+ regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0);
+ /* disable DP PLL */
+ regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0);
+}
+
+/* reference clk frequencies supported by the bridge in KHz */
+u32 ti_sn_bridge_ref_clk_table[] = {
+ 12000,
+ 19200,
+ 26000,
+ 27000,
+ 38400,
+};
+
+static void ti_sn_bridge_set_refclk(struct ti_sn_bridge *pdata)
+{
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(ti_sn_bridge_ref_clk_table); i++)
+ if (ti_sn_bridge_ref_clk_table[i] == pdata->refclk_khz)
+ break;
+ regmap_write(pdata->regmap, SN_REFCLK_FREQ_REG,
+ (DPPLL_CLK_SRC_REFCLK | (i << SN_DSIA_REFCLK_OFFSET)));
+}
+
+struct dp_data_rate {
+ unsigned int bit_val;
+ unsigned int dp_rate;
+};
+
+/* dp data rate supported by the bridge Mbps */
+static struct dp_data_rate ti_sn_bridge_dp_rate_table[] = {
+ {1, 1620},
+ {2, 2160},
+ {3, 2430},
+ {4, 2700},
+ {5, 3240},
+ {6, 4320},
+ {7, 5400},
+};
+
+static void ti_sn_bridge_set_dsi_dp_rate(struct ti_sn_bridge *pdata)
+{
+ unsigned int bit_rate_mhz, clk_freq_mhz, dp_rate_mhz;
+ unsigned int val = 0, i = 0;
+ struct drm_display_mode *mode = &pdata->curr_mode;
+
+ /* set DSIA clk frequency */
+ bit_rate_mhz = (mode->clock / 1000) *
+ mipi_dsi_pixel_format_to_bpp(pdata->dsi->format);
+ clk_freq_mhz = bit_rate_mhz / (pdata->dsi->lanes * 2);
+
+ /* for each increment in val, frequency increases by 5MHz */
+ val = (MIN_DSI_CLK_FREQ_MHZ / 5) +
+ (((clk_freq_mhz - MIN_DSI_CLK_FREQ_MHZ) / 5) & 0xFF);
+ regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val);
+
+ /* set DP data rate */
+ dp_rate_mhz = ((bit_rate_mhz / pdata->dsi->lanes) * DP_CLK_FUDGE_NUM) /
+ DP_CLK_FUDGE_DEN;
+ for (i = 0; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_table); i++)
+ if (ti_sn_bridge_dp_rate_table[i].dp_rate > dp_rate_mhz)
+ break;
+ if (i == ARRAY_SIZE(ti_sn_bridge_dp_rate_table))
+ i--; /* set to maximum possible */
+
+ val = ti_sn_bridge_dp_rate_table[i].bit_val << SN_DP_DATA_RATE_OFFSET;
+ regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG,
+ SN_DP_DATA_RATE_BITS, val);
+}
+
+static void ti_sn_bridge_set_video_timings(struct ti_sn_bridge *pdata)
+{
+ struct drm_display_mode *mode = &pdata->curr_mode;
+
+ regmap_write(pdata->regmap, SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG,
+ mode->hdisplay & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_ACTIVE_LINE_LENGTH_HIGH_REG,
+ (mode->hdisplay >> SN_TIMING_HIGH_OFFSET) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG,
+ mode->vdisplay & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_VERTICAL_DISPLAY_SIZE_HIGH_REG,
+ (mode->vdisplay >> SN_TIMING_HIGH_OFFSET) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG,
+ (mode->hsync_end - mode->hsync_start) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG,
+ ((mode->hsync_end - mode->hsync_start) >>
+ SN_TIMING_HIGH_OFFSET) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG,
+ (mode->vsync_end - mode->vsync_start) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG,
+ ((mode->vsync_end - mode->vsync_start) >>
+ SN_TIMING_HIGH_OFFSET) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_HORIZONTAL_BACK_PORCH_REG,
+ (mode->htotal - mode->hsync_end) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_VERTICAL_BACK_PORCH_REG,
+ (mode->vtotal - mode->vsync_end) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_HORIZONTAL_FRONT_PORCH_REG,
+ (mode->hsync_start - mode->hdisplay) & 0xFF);
+ regmap_write(pdata->regmap, SN_CHA_VERTICAL_FRONT_PORCH_REG,
+ (mode->vsync_start - mode->vdisplay) & 0xFF);
+ usleep_range(10000, 10050); /* 10ms delay recommended by spec */
+}
+
+static void ti_sn_bridge_enable(struct drm_bridge *bridge)
+{
+ struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+ struct drm_panel *panel = pdata->panel;
+ unsigned int val = 0;
+
+ if (panel)
+ drm_panel_prepare(panel);
+
+ /* DSI_A lane config */
+ val = (4 - pdata->dsi->lanes) << SN_DSIA_LANE_OFFSET;
+ regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG,
+ SN_DSIA_NUM_LANES_BITS, val);
+
+ /* DP lane config */
+ val = (pdata->dsi->lanes - 1) << SN_DP_LANE_OFFSET;
+ regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG,
+ SN_DP_NUM_LANES_BITS, val);
+
+ /* set dsi/dp clk frequency value */
+ ti_sn_bridge_set_dsi_dp_rate(pdata);
+
+ /* enable DP PLL */
+ regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1);
+ usleep_range(10000, 10050); /* 10ms delay recommended by spec */
+
+ /**
+ * The SN65DSI86 only supports ASSR Display Authentication method and
+ * this method is enabled by default. An eDP panel must support this
+ * authentication method. We need to enable this method in the eDP panel
+ * at DisplayPort address 0x0010A prior to link training.
+ */
+ regmap_write(pdata->regmap, SN_AUX_WDATA0_REG, 0x01);
+ regmap_write(pdata->regmap, SN_AUX_ADDR_19_16_REG, 0x00);
+ regmap_write(pdata->regmap, SN_AUX_ADDR_15_8_REG, 0x01);
+ regmap_write(pdata->regmap, SN_AUX_ADDR_7_0_REG, 0x0A);
+ regmap_write(pdata->regmap, SN_AUX_LENGTH_REG, 0x01);
+ regmap_write(pdata->regmap, SN_AUX_CMD_REG, 0x81);
+ usleep_range(10000, 10050); /* 10ms delay recommended by spec */
+
+ /* Semi auto link training mode */
+ regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A);
+ msleep(20); /* 20ms delay recommended by spec */
+
+ /* config video parameters */
+ ti_sn_bridge_set_video_timings(pdata);
+
+ /* enable video stream */
+ regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG,
+ SN_ENABLE_VID_STREAM_BIT, SN_ENABLE_VID_STREAM_BIT);
+
+ if (panel)
+ drm_panel_enable(panel);
+}
+
+void ti_sn_bridge_pre_enable(struct drm_bridge *bridge)
+{
+ struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+
+ ti_sn_bridge_power_ctrl(pdata, true);
+
+ /* configure bridge CLK_SRC and ref_clk */
+ ti_sn_bridge_set_refclk(pdata);
+}
+
+void ti_sn_bridge_post_disable(struct drm_bridge *bridge)
+{
+ struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+
+ ti_sn_bridge_power_ctrl(pdata, false);
+}
+
+static const struct drm_bridge_funcs ti_sn_bridge_funcs = {
+ .attach = ti_sn_bridge_attach,
+ .pre_enable = ti_sn_bridge_pre_enable,
+ .enable = ti_sn_bridge_enable,
+ .disable = ti_sn_bridge_disable,
+ .post_disable = ti_sn_bridge_post_disable,
+ .mode_set = ti_sn_bridge_mode_set,
+};
+
+static int ti_sn_bridge_parse_dsi_host(struct ti_sn_bridge *pdata)
+{
+ struct device_node *np = pdata->dev->of_node;
+ struct device_node *end_node;
+
+ end_node = of_graph_get_endpoint_by_regs(np, 0, 0);
+ if (!end_node) {
+ DRM_ERROR("remote endpoint not found\n");
+ return -ENODEV;
+ }
+
+ pdata->host_node = of_graph_get_remote_port_parent(end_node);
+ of_node_put(end_node);
+ if (!pdata->host_node) {
+ DRM_ERROR("remote node not found\n");
+ return -ENODEV;
+ }
+ of_node_put(pdata->host_node);
+
+ return 0;
+}
+
+static int ti_sn_bridge_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ti_sn_bridge *pdata;
+ struct device_node *ddc_node;
+ int ret = 0;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ DRM_ERROR("device doesn't support I2C\n");
+ return -ENODEV;
+ }
+
+ pdata = devm_kzalloc(&client->dev,
+ sizeof(struct ti_sn_bridge), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->dev = &client->dev;
+ DRM_DEBUG("I2C address is %x\n", client->addr);
+
+ pdata->regmap = devm_regmap_init_i2c(client,
+ &ti_sn_bridge_regmap_config);
+ if (IS_ERR(pdata->regmap))
+ return PTR_ERR(pdata->regmap);
+
+ pdata->enable_gpio = devm_gpiod_get(pdata->dev,
+ "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(pdata->enable_gpio)) {
+ DRM_ERROR("failed to get enable gpio from DT\n");
+ ret = PTR_ERR(pdata->enable_gpio);
+ return ret;
+ }
+
+ ret = ti_sn_bridge_parse_regulators(pdata);
+ if (ret) {
+ DRM_ERROR("failed to parse regulators\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(pdata->dev->of_node,
+ "refclk-freq-khz", &pdata->refclk_khz);
+ if (ret)
+ pdata->refclk_khz = SN_DEFAULT_REF_CLK_KHZ;
+
+ ret = ti_sn_bridge_parse_dsi_host(pdata);
+ if (ret)
+ return ret;
+
+ ddc_node = of_parse_phandle(pdata->dev->of_node, "ddc-i2c-bus", 0);
+ if (ddc_node) {
+ pdata->ddc = of_find_i2c_adapter_by_node(ddc_node);
+ of_node_put(ddc_node);
+ if (!pdata->ddc) {
+ dev_dbg(pdata->dev, "failed to read ddc node\n");
+ return -EPROBE_DEFER;
+ }
+ } else {
+ dev_dbg(pdata->dev, "no ddc property found\n");
+ }
+
+ ti_sn_bridge_power_ctrl(pdata, true);
+ ret = ti_sn_bridge_read_device_rev(pdata);
+ ti_sn_bridge_power_ctrl(pdata, false);
+ if (ret)
+ return ret;
+
+ i2c_set_clientdata(client, pdata);
+ mutex_init(&pdata->lock);
+
+ pdata->bridge.funcs = &ti_sn_bridge_funcs;
+ pdata->bridge.of_node = client->dev.of_node;
+
+ drm_bridge_add(&pdata->bridge);
+
+ DRM_DEBUG("bridge device registered successfully\n");
+
+ return 0;
+}
+
+static int ti_sn_bridge_remove(struct i2c_client *client)
+{
+ struct ti_sn_bridge *pdata = i2c_get_clientdata(client);
+
+ if (!pdata)
+ return -EINVAL;
+
+ mipi_dsi_detach(pdata->dsi);
+ mipi_dsi_device_unregister(pdata->dsi);
+
+ drm_bridge_remove(&pdata->bridge);
+ i2c_put_adapter(pdata->ddc);
+
+ return 0;
+}
+
+static struct i2c_device_id ti_sn_bridge_id[] = {
+ { "ti,sn65dsi86", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, ti_sn_bridge_id);
+
+static const struct of_device_id ti_sn_bridge_match_table[] = {
+ {.compatible = "ti,sn65dsi86"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, ti_sn_bridge_match_table);
+
+static struct i2c_driver ti_sn_bridge_driver = {
+ .driver = {
+ .name = "ti_sn65dsi86",
+ .owner = THIS_MODULE,
+ .of_match_table = ti_sn_bridge_match_table,
+ },
+ .probe = ti_sn_bridge_probe,
+ .remove = ti_sn_bridge_remove,
+ .id_table = ti_sn_bridge_id,
+};
+
+module_i2c_driver(ti_sn_bridge_driver);
+MODULE_DESCRIPTION("sn65dsi86 DSI to eDP bridge driver");
+MODULE_LICENSE("GPL v2");
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno
^ permalink raw reply related [flat|nested] 23+ messages in thread[parent not found: <1524821982-2778-2-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>]
* [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings [not found] ` <1524821982-2778-2-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> @ 2018-04-30 1:50 ` kbuild test robot 0 siblings, 0 replies; 23+ messages in thread From: kbuild test robot @ 2018-04-30 1:50 UTC (permalink / raw) Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, ryadav-sgV2jX0FEOL9JmXXK+q4OQ, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, kbuild-all-JC7UmRfGjtg, hoegsberg-F7+t8E8rja9g9hUCZPvPmw, freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, chandanu-sgV2jX0FEOL9JmXXK+q4OQ From: Fengguang Wu <fengguang.wu@intel.com> drivers/gpu/drm/bridge/ti-sn65dsi86.c:711:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Fixes: 90200d12a626 ("drm/bridge: add support for sn65dsi86 bridge driver") CC: Sandeep Panda <spanda@codeaurora.org> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> --- ti-sn65dsi86.c | 1 - 1 file changed, 1 deletion(-) --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -708,7 +708,6 @@ MODULE_DEVICE_TABLE(of, ti_sn_bridge_mat static struct i2c_driver ti_sn_bridge_driver = { .driver = { .name = "ti_sn65dsi86", - .owner = THIS_MODULE, .of_match_table = ti_sn_bridge_match_table, }, .probe = ti_sn_bridge_probe, _______________________________________________ Freedreno mailing list Freedreno@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/freedreno ^ permalink raw reply [flat|nested] 23+ messages in thread
* [drm-intel:topic/drm-misc 3/3] drivers/gpu/drm/bridge/sil-sii8620.c:1556:3-8: No need to set .owner here. The core will do it. @ 2016-10-26 16:58 kbuild test robot 2016-10-26 16:58 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot 0 siblings, 1 reply; 23+ messages in thread From: kbuild test robot @ 2016-10-26 16:58 UTC (permalink / raw) To: Andrzej Hajda; +Cc: intel-gfx, kbuild-all, dri-devel tree: git://anongit.freedesktop.org/drm-intel topic/drm-misc head: ce6e153f414a73a52fa1498489ce4adf20229445 commit: ce6e153f414a73a52fa1498489ce4adf20229445 [3/3] drm/bridge: add Silicon Image SiI8620 driver coccinelle warnings: (new ones prefixed by >>) >> drivers/gpu/drm/bridge/sil-sii8620.c:1556:3-8: No need to set .owner here. The core will do it. -- >> drivers/gpu/drm/bridge/sil-sii8620.c:988:2-3: Unneeded semicolon Please review and possibly fold the followup patch. --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings 2016-10-26 16:58 [drm-intel:topic/drm-misc 3/3] drivers/gpu/drm/bridge/sil-sii8620.c:1556:3-8: No need to set .owner here. The core will do it kbuild test robot @ 2016-10-26 16:58 ` kbuild test robot 0 siblings, 0 replies; 23+ messages in thread From: kbuild test robot @ 2016-10-26 16:58 UTC (permalink / raw) To: Andrzej Hajda; +Cc: intel-gfx, kbuild-all, dri-devel, Archit Taneja drivers/gpu/drm/bridge/sil-sii8620.c:1556:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci CC: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> --- sil-sii8620.c | 1 - 1 file changed, 1 deletion(-) --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -1553,7 +1553,6 @@ MODULE_DEVICE_TABLE(i2c, sii8620_id); static struct i2c_driver sii8620_driver = { .driver = { .name = "sii8620", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(sii8620_dt_match), }, .probe = sii8620_probe, _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFC 2/2] drm/bridge: Add I2C based driver for ps8640 bridge
@ 2015-10-16 13:52 kbuild test robot
2015-10-16 12:15 ` CK Hu
0 siblings, 1 reply; 23+ messages in thread
From: kbuild test robot @ 2015-10-16 13:52 UTC (permalink / raw)
To: CK Hu
Cc: kbuild-all-JC7UmRfGjtg, Rob Herring, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, David Airlie, Matthias Brugger,
Jitao Shi, Thierry Reding, Ajay Kumar, Inki Dae, Rahul Sharma,
Sean Paul, Vincent Palatin, Andy Yan, Philipp Zabel, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w
Hi Jitao,
[auto build test WARNING on drm-exynos/exynos-drm/for-next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]
url: https://github.com/0day-ci/linux/commits/CK-Hu/Dcumentation-bridge-Add-documentation-for-ps8640-DT-properties/20151016-201658
coccinelle warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/bridge/parade-ps8640.c:480:3-8: No need to set .owner here. The core will do it.
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 23+ messages in thread* [RFC 2/2] drm/bridge: Add I2C based driver for ps8640 bridge @ 2015-10-16 12:15 ` CK Hu 2015-10-16 13:52 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot 0 siblings, 1 reply; 23+ messages in thread From: CK Hu @ 2015-10-16 12:15 UTC (permalink / raw) To: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, David Airlie, Matthias Brugger Cc: Jitao Shi, Thierry Reding, Ajay Kumar, Inki Dae, Rahul Sharma, Sean Paul, Vincent Palatin, Andy Yan, Philipp Zabel, Russell King, devicetree, linux-kernel, dri-devel, linux-arm-kernel, linux-mediatek, srv_heupstream, Sascha Hauer, yingjoe.chen, eddie.huang, cawa.cheng From: Jitao Shi <jitao.shi@mediatek.com> This patch adds drm_bridge driver for parade DSI to eDP bridge chip. Signed-off-by: Jitao Shi <jitao.shi@mediatek.com> --- drivers/gpu/drm/bridge/Kconfig | 9 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/parade-ps8640.c | 489 ++++++++++++++++++++++++++++++++ 3 files changed, 499 insertions(+) create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 2de52a5..8ecaeed 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -29,4 +29,13 @@ config DRM_PARADE_PS8622 ---help--- Parade eDP-LVDS bridge chip driver. +config DRM_PARADE_PS8640 + bool "Parade PS8640 MIPI DSI to eDP Converter" + select DRM_KMS_HELPER + select DRM_PANEL + ---help--- + Choose this option if you have PS8640 for display + The PS8640 is a high-performance and low-power + MIPI DSI to eDP converter + endmenu diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index e2eef1c..da9e4a4 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -3,3 +3,4 @@ ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o +obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c new file mode 100644 index 0000000..dc62dd7 --- /dev/null +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/of_graph.h> +#include <linux/regulator/consumer.h> + +#include <drm/drmP.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> + +#define PAGE2_GPIO_L 0xa6 +#define PAGE2_GPIO_H 0xa7 +#define PS_GPIO9 BIT(1) + +#define PAGE4_REV_L 0xf0 +#define PAGE4_REV_H 0xf1 +#define PAGE4_CHIP_L 0xf2 +#define PAGE4_CHIP_H 0xf3 + +#define bridge_to_ps8640(e) container_of(e, struct ps8640, bridge) +#define connector_to_ps8640(e) container_of(e, struct ps8640, connector) + +struct ps8640 { + struct drm_connector connector; + struct drm_bridge bridge; + struct i2c_client *client; + struct ps8640_driver_data *driver_data; + struct regulator *pwr_1v2_supply; + struct regulator *pwr_3v3_supply; + struct drm_panel *panel; + struct gpio_desc *gpio_rst_n; + struct gpio_desc *gpio_pwr_n; + struct gpio_desc *gpio_mode_sel_n; + void *edid; + u16 base_reg; + bool enabled; +}; + +static int ps8640_regr(struct i2c_client *client, u16 i2c_addr, + u8 reg, u8 *value) +{ + int ret; + + client->addr = i2c_addr; + + ret = i2c_master_send(client, ®, 1); + if (ret <= 0) { + DRM_ERROR("Failed to send i2c command, ret=%d\n", ret); + return ret; + } + + ret = i2c_master_recv(client, value, 1); + if (ret <= 0) { + DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret); + return ret; + } + + return 0; +} + +static int ps8640_regw(struct i2c_client *client, u16 i2c_addr, + u8 reg, u8 value) +{ + int ret; + char buf[2]; + + client->addr = i2c_addr; + + buf[0] = reg; + buf[1] = value; + ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); + if (ret <= 0) { + DRM_ERROR("Failed to send i2c command, ret=%d\n", ret); + return ret; + } + + return 0; +} + +static int ps8640_check_valid_id(struct ps8640 *ps_bridge) +{ + struct i2c_client *client = ps_bridge->client; + u8 rev_id_low, rev_id_high, chip_id_low, chip_id_high; + int retry_cnt = 0; + + do { + ps8640_regr(client, ps_bridge->base_reg + 4, PAGE4_CHIP_H, + &chip_id_high); + if (chip_id_high != 0x30) + DRM_INFO("chip_id_high = 0x%x\n", chip_id_high); + } while ((retry_cnt++ < 2) && (chip_id_high != 0x30)); + + ps8640_regr(client, ps_bridge->base_reg + 4, PAGE4_REV_L, &rev_id_low); + ps8640_regr(client, ps_bridge->base_reg + 4, PAGE4_REV_H, &rev_id_high); + ps8640_regr(client, ps_bridge->base_reg + 4, PAGE4_CHIP_L, + &chip_id_low); + + if ((rev_id_low == 0x00) && (rev_id_high == 0x0a) && + (chip_id_low == 0x00) && (chip_id_high == 0x30)) + return 1; + + return 0; +} + +static void ps8640_show_mcu_fw_version(struct ps8640 *ps_bridge) +{ + struct i2c_client *client = ps_bridge->client; + u8 major_ver, minor_ver; + + ps8640_regr(client, ps_bridge->base_reg + 5, 0x4, &major_ver); + ps8640_regr(client, ps_bridge->base_reg + 5, 0x5, &minor_ver); + + DRM_INFO_ONCE("ps8640 rom fw version %d.%d\n", major_ver, minor_ver); +} + +static int ps8640_bdg_enable(struct ps8640 *ps_bridge) +{ + struct i2c_client *client = ps_bridge->client; + + if (ps8640_check_valid_id(ps_bridge)) { + ps8640_regw(client, ps_bridge->base_reg + 3, 0xfe, 0x13); + ps8640_regw(client, ps_bridge->base_reg + 3, 0xff, 0x18); + ps8640_regw(client, ps_bridge->base_reg + 3, 0xfe, 0x13); + ps8640_regw(client, ps_bridge->base_reg + 3, 0xff, 0x1c); + + return 0; + } + + return -1; +} + +static void ps8640_prepare(struct ps8640 *ps_bridge) +{ + struct i2c_client *client = ps_bridge->client; + int err, retry_cnt = 0; + u8 set_vdo_done; + + if (ps_bridge->enabled) + return; + + if (drm_panel_prepare(ps_bridge->panel)) { + DRM_ERROR("failed to prepare panel\n"); + return; + } + + err = regulator_enable(ps_bridge->pwr_1v2_supply); + if (err < 0) { + DRM_ERROR("failed to enable pwr_1v2_supply: %d\n", err); + return; + } + + err = regulator_enable(ps_bridge->pwr_3v3_supply); + if (err < 0) { + DRM_ERROR("failed to enable pwr_3v3_supply: %d\n", err); + return; + } + + gpiod_set_value(ps_bridge->gpio_pwr_n, 1); + gpiod_set_value(ps_bridge->gpio_rst_n, 0); + usleep_range(500, 700); + gpiod_set_value(ps_bridge->gpio_rst_n, 1); + + do { + msleep(50); + ps8640_regr(client, ps_bridge->base_reg + 2, PAGE2_GPIO_H, + &set_vdo_done); + } while ((retry_cnt++ < 70) && ((set_vdo_done & PS_GPIO9) != PS_GPIO9)); + + ps8640_show_mcu_fw_version(ps_bridge); + ps_bridge->enabled = true; +} + +static void ps8640_pre_enable(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + + ps8640_prepare(ps_bridge); +} + +static void ps8640_enable(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + + ps8640_bdg_enable(ps_bridge); + + if (drm_panel_enable(ps_bridge->panel)) { + DRM_ERROR("failed to enable panel\n"); + return; + } +} + +static void ps8640_disable(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + + if (!ps_bridge->enabled) + return; + + ps_bridge->enabled = false; + + if (drm_panel_disable(ps_bridge->panel)) { + DRM_ERROR("failed to disable panel\n"); + return; + } + + regulator_disable(ps_bridge->pwr_1v2_supply); + regulator_disable(ps_bridge->pwr_3v3_supply); + gpiod_set_value(ps_bridge->gpio_rst_n, 0); + gpiod_set_value(ps_bridge->gpio_pwr_n, 0); +} + +static void ps8640_post_disable(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + + if (drm_panel_unprepare(ps_bridge->panel)) { + DRM_ERROR("failed to unprepare panel\n"); + return; + } +} + +static int ps8640_get_modes(struct drm_connector *connector) +{ + struct ps8640 *ps_bridge = connector_to_ps8640(connector); + struct i2c_client *client = ps_bridge->client; + + ps8640_prepare(ps_bridge); + ps8640_regw(client, ps_bridge->base_reg + 2, 0xea, 0xd0); + + return drm_panel_get_modes(ps_bridge->panel); +} + +static struct drm_encoder *ps8640_best_encoder(struct drm_connector *connector) +{ + struct ps8640 *ps_bridge; + + ps_bridge = connector_to_ps8640(connector); + return ps_bridge->bridge.encoder; +} + +static const struct drm_connector_helper_funcs + ps8640_connector_helper_funcs = { + .get_modes = ps8640_get_modes, + .best_encoder = ps8640_best_encoder, +}; + +static enum drm_connector_status ps8640_detect(struct drm_connector *connector, + bool force) +{ + return connector_status_connected; +} + +static void ps8640_connector_destroy(struct drm_connector *connector) +{ + drm_connector_unregister(connector); + drm_connector_cleanup(connector); +} + +static const struct drm_connector_funcs ps8640_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = ps8640_detect, + .destroy = ps8640_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int ps8640_bridge_attach(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + int ret; + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + ret = drm_connector_init(bridge->dev, &ps_bridge->connector, + &ps8640_connector_funcs, + DRM_MODE_CONNECTOR_eDP); + + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + drm_connector_helper_add(&ps_bridge->connector, + &ps8640_connector_helper_funcs); + drm_connector_register(&ps_bridge->connector); + + ps_bridge->connector.dpms = DRM_MODE_DPMS_ON; + drm_mode_connector_attach_encoder(&ps_bridge->connector, + bridge->encoder); + + if (ps_bridge->panel) + drm_panel_attach(ps_bridge->panel, &ps_bridge->connector); + + return ret; +} + +static bool ps8640_bridge_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static const struct drm_bridge_funcs ps8640_bridge_funcs = { + .attach = ps8640_bridge_attach, + .mode_fixup = ps8640_bridge_mode_fixup, + .disable = ps8640_disable, + .post_disable = ps8640_post_disable, + .pre_enable = ps8640_pre_enable, + .enable = ps8640_enable, +}; + +static int ps8640_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct ps8640 *ps_bridge; + struct device_node *np = dev->of_node; + struct device_node *in_ep, *out_ep; + struct device_node *panel_node = NULL; + int ret, size; + u32 temp_reg; + const u8 *edidp; + + ps_bridge = devm_kzalloc(dev, sizeof(*ps_bridge), GFP_KERNEL); + if (!ps_bridge) + return -ENOMEM; + + /* FIXME - use of_graph_get_port_by_id(np, 1) on newer kernels */ + in_ep = of_graph_get_next_endpoint(np, NULL); + if (in_ep) { + out_ep = of_graph_get_next_endpoint(np, in_ep); + of_node_put(in_ep); + if (out_ep) { + panel_node = of_graph_get_remote_port_parent(out_ep); + of_node_put(out_ep); + } + } + if (panel_node) { + ps_bridge->panel = of_drm_find_panel(panel_node); + of_node_put(panel_node); + if (!ps_bridge->panel) + return -EPROBE_DEFER; + } + + ps_bridge->client = client; + + edidp = of_get_property(np, "edid", &size); + + if (edidp) + ps_bridge->edid = devm_kmemdup(&client->dev, edidp, size, + GFP_KERNEL); + + ps_bridge->pwr_3v3_supply = devm_regulator_get(dev, "ps8640-3v3"); + if (IS_ERR(ps_bridge->pwr_3v3_supply)) { + dev_err(dev, "cannot get ps_bridge->pwr_3v3_supply\n"); + return PTR_ERR(ps_bridge->pwr_3v3_supply); + } + + ps_bridge->pwr_1v2_supply = devm_regulator_get(dev, "ps8640-1v2"); + if (IS_ERR(ps_bridge->pwr_1v2_supply)) { + dev_err(dev, "cannot get ps_bridge->pwr_1v2_supply\n"); + return PTR_ERR(ps_bridge->pwr_1v2_supply); + } + + ps_bridge->gpio_mode_sel_n = devm_gpiod_get(&client->dev, "mode-sel", + GPIOD_OUT_HIGH); + if (IS_ERR(ps_bridge->gpio_mode_sel_n)) { + ret = PTR_ERR(ps_bridge->gpio_mode_sel_n); + DRM_ERROR("cannot get gpio_mode_sel_n %d\n", ret); + return ret; + } + + ret = gpiod_direction_output(ps_bridge->gpio_mode_sel_n, 1); + if (ret) { + DRM_ERROR("cannot configure gpio_mode_sel_n\n"); + return ret; + } + + ps_bridge->gpio_pwr_n = devm_gpiod_get(&client->dev, "power", + GPIOD_OUT_HIGH); + if (IS_ERR(ps_bridge->gpio_pwr_n)) { + ret = PTR_ERR(ps_bridge->gpio_pwr_n); + DRM_ERROR("cannot get gpio_pwr_n %d\n", ret); + return ret; + } + + ret = gpiod_direction_output(ps_bridge->gpio_pwr_n, 1); + if (ret) { + DRM_ERROR("cannot configure gpio_pwr_n\n"); + return ret; + } + + ps_bridge->gpio_rst_n = devm_gpiod_get(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(ps_bridge->gpio_rst_n)) { + ret = PTR_ERR(ps_bridge->gpio_rst_n); + DRM_ERROR("cannot get gpio_rst_n %d\n", ret); + return ret; + } + + ret = gpiod_direction_output(ps_bridge->gpio_rst_n, 1); + if (ret) { + DRM_ERROR("cannot configure gpio_rst_n\n"); + return ret; + } + + ret = of_property_read_u32(dev->of_node, "reg", &temp_reg); + if (ret) { + DRM_ERROR("Can't read base_reg value\n"); + return ret; + } + ps_bridge->base_reg = temp_reg; + + ps_bridge->bridge.funcs = &ps8640_bridge_funcs; + ps_bridge->bridge.of_node = dev->of_node; + ret = drm_bridge_add(&ps_bridge->bridge); + if (ret) { + DRM_ERROR("Failed to add bridge\n"); + return ret; + } + + i2c_set_clientdata(client, ps_bridge); + + return 0; +} + +static int ps8640_remove(struct i2c_client *client) +{ + struct ps8640 *ps_bridge = i2c_get_clientdata(client); + + drm_bridge_remove(&ps_bridge->bridge); + + return 0; +} + +static const struct i2c_device_id ps8640_i2c_table[] = { + {"parade,ps8640", 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ps8640_i2c_table); + +static const struct of_device_id ps8640_match[] = { + { .compatible = "parade,ps8640" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ps8640_match); + +static struct i2c_driver ps8640_driver = { + .id_table = ps8640_i2c_table, + .probe = ps8640_probe, + .remove = ps8640_remove, + .driver = { + .name = "parade,ps8640", + .owner = THIS_MODULE, + .of_match_table = ps8640_match, + }, +}; +module_i2c_driver(ps8640_driver); + +MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>"); +MODULE_AUTHOR("CK Hu <ck.hu@mediatek.com>"); +MODULE_DESCRIPTION("PARADE ps8640 DSI-eDP converter driver"); +MODULE_LICENSE("GPL v2"); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings 2015-10-16 12:15 ` CK Hu @ 2015-10-16 13:52 ` kbuild test robot 0 siblings, 0 replies; 23+ messages in thread From: kbuild test robot @ 2015-10-16 13:52 UTC (permalink / raw) To: CK Hu Cc: kbuild-all, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, David Airlie, Matthias Brugger, Jitao Shi, Thierry Reding, Ajay Kumar, Inki Dae, Rahul Sharma, Sean Paul, Vincent Palatin, Andy Yan, Philipp Zabel, Russell King, devicetree, linux-kernel, dri-devel, linux-arm-kernel, linux-mediatek, srv_heupstream drivers/gpu/drm/bridge/parade-ps8640.c:480:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci CC: Jitao Shi <jitao.shi@mediatek.com> Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> --- parade-ps8640.c | 1 - 1 file changed, 1 deletion(-) --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -477,7 +477,6 @@ static struct i2c_driver ps8640_driver = .remove = ps8640_remove, .driver = { .name = "parade,ps8640", - .owner = THIS_MODULE, .of_match_table = ps8640_match, }, }; ^ permalink raw reply [flat|nested] 23+ messages in thread
[parent not found: <201508211922.3S711l5f%fengguang.wu@intel.com>]
* [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings [not found] <201508211922.3S711l5f%fengguang.wu@intel.com> @ 2015-08-21 11:05 ` kbuild test robot 2015-09-04 9:43 ` Thierry Reding 2015-08-21 11:05 ` kbuild test robot 1 sibling, 1 reply; 23+ messages in thread From: kbuild test robot @ 2015-08-21 11:05 UTC (permalink / raw) To: Thierry Reding Cc: dri-devel, Javier Martinez Canillas, kbuild-all, Uwe Kleine-König, Gustavo Padovan, Ajay Kumar drivers/gpu/drm/bridge/nxp-ptn3460.c:403:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> --- nxp-ptn3460.c | 1 - 1 file changed, 1 deletion(-) --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -400,7 +400,6 @@ static struct i2c_driver ptn3460_driver .remove = ptn3460_remove, .driver = { .name = "nxp,ptn3460", - .owner = THIS_MODULE, .of_match_table = ptn3460_match, }, }; _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings 2015-08-21 11:05 ` kbuild test robot @ 2015-09-04 9:43 ` Thierry Reding 0 siblings, 0 replies; 23+ messages in thread From: Thierry Reding @ 2015-09-04 9:43 UTC (permalink / raw) To: kbuild test robot Cc: dri-devel, Javier Martinez Canillas, kbuild-all, Uwe Kleine-König, Gustavo Padovan, Ajay Kumar [-- Attachment #1.1: Type: text/plain, Size: 905 bytes --] On Fri, Aug 21, 2015 at 07:05:39PM +0800, kbuild test robot wrote: > drivers/gpu/drm/bridge/nxp-ptn3460.c:403:3-8: No need to set .owner here. The core will do it. > > Remove .owner field if calls are used which set it automatically > > Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci > > Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> > --- > > nxp-ptn3460.c | 1 - > 1 file changed, 1 deletion(-) Applied with a slightly reworded commit message. Thanks, Thierry > > --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c > +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c > @@ -400,7 +400,6 @@ static struct i2c_driver ptn3460_driver > .remove = ptn3460_remove, > .driver = { > .name = "nxp,ptn3460", > - .owner = THIS_MODULE, > .of_match_table = ptn3460_match, > }, > }; Applied with a slightly reworded commit message. Thanks, Thierry [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 819 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings [not found] <201508211922.3S711l5f%fengguang.wu@intel.com> 2015-08-21 11:05 ` kbuild test robot @ 2015-08-21 11:05 ` kbuild test robot 2015-09-04 9:43 ` Thierry Reding 1 sibling, 1 reply; 23+ messages in thread From: kbuild test robot @ 2015-08-21 11:05 UTC (permalink / raw) To: Thierry Reding Cc: Vincent Palatin, dri-devel, Geert Uytterhoeven, kbuild-all, Uwe Kleine-König, Gustavo Padovan drivers/gpu/drm/bridge/parade-ps8622.c:671:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> --- parade-ps8622.c | 1 - 1 file changed, 1 deletion(-) --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -668,7 +668,6 @@ static struct i2c_driver ps8622_driver = .remove = ps8622_remove, .driver = { .name = "ps8622", - .owner = THIS_MODULE, .of_match_table = ps8622_devices, }, }; _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings 2015-08-21 11:05 ` kbuild test robot @ 2015-09-04 9:43 ` Thierry Reding 0 siblings, 0 replies; 23+ messages in thread From: Thierry Reding @ 2015-09-04 9:43 UTC (permalink / raw) To: kbuild test robot Cc: Vincent Palatin, dri-devel, Geert Uytterhoeven, kbuild-all, Uwe Kleine-König, Gustavo Padovan [-- Attachment #1.1: Type: text/plain, Size: 839 bytes --] On Fri, Aug 21, 2015 at 07:05:39PM +0800, kbuild test robot wrote: > drivers/gpu/drm/bridge/parade-ps8622.c:671:3-8: No need to set .owner here. The core will do it. > > Remove .owner field if calls are used which set it automatically > > Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci > > Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> > --- > > parade-ps8622.c | 1 - > 1 file changed, 1 deletion(-) > > --- a/drivers/gpu/drm/bridge/parade-ps8622.c > +++ b/drivers/gpu/drm/bridge/parade-ps8622.c > @@ -668,7 +668,6 @@ static struct i2c_driver ps8622_driver = > .remove = ps8622_remove, > .driver = { > .name = "ps8622", > - .owner = THIS_MODULE, > .of_match_table = ps8622_devices, > }, > }; Applied with a slightly reworded commit message. Thanks, Thierry [-- Attachment #1.2: signature.asc --] [-- Type: application/pgp-signature, Size: 819 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2018-04-30 1:50 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CGME20170803074535eucas1p107414859fa54647d1f623c73d0fc17f2@eucas1p1.samsung.com>
2017-08-03 7:45 ` [PATCH 0/2] add Silicon Image SiI9234 driver Maciej Purski
[not found] ` <CGME20170803074538eucas1p1fec88e4f2c3ebc00054fd362a504c03e@eucas1p1.samsung.com>
2017-08-03 7:45 ` [PATCH 1/2] drm/bridge: " Maciej Purski
2017-08-03 10:24 ` Laurent Pinchart
2017-08-04 6:55 ` Marek Szyprowski
2017-08-10 14:51 ` Laurent Pinchart
2017-08-11 7:00 ` Marek Szyprowski
2017-08-11 8:59 ` Laurent Pinchart
2017-08-11 9:00 ` Laurent Pinchart
2017-08-14 16:35 ` Mark Brown
2017-08-03 19:36 ` kbuild test robot
[not found] ` <1501746323-5254-2-git-send-email-m.purski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2017-08-03 19:36 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot
2017-08-12 22:43 ` [PATCH 1/2] drm/bridge: add Silicon Image SiI9234 driver kbuild test robot
[not found] ` <CGME20170803074541eucas1p2b054d4853a98819fc42f19f7cae7f419@eucas1p2.samsung.com>
2017-08-03 7:45 ` [PATCH 2/2] ARM: dts: exynos: Add HDMI and Sil9234 to Trats2 board Maciej Purski
2017-08-03 19:20 ` Krzysztof Kozlowski
2017-08-04 6:32 ` Marek Szyprowski
2017-08-04 6:44 ` Krzysztof Kozlowski
2018-04-27 9:39 [PATCH v4 1/3] drm/bridge: add support for sn65dsi86 bridge driver Sandeep Panda
[not found] ` <1524821982-2778-2-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-04-30 1:50 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot
-- strict thread matches above, loose matches on Subject: below --
2016-10-26 16:58 [drm-intel:topic/drm-misc 3/3] drivers/gpu/drm/bridge/sil-sii8620.c:1556:3-8: No need to set .owner here. The core will do it kbuild test robot
2016-10-26 16:58 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot
2015-10-16 13:52 [RFC 2/2] drm/bridge: Add I2C based driver for ps8640 bridge kbuild test robot
2015-10-16 12:15 ` CK Hu
2015-10-16 13:52 ` [PATCH] drm/bridge: fix platform_no_drv_owner.cocci warnings kbuild test robot
[not found] <201508211922.3S711l5f%fengguang.wu@intel.com>
2015-08-21 11:05 ` kbuild test robot
2015-09-04 9:43 ` Thierry Reding
2015-08-21 11:05 ` kbuild test robot
2015-09-04 9:43 ` Thierry Reding
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).