diff options
author | Leon Woestenberg <leon@sidebranch.com> | 2017-01-09 13:54:02 +0100 |
---|---|---|
committer | Christian Kohn <christian.kohn@xilinx.com> | 2017-01-31 19:03:28 -0800 |
commit | 36871e80e2ba27d48dd91644252612dd889db78d (patch) | |
tree | 08d386ebab6fb0c88e228e58dcb37cc81be1ca48 | |
parent | af152057f7566b14ec9f49cf66fb8852a9dc21f4 (diff) | |
download | linux-36871e80e2ba27d48dd91644252612dd889db78d.tar.gz |
Move DP159 retimer driver from V4L2 to misc. as it does not relate to V4L2.
Signed-off-by: Leon Woestenberg <leon@sidebranch.com>
-rw-r--r-- | drivers/gpu/drm/xilinx/xilinx_drm_hdmi.c | 3 | ||||
-rw-r--r-- | drivers/media/i2c/Kconfig | 8 | ||||
-rw-r--r-- | drivers/media/i2c/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/i2c/dp159.c | 495 | ||||
-rw-r--r-- | drivers/media/platform/xilinx/xilinx-hdmirx.c | 142 | ||||
-rw-r--r-- | drivers/misc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/dp159.c | 436 | ||||
-rw-r--r-- | drivers/phy/phy-vphy.c | 3 |
9 files changed, 569 insertions, 529 deletions
diff --git a/drivers/gpu/drm/xilinx/xilinx_drm_hdmi.c b/drivers/gpu/drm/xilinx/xilinx_drm_hdmi.c index aa2c11381a3d57..8ca1bab755d116 100644 --- a/drivers/gpu/drm/xilinx/xilinx_drm_hdmi.c +++ b/drivers/gpu/drm/xilinx/xilinx_drm_hdmi.c @@ -991,7 +991,7 @@ static int xilinx_drm_hdmi_encoder_init(struct platform_device *pdev, xvphy_mutex_lock(hdmi->phy[0]); /* the callback is not specific to a single lane, but we need to - * provide one of the phy's as reference */ + * provide one of the phys as reference */ XVphy_SetHdmiCallback(hdmi->xvphy, XVPHY_HDMI_HANDLER_TXINIT, VphyHdmiTxInitCallback, (void *)hdmi); @@ -1129,7 +1129,6 @@ XV_axi4s_remap_Config* XV_axi4s_remap_LookupConfig_TX(u16 DeviceId) { return NULL; } - static void xilinx_drm_hdmi_config_init(XV_HdmiTxSs_Config *config, void __iomem *iomem) { config->BaseAddress = (uintptr_t)iomem; diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 071fc4d6dd5950..fa8accd8281ac4 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -731,14 +731,6 @@ config VIDEO_M52790 To compile this driver as a module, choose M here: the module will be called m52790. -config VIDEO_DP159 - tristate "Texas Instruments DP159 Redriver/retimer" - depends on VIDEO_V4L2 && I2C - ---help--- - Support for the Texas Instruments DP159 Redriver/retimer. - - To compile this driver as a module, choose M here: the - module will be called m52790. endmenu menu "Sensors used on soc_camera driver" diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 78dcc2f426b05d..94f2c99e890da8 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -80,4 +80,3 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o obj-$(CONFIG_VIDEO_OV2659) += ov2659.o obj-$(CONFIG_VIDEO_TC358743) += tc358743.o -obj-$(CONFIG_VIDEO_DP159) += dp159.o diff --git a/drivers/media/i2c/dp159.c b/drivers/media/i2c/dp159.c deleted file mode 100644 index c6b97d5f9026a2..00000000000000 --- a/drivers/media/i2c/dp159.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * dp159 redriver and retimer - * Copyright (C) 2016 Leon Woestenberg <leon@sidebranch.com> - * - * based on dp159.c - * Copyright (C) 2007 Hans Verkuil - * - * 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; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/i2c.h> -#include <linux/videodev2.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/of.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ctrls.h> -#include <linux/of.h> - -MODULE_DESCRIPTION("i2c device driver for dp159 redriver and retimer"); -MODULE_AUTHOR("Leon Woestenberg"); -MODULE_LICENSE("GPL"); - -static bool debug; - -module_param(debug, bool, 0644); - -MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); - -struct dp159_state { - struct v4l2_subdev sd; - struct v4l2_ctrl_handler hdl; -}; - -//static int dp159_program(struct v4l2_subdev *sd, int mode); - -static inline struct dp159_state *to_state(struct v4l2_subdev *sd) -{ - return container_of(sd, struct dp159_state, sd); -} - -static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -{ - return &container_of(ctrl->handler, struct dp159_state, hdl)->sd; -} - -/* ----------------------------------------------------------------------- */ - -static inline int dp159_write(struct v4l2_subdev *sd, u8 reg, u8 value) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return i2c_smbus_write_byte_data(client, reg, value); -} - -static inline int dp159_read(struct v4l2_subdev *sd, u8 reg) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return i2c_smbus_read_byte_data(client, reg); -} - -static int dp159_program(struct v4l2_subdev *sd, int mode) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - int r; - if (client->addr == 0x2C) { - switch (mode) { - /* HDMI 1.4 (250Mbps - 1.2Gbps) */ - case 0 : - // Select page 1 - r = dp159_write(sd, 0xff, 0x01); - - // PLL_FBDIV is 280 - r = dp159_write(sd, 0x04, 0x80); - r = dp159_write(sd, 0x05, 0x02); - - // PLL_PREDIV is 2 - r = dp159_write(sd, 0x08, 0x02); - - // CDR_CONFIG[4:0] - r = dp159_write(sd, 0x0e, 0x10); - - // CP_CURRENT - r = dp159_write(sd, 0x01, 0x81); - usleep_range(10000, 11000); - - // Enable Bandgap - r = dp159_write(sd, 0x00, 0x02); - usleep_range(10000, 11000); - // Enable PLL - r = dp159_write(sd, 0x00, 0x03); - - // Enable TX - r = dp159_write(sd, 0x10, 0x0f); - - // HDMI_TWPST1 - r = dp159_write(sd, 0x14, 0x10); - - // DP_TWPST1 - r = dp159_write(sd, 0x16, 0x10); - - // DP_TWPST2 - r = dp159_write(sd, 0x17, 0x00); - - // Slew CTRL - r = dp159_write(sd, 0x12, 0x28); - - // FIR_UPD - r = dp159_write(sd, 0x13, 0x0f); - r = dp159_write(sd, 0x13, 0x00); - - // TX_RATE - r = dp159_write(sd, 0x11, 0xC0); - - // Enable receivers - r = dp159_write(sd, 0x30, 0x0f); - - // PD_RXINT - r = dp159_write(sd, 0x32, 0x00); - - // RX_RATE - r = dp159_write(sd, 0x31, 0xC0); - - // Disable offset correction - r = dp159_write(sd, 0x34, 0x00); - - // Change default of CDR_STL - r = dp159_write(sd, 0x3c, 0x04); - - // Change default of CDR_SO_TR - r = dp159_write(sd, 0x3D, 0x06); - - // EQFTC - r = dp159_write(sd, 0x4D, 0x38); - - // Enable Adaptive EQ - r = dp159_write(sd, 0x4c, 0x03); - - // Select page 0 - r = dp159_write(sd, 0xff, 0x00); - - // Gate HPD_SNK - r = dp159_write(sd, 0x09, 0x01); - - // Set GPIO - r = dp159_write(sd, 0xe0, 0x01); - - // Un gate HPD_SNK - r = dp159_write(sd, 0x09, 0x00); - return 0; - break; - - case 1 : // HDMI 1.4 (1.2Gbps - 3Gbps) - // Select page 1 - r = dp159_write(sd, 0xff, 0x01); - - // PLL_FBDIV is 140 - r = dp159_write(sd, 0x04, 0x40); - r = dp159_write(sd, 0x05, 0x01); - - // PLL_PREDIV is 4 - r = dp159_write(sd, 0x08, 0x04); - - // CDR_CONFIG[4:0] - r = dp159_write(sd, 0x0e, 0x10); - - // CP_CURRENT - r = dp159_write(sd, 0x01, 0x81); - usleep_range(10000, 11000); - // Enable Bandgap - r = dp159_write(sd, 0x00, 0x02); - usleep_range(10000, 11000); - // Enable PLL - r = dp159_write(sd, 0x00, 0x03); - - // Enable TX - r = dp159_write(sd, 0x10, 0x0f); - - // HDMI_TWPST1 - r = dp159_write(sd, 0x14, 0x10); - - // DP_TWPST1 - r = dp159_write(sd, 0x16, 0x10); - - // DP_TWPST2 - r = dp159_write(sd, 0x17, 0x00); - - // Slew CTRL - r = dp159_write(sd, 0x12, 0x28); - - // FIR_UPD - r = dp159_write(sd, 0x13, 0x0f); - r = dp159_write(sd, 0x13, 0x00); - - // TX_RATE - r = dp159_write(sd, 0x11, 0x70); - - // Enable receivers - r = dp159_write(sd, 0x30, 0x0f); - - // PD_RXINT - r = dp159_write(sd, 0x32, 0x00); - - // RX_RATE - r = dp159_write(sd, 0x31, 0x40); - - // Disable offset correction - r = dp159_write(sd, 0x34, 0x00); - - // Change default of CDR_STL - r = dp159_write(sd, 0x3c, 0x04); - - // Change default of CDR_SO_TR - r = dp159_write(sd, 0x3D, 0x06); - - // EQFTC - r = dp159_write(sd, 0x4D, 0x28); - - // Enable Adaptive EQ - r = dp159_write(sd, 0x4c, 0x03); - - // Select page 0 - r = dp159_write(sd, 0xff, 0x00); - - // Gate HPD_SNK - r = dp159_write(sd, 0x09, 0x01); - - // Set GPIO - r = dp159_write(sd, 0xe0, 0x01); - - // Un gate HPD_SNK - r = dp159_write(sd, 0x09, 0x00); - return 0; - break; - - case 2 : // HDMI 2.0 (3.4Gbps - 6 Gbps) - - // Select page 1 - r = dp159_write(sd, 0xff, 0x01); - - // PLL_FBDIV is 280 - r = dp159_write(sd, 0x04, 0x80); - r = dp159_write(sd, 0x05, 0x02); - - // PLL_PREDIV is 4 - r = dp159_write(sd, 0x08, 0x04); - - // CDR_CONFIG[4:0] - r = dp159_write(sd, 0x0e, 0x10); - - // CP_CURRENT - r = dp159_write(sd, 0x01, 0x81); - usleep_range(10000, 11000); - // Enable Bandgap - r = dp159_write(sd, 0x00, 0x02); - usleep_range(10000, 11000); - // Enable PLL - r = dp159_write(sd, 0x00, 0x03); - - // Enable TX - r = dp159_write(sd, 0x10, 0x0f); - - // HDMI_TWPST1 - r = dp159_write(sd, 0x14, 0x10); - - // DP_TWPST1 - r = dp159_write(sd, 0x16, 0x10); - - // DP_TWPST2 - r = dp159_write(sd, 0x17, 0x00); - - // Slew CTRL - r = dp159_write(sd, 0x12, 0x28); - - // FIR_UPD - r = dp159_write(sd, 0x13, 0x0f); - r = dp159_write(sd, 0x13, 0x00); - - // TX_RATE - r = dp159_write(sd, 0x11, 0x30); - - // Enable receivers - r = dp159_write(sd, 0x30, 0x0f); - - // PD_RXINT - r = dp159_write(sd, 0x32, 0x00); - - // RX_RATE - r = dp159_write(sd, 0x31, 0x00); - - // Disable offset correction - r = dp159_write(sd, 0x34, 0x00); - - // Change default of CDR_STL - r = dp159_write(sd, 0x3c, 0x04); - - // Change default of CDR_SO_TR - r = dp159_write(sd, 0x3D, 0x06); - - // EQFTC - r = dp159_write(sd, 0x4D, 0x18); - - // Enable Adaptive EQ - r = dp159_write(sd, 0x4c, 0x03); - - // Select page 0 - r = dp159_write(sd, 0xff, 0x00); - - // Gate HPD_SNK - r = dp159_write(sd, 0x09, 0x01); - - // Set GPIO - r = dp159_write(sd, 0xe0, 0x01); - - // Un gate HPD_SNK - r = dp159_write(sd, 0x09, 0x00); - return 0; - break; - } /* switch (mode) */ - /* DP159 ES? */ - } else if (client->addr == 0x5C) { - if (mode == 2) { - r = dp159_write(sd, 0x0A, 0x36); // Automatic retimer for HDMI 2.0 - r = dp159_write(sd, 0x0B, 0x1a); - - r = dp159_write(sd, 0x0C, 0xa1); - r = dp159_write(sd, 0x0D, 0x00); - } else { - r = dp159_write(sd, 0x0A, 0x35); // Automatic redriver to retimer crossover at 1.0 Gbps - //r = dp159_write(sd, 0x0A, 0x34); // The redriver mode must be selected to support low video rates - r = dp159_write(sd, 0x0B, 0x01); - r = dp159_write(sd, 0x0C, 0xA0); // Set VSWING data decrease by 24% - r = dp159_write(sd, 0x0D, 0x00); - } - } -} - -static int dp159_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = to_sd(ctrl); - int mode = 0; - switch (ctrl->id) { - case V4L2_CID_LINK_FREQ: - if ((ctrl->val / 1000000) > 3400) { - mode = 2; - } else if ((ctrl->val / 1000000) > 1200) { - mode = 1; - } - return dp159_program(sd, mode); - } - return -EINVAL; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int dp159_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) -{ - reg->size = 1; - reg->val = dp159_read(sd, reg->reg); - return 0; -} - -static int dp159_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) -{ - dp159_write(sd, reg->reg, reg->val & 0xff); - return 0; -} -#endif - -static int dp159_log_status(struct v4l2_subdev *sd) -{ -#if 0 - u8 v = dp159_read(sd, 0x09) & 7; - u8 m = dp159_read(sd, 0x04); - int vol = dp159_read(sd, 0x08) & 0x3f; - - v4l2_info(sd, "Input: %d%s\n", v, - (m & 0x80) ? " (muted)" : ""); - if (vol >= 32) - vol = vol - 64; - v4l2_info(sd, "Volume: %d dB\n", vol); -#endif - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static const struct v4l2_ctrl_ops dp159_ctrl_ops = { - .s_ctrl = dp159_s_ctrl, -}; - -static const struct v4l2_subdev_core_ops dp159_core_ops = { - .log_status = dp159_log_status, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .g_register = dp159_g_register, - .s_register = dp159_s_register, -#endif -}; - -static const struct v4l2_subdev_ops dp159_ops = { - .core = &dp159_core_ops, -}; - -/* ----------------------------------------------------------------------- */ - -static int dp159_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct dp159_state *state; - struct v4l2_subdev *sd; - - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - v4l_info(client, "chip found @ 0x%x (%s)\n", - client->addr << 1, client->adapter->name); - - state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); - if (state == NULL) - return -ENOMEM; - sd = &state->sd; - v4l2_i2c_subdev_init(sd, client, &dp159_ops); - - v4l2_ctrl_handler_init(&state->hdl, 1); - v4l2_ctrl_new_std(&state->hdl, &dp159_ctrl_ops, - V4L2_CID_LINK_FREQ, 0, 8000*1000*1000LL, 1, 0); - sd->ctrl_handler = &state->hdl; - if (state->hdl.error) { - int err = state->hdl.error; - - v4l2_ctrl_handler_free(&state->hdl); - return err; - } - /* set volume/mute */ - v4l2_ctrl_handler_setup(&state->hdl); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static int dp159_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct dp159_state *state = to_state(sd); - - v4l2_device_unregister_subdev(sd); - v4l2_ctrl_handler_free(&state->hdl); - return 0; -} - -/* ----------------------------------------------------------------------- */ - -static const struct i2c_device_id dp159_id[] = { - { "dp159", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, dp159_id); - -#if IS_ENABLED(CONFIG_OF) -static const struct of_device_id dp159_of_match[] = { - { .compatible = "ti,dp159", }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, dp159_of_match); -#endif - -static struct i2c_driver dp159_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "dp159", -//#if IS_ENABLED(CONFIG_OF) - .of_match_table = of_match_ptr(dp159_of_match), -//#endif - }, - .probe = dp159_probe, - .remove = dp159_remove, - .id_table = dp159_id, -}; - -module_i2c_driver(dp159_driver); diff --git a/drivers/media/platform/xilinx/xilinx-hdmirx.c b/drivers/media/platform/xilinx/xilinx-hdmirx.c index afd4a4f397b5d8..2f39d26e59da06 100644 --- a/drivers/media/platform/xilinx/xilinx-hdmirx.c +++ b/drivers/media/platform/xilinx/xilinx-hdmirx.c @@ -1,8 +1,8 @@ /* - * Xilinx Video HDMI RX Subsystem driver (Early Access Release) + * Xilinx Video HDMI RX Subsystem driver * - * Copyright (C) 2016 Leon Woestenberg <leon@sidebranch.com> - * Copyright (C) 2016 Xilinx, Inc. + * Copyright (C) 2016-2017 Leon Woestenberg <leon@sidebranch.com> + * Copyright (C) 2016-2017 Xilinx, Inc. * * Authors: Leon Woestenberg <leon@sidebranch.com> * Rohit Consul <rohitco@xilinx.com> @@ -29,9 +29,9 @@ #include <media/v4l2-subdev.h> #include <media/v4l2-dv-timings.h> -#include "xilinx-vip.h" +#include <linux/phy/phy-vphy.h> -#include "linux/phy/phy-vphy.h" +#include "xilinx-vip.h" /* baseline driver includes */ #include "xilinx-hdmi-rx/xv_hdmirxss.h" @@ -220,8 +220,9 @@ static int xhdmirx_get_edid(struct v4l2_subdev *subdev, struct v4l2_edid *edid) static void xhdmirx_set_hpd(struct xhdmirx_device *xhdmirx, int enable) { + XV_HdmiRxSs *HdmiRxSsPtr; BUG_ON(!xhdmirx); - XV_HdmiRxSs *HdmiRxSsPtr = &xhdmirx->xv_hdmirxss; + HdmiRxSsPtr = &xhdmirx->xv_hdmirxss; XV_HdmiRx_SetHpd(HdmiRxSsPtr->HdmiRxPtr, enable); } @@ -349,7 +350,6 @@ static int xhdmirx_query_dv_timings(struct v4l2_subdev *subdev, struct v4l2_dv_timings *timings) { struct xhdmirx_device *xhdmirx = to_xhdmirx(subdev); - printk(KERN_INFO "xhdmirx_set_format\n"); struct v4l2_bt_timings *bt = &timings->bt; if (!timings) @@ -996,28 +996,124 @@ static int xhdmirx_parse_of(struct xhdmirx_device *xhdmirx, XV_HdmiRxSs_Config * { struct device *dev = xhdmirx->dev; struct device_node *node = dev->of_node; - (void)dev; - (void)node; -#if 0 - struct device_node *ports; - struct device_node *port; - unsigned int nports = 0; - bool has_endpoint = false; -#endif +// struct device_node *ports; + int ret; -#if 0 // example bool - bool has_dre = false; - has_dre = of_property_read_bool(node, "xlnx,include-dre"); -#endif -#if 0 // example u32 - u32 value; - int err; - err = of_property_read_u32(node, "xlnx,datawidth", &value); + printk(KERN_INFO "Reading HDMI Rx Device Tree Info\n"); + +// ports = of_get_child_by_name(node, "ports"); +// if (ports == NULL) +// ports = node; + + ret = of_property_read_u32(node, "xlnx,input-pixels-per-clock", (u32 *)&config->Ppc); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,max-bits-per-component", (u32 *)&config->MaxBitsPerPixel); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,include-hdmi-rx", (u32 *)&config->HdmiRx.IsPresent); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,devid-hdmi-rx", (u32 *)&config->HdmiRx.DeviceId); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,offset-hdmi-rx", (u32 *)&config->HdmiRx.AddrOffset); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,include-remapper", (u32 *)&config->Remapper.IsPresent); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,devid-remapper", (u32 *)&config->Remapper.DeviceId); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,offset-remapper", (u32 *)&config->Remapper.AddrOffset); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,include-remap-gpio", (u32 *)&config->RemapperReset.IsPresent); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,devid-remap-gpio", (u32 *)&config->RemapperReset.DeviceId); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,offset-remap-gpio", (u32 *)&config->RemapperReset.AddrOffset); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,include-timer", (u32 *)&config->HdcpTimer.IsPresent); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,devid-timer", (u32 *)&config->HdcpTimer.DeviceId); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,offset-timer", (u32 *)&config->HdcpTimer.AddrOffset); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,include-hdcp-1-4", (u32 *)&config->Hdcp14.IsPresent); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,devid-hdcp-1-4", (u32 *)&config->Hdcp14.DeviceId); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,offset-hdcp-1-4", (u32 *)&config->Hdcp14.AddrOffset); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,include-hdcp-2-2", (u32 *)&config->Hdcp22.IsPresent); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,devid-hdcp-2-2", (u32 *)&config->Hdcp22.DeviceId); + if (ret < 0) { + goto error_dt; + } + ret = of_property_read_u32(node, "xlnx,offset-hdcp-2-2", (u32 *)&config->Hdcp22.AddrOffset); + if (ret < 0) { + goto error_dt; + } +#if 1 + printk(KERN_INFO "Config.PPC %d\n", config->Ppc); + printk(KERN_INFO "Config.BPC %d\n", config->MaxBitsPerPixel); + printk(KERN_INFO "Config.IsHdmiRx %d\n", config->HdmiRx.IsPresent); + printk(KERN_INFO "Config.IsHdcp14 %d\n", config->Hdcp14.IsPresent); + printk(KERN_INFO "Config.IsHdcp22 %d\n", config->Hdcp22.IsPresent); + printk(KERN_INFO "Config.IsRemapper %lx\n", config->Remapper.IsPresent); + printk(KERN_INFO "Config.IsGpio %d\n", config->RemapperReset.IsPresent); + printk(KERN_INFO "Config.IsHdcpTimer %d\n", config->HdcpTimer.IsPresent); + printk(KERN_INFO "Config.Remap-devid %d\n", config->Remapper.DeviceId); + printk(KERN_INFO "Config.Remap-offset %lx\n", config->Remapper.AddrOffset); + printk(KERN_INFO "Config.gpio-devid %d\n", config->RemapperReset.DeviceId); + printk(KERN_INFO "Config.gpio-offset %p\n", config->RemapperReset.AddrOffset); + printk(KERN_INFO "Config.timer-devid %d\n", config->HdcpTimer.DeviceId); + printk(KERN_INFO "Config.timer-offset %lx\n", config->HdcpTimer.AddrOffset); + printk(KERN_INFO "Config.hdcp14-devid %d\n", config->Hdcp14.DeviceId); + printk(KERN_INFO "Config.hdcp14-offset %lx\n", config->Hdcp14.AddrOffset); + printk(KERN_INFO "Config.hdcp22-devid %d\n", config->Hdcp22.DeviceId); + printk(KERN_INFO "Config.hdcp22-offset %lx\n", config->Hdcp22.AddrOffset); #endif return 0; + +error_dt: + dev_err(dev, "Error Reading Xilinx Hdmi Rx Device Tree"); + return ret; } + static int xhdmirx_probe(struct platform_device *pdev) { struct v4l2_subdev *subdev; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b84d4ed650a79f..25689a9e4198cd 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -816,6 +816,15 @@ config XILINX_TRAFGEN If unsure, say N +config RETIMER_DP159 + tristate "Texas Instruments DP159 Redriver/retimer" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Texas Instruments DP159 Redriver/retimer. + + To compile this driver as a module, choose M here: the + module will be called dp159. + source "drivers/misc/jesd204b/Kconfig" source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b9523ce5da5f23..66ff27c8adba68 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_PANEL) += panel.o +obj-$(CONFIG_RETIMER_DP159) += dp159.o diff --git a/drivers/misc/dp159.c b/drivers/misc/dp159.c new file mode 100644 index 00000000000000..f55a1ad5e4ac0b --- /dev/null +++ b/drivers/misc/dp159.c @@ -0,0 +1,436 @@ +/* + * dp159 redriver and retimer + * Copyright (C) 2016 Leon Woestenberg <leon@sidebranch.com> + * + * based on dp159.c + * Copyright (C) 2007 Hans Verkuil + * + * 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; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of.h> +#include <linux/clk-provider.h> + +MODULE_DESCRIPTION("i2c device driver for dp159 redriver and retimer"); +MODULE_AUTHOR("Leon Woestenberg"); +MODULE_LICENSE("GPL"); + +static bool debug; + +module_param(debug, bool, 0644); + +MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); + +struct clk_tx_linerate { + struct clk_hw hw; + struct i2c_client *client; +}; + +static inline int dp159_write(struct i2c_client *client, u8 reg, u8 value) +{ + +#if 0 + struct i2c_client *client = v4l2_get_subdevdata(client); +#endif + return i2c_smbus_write_byte_data(client, reg, value); +} + +static inline int dp159_read(struct i2c_client *client, u8 reg) +{ + + return i2c_smbus_read_byte_data(client, reg); +} + +static int dp159_program(struct i2c_client *client, int mode) +{ + int r; + if (client->addr == 0x2C) { + switch (mode) { + /* HDMI 1.4 (250Mbps - 1.2Gbps) */ + case 0 : + // Select page 1 + r = dp159_write(client, 0xff, 0x01); + + // PLL_FBDIV is 280 + r = dp159_write(client, 0x04, 0x80); + r = dp159_write(client, 0x05, 0x02); + + // PLL_PREDIV is 2 + r = dp159_write(client, 0x08, 0x02); + + // CDR_CONFIG[4:0] + r = dp159_write(client, 0x0e, 0x10); + + // CP_CURRENT + r = dp159_write(client, 0x01, 0x81); + usleep_range(10000, 11000); + + // Enable Bandgap + r = dp159_write(client, 0x00, 0x02); + usleep_range(10000, 11000); + // Enable PLL + r = dp159_write(client, 0x00, 0x03); + + // Enable TX + r = dp159_write(client, 0x10, 0x0f); + + // HDMI_TWPST1 + r = dp159_write(client, 0x14, 0x10); + + // DP_TWPST1 + r = dp159_write(client, 0x16, 0x10); + + // DP_TWPST2 + r = dp159_write(client, 0x17, 0x00); + + // Slew CTRL + r = dp159_write(client, 0x12, 0x28); + + // FIR_UPD + r = dp159_write(client, 0x13, 0x0f); + r = dp159_write(client, 0x13, 0x00); + + // TX_RATE + r = dp159_write(client, 0x11, 0xC0); + + // Enable receivers + r = dp159_write(client, 0x30, 0x0f); + + // PD_RXINT + r = dp159_write(client, 0x32, 0x00); + + // RX_RATE + r = dp159_write(client, 0x31, 0xC0); + + // Disable offset correction + r = dp159_write(client, 0x34, 0x00); + + // Change default of CDR_STL + r = dp159_write(client, 0x3c, 0x04); + + // Change default of CDR_SO_TR + r = dp159_write(client, 0x3D, 0x06); + + // EQFTC + r = dp159_write(client, 0x4D, 0x38); + + // Enable Adaptive EQ + r = dp159_write(client, 0x4c, 0x03); + + // Select page 0 + r = dp159_write(client, 0xff, 0x00); + + // Gate HPD_SNK + r = dp159_write(client, 0x09, 0x01); + + // Set GPIO + r = dp159_write(client, 0xe0, 0x01); + + // Un gate HPD_SNK + r = dp159_write(client, 0x09, 0x00); + return 0; + break; + + case 1 : // HDMI 1.4 (1.2Gbps - 3Gbps) + // Select page 1 + r = dp159_write(client, 0xff, 0x01); + + // PLL_FBDIV is 140 + r = dp159_write(client, 0x04, 0x40); + r = dp159_write(client, 0x05, 0x01); + + // PLL_PREDIV is 4 + r = dp159_write(client, 0x08, 0x04); + + // CDR_CONFIG[4:0] + r = dp159_write(client, 0x0e, 0x10); + + // CP_CURRENT + r = dp159_write(client, 0x01, 0x81); + usleep_range(10000, 11000); + // Enable Bandgap + r = dp159_write(client, 0x00, 0x02); + usleep_range(10000, 11000); + // Enable PLL + r = dp159_write(client, 0x00, 0x03); + + // Enable TX + r = dp159_write(client, 0x10, 0x0f); + + // HDMI_TWPST1 + r = dp159_write(client, 0x14, 0x10); + + // DP_TWPST1 + r = dp159_write(client, 0x16, 0x10); + + // DP_TWPST2 + r = dp159_write(client, 0x17, 0x00); + + // Slew CTRL + r = dp159_write(client, 0x12, 0x28); + + // FIR_UPD + r = dp159_write(client, 0x13, 0x0f); + r = dp159_write(client, 0x13, 0x00); + + // TX_RATE + r = dp159_write(client, 0x11, 0x70); + + // Enable receivers + r = dp159_write(client, 0x30, 0x0f); + + // PD_RXINT + r = dp159_write(client, 0x32, 0x00); + + // RX_RATE + r = dp159_write(client, 0x31, 0x40); + + // Disable offset correction + r = dp159_write(client, 0x34, 0x00); + + // Change default of CDR_STL + r = dp159_write(client, 0x3c, 0x04); + + // Change default of CDR_SO_TR + r = dp159_write(client, 0x3D, 0x06); + + // EQFTC + r = dp159_write(client, 0x4D, 0x28); + + // Enable Adaptive EQ + r = dp159_write(client, 0x4c, 0x03); + + // Select page 0 + r = dp159_write(client, 0xff, 0x00); + + // Gate HPD_SNK + r = dp159_write(client, 0x09, 0x01); + + // Set GPIO + r = dp159_write(client, 0xe0, 0x01); + + // Un gate HPD_SNK + r = dp159_write(client, 0x09, 0x00); + return 0; + break; + + case 2 : // HDMI 2.0 (3.4Gbps - 6 Gbps) + + // Select page 1 + r = dp159_write(client, 0xff, 0x01); + + // PLL_FBDIV is 280 + r = dp159_write(client, 0x04, 0x80); + r = dp159_write(client, 0x05, 0x02); + + // PLL_PREDIV is 4 + r = dp159_write(client, 0x08, 0x04); + + // CDR_CONFIG[4:0] + r = dp159_write(client, 0x0e, 0x10); + + // CP_CURRENT + r = dp159_write(client, 0x01, 0x81); + usleep_range(10000, 11000); + // Enable Bandgap + r = dp159_write(client, 0x00, 0x02); + usleep_range(10000, 11000); + // Enable PLL + r = dp159_write(client, 0x00, 0x03); + + // Enable TX + r = dp159_write(client, 0x10, 0x0f); + + // HDMI_TWPST1 + r = dp159_write(client, 0x14, 0x10); + + // DP_TWPST1 + r = dp159_write(client, 0x16, 0x10); + + // DP_TWPST2 + r = dp159_write(client, 0x17, 0x00); + + // Slew CTRL + r = dp159_write(client, 0x12, 0x28); + + // FIR_UPD + r = dp159_write(client, 0x13, 0x0f); + r = dp159_write(client, 0x13, 0x00); + + // TX_RATE + r = dp159_write(client, 0x11, 0x30); + + // Enable receivers + r = dp159_write(client, 0x30, 0x0f); + + // PD_RXINT + r = dp159_write(client, 0x32, 0x00); + + // RX_RATE + r = dp159_write(client, 0x31, 0x00); + + // Disable offset correction + r = dp159_write(client, 0x34, 0x00); + + // Change default of CDR_STL + r = dp159_write(client, 0x3c, 0x04); + + // Change default of CDR_SO_TR + r = dp159_write(client, 0x3D, 0x06); + + // EQFTC + r = dp159_write(client, 0x4D, 0x18); + + // Enable Adaptive EQ + r = dp159_write(client, 0x4c, 0x03); + + // Select page 0 + r = dp159_write(client, 0xff, 0x00); + + // Gate HPD_SNK + r = dp159_write(client, 0x09, 0x01); + + // Set GPIO + r = dp159_write(client, 0xe0, 0x01); + + // Un gate HPD_SNK + r = dp159_write(client, 0x09, 0x00); + return 0; + break; + } /* switch (mode) */ + /* DP159 ES? */ + } else if (client->addr == 0x5C) { + if (mode == 2) { + r = dp159_write(client, 0x0A, 0x36); // Automatic retimer for HDMI 2.0 + r = dp159_write(client, 0x0B, 0x1a); + + r = dp159_write(client, 0x0C, 0xa1); + r = dp159_write(client, 0x0D, 0x00); + } else { + r = dp159_write(client, 0x0A, 0x35); // Automatic redriver to retimer crossover at 1.0 Gbps + //r = dp159_write(client, 0x0A, 0x34); // The redriver mode must be selected to support low video rates + r = dp159_write(client, 0x0B, 0x01); + r = dp159_write(client, 0x0C, 0xA0); // Set VSWING data decrease by 24% + r = dp159_write(client, 0x0D, 0x00); + } + } +} + +#define to_clk_tx_linerate(_hw) container_of(_hw, struct clk_tx_linerate, hw) + +int clk_tx_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) +{ + struct clk_tx_linerate *clk; + clk = to_clk_tx_linerate(hw); + return 0; +}; + +int clk_tx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_tx_linerate *clk; + clk = to_clk_tx_linerate(hw); + return 0; +}; + +long clk_tx_round_rate(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate) +{ + struct clk_tx_linerate *clk; + clk = to_clk_tx_linerate(hw); + return 0; +}; + +struct clk_ops clk_tx_rate_ops = { + .set_rate = &clk_tx_set_rate, + .recalc_rate = &clk_tx_recalc_rate, + .round_rate = &clk_tx_round_rate, +}; + +static int dp159_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct clk_tx_linerate *clk_tx; + struct clk_init_data init; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + /* allocate fixed-rate clock */ + clk_tx = kzalloc(sizeof(*clk_tx), GFP_KERNEL); + if (!clk_tx) + return -ENOMEM; + + init.name = "clk_tx_linerate"; + init.ops = &clk_tx_rate_ops; + init.flags = /*flags |*/ CLK_IS_BASIC; + init.parent_names = NULL; + init.num_parents = 0; + + /* register the clock */ + clk_tx = clk_register(&client->dev, &clk_tx->hw); + if (IS_ERR(clk_tx)) { + kfree(clk_tx); + return ERR_PTR(clk_tx); + } + /* reference to client in clock */ + clk_tx->client = client; + /* reference to clk in client */ + i2c_set_clientdata(client, (void *)clk_tx); + + return 0; +} + +static int dp159_remove(struct i2c_client *client) +{ + struct clk_tx_linerate *clk_tx; + clk_tx = (struct clk_tx_linerate *)i2c_get_clientdata(client); + if (clk_tx) + clk_unregister(clk_tx); + return 0; +} + +static const struct i2c_device_id dp159_id[] = { + { "dp159", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, dp159_id); + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id dp159_of_match[] = { + { .compatible = "ti,dp159", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, dp159_of_match); +#endif + +static struct i2c_driver dp159_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "dp159", + .of_match_table = of_match_ptr(dp159_of_match), + }, + .probe = dp159_probe, + .remove = dp159_remove, + .id_table = dp159_id, +}; + +module_i2c_driver(dp159_driver); diff --git a/drivers/phy/phy-vphy.c b/drivers/phy/phy-vphy.c index 525d4c6c3d310d..bb48f75d25ff94 100644 --- a/drivers/phy/phy-vphy.c +++ b/drivers/phy/phy-vphy.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <dt-bindings/phy/phy.h> #include <linux/list.h> +#include <linux/slab.h> #include <linux/interrupt.h> #include "linux/phy/phy-vphy.h" @@ -475,6 +476,8 @@ static int xvphy_probe(struct platform_device *pdev) struct xvphy_dev *vphydev; struct phy_provider *provider; struct phy *phy; + struct clk *clk; + struct resource *res; int lanecount, port = 0, index = 0; int ret; |