Add suppport for sn65dsi86 bridge chip and Innolux 2k edp panel
Subsystems (7)
v5 cover Add suppport for sn65dsi86 bridge chip and Innolux 2k edp panel
Changes in current patchset:
- Separate panel driver change from dt-binding documentation.
- Add the properties from simple-panel binding that are applicable to this edp panel dt-binding.
- Fix the warnings in bridge driver, reported by Kbuild test robot.
Sandeep Panda (4):
drm/bridge: add support for sn65dsi86 bridge driver
dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings drm/panel: add Innolux TV123WAM panel driver support
dt-bindings: drm/panel: Document Innolux TV123WAM panel bindings
.../bindings/display/bridge/ti,sn65dsi86.txt | 76 +++ .../bindings/display/panel/innolux,tv123wam.txt | 20 + drivers/gpu/drm/bridge/Kconfig | 9 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/ti-sn65dsi86.c | 725 +++++++++++++++++++++ drivers/gpu/drm/panel/panel-simple.c | 27 + 6 files changed, 858 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 1525235522-8954-1-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
PATCH v5 1/4 drm/bridge: add support for sn65dsi86 bridge driver
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.
Changes in v5:
- Fixed Kbuild test service reported warnings.
--- drivers/gpu/drm/bridge/Kconfig | 9 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/ti-sn65dsi86.c | 725 ++++++++++++++++++++++++++++++++++ 3 files changed, 735 insertions(+) create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.c
drivers/gpu/drm/bridge/Kconfig +9 -0
@@ -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"
drivers/gpu/drm/bridge/Makefile +1 -0
@@ -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/
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +725 -0
725 lines not on this page · raw message
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [PATCH v5 1/4] drm/bridge: add support for sn65dsi86 bridge driver
Quoted 45 lines · Sandeep Panda
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 ani2c_adapterand usedrm_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 ofirq_gpioand 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).
Quoted 10 lines
Changes in v4:
- Update License/Copyright (Sean Paul).
- AddKconfigandMakefilechanges (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 topower_ctrlAPI to avoid race conditions (Sean Paul).
- Add support to parse reference clk frequency from dt(optional).
- Update the bridge chip enable/disable sequence.
It seems like you also added 2 new supply names, as well as remove the configurable gpios?
Quoted 127 lines
Changes in v5:
- FixedKbuildtest service reported warnings.Signed-off-by Sandeep Panda <[email protected]>--- drivers/gpu/drm/bridge/Kconfig | 9 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/ti-sn65dsi86.c | 725 ++++++++++++++++++++++++++++++++++ 3 files changed, 735 insertions(+) create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.cdrivers/gpu/drm/bridge/Kconfig +9
-0@@ -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"drivers/gpu/drm/bridge/Makefile +1
-0@@ -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/drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +79
-0@@ -0,0 +1,725 @@ +// 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_HPD_DISABLE_REG 0x5C +#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)) +#define SN_HPD_DISABLE_BIT BIT(0) + +struct ti_sn_bridge { +struct device *dev; +struct regmap *regmap; +struct drm_bridge bridge;
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 89
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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;
You only use this in one function, it should be a local.
Quoted 20 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +20
-0+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 , +};
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 119
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ +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--;
I think you should use a kref instead of rolling your own ref_count. You can handle release by calling kref_put_mutex(), which will handle the reference and the lock. On the acquire side, you can use kref_get_unless_zero which will be fast if the reference is already active.
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 125
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+ +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" );
print ret on failure
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 136
Quoted 11 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +11
-0+ 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);
No need for this.
Quoted 17 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +17
-0+ } + +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);
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 163
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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 */
This comment isn't useful.
Quoted 101 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +101
-0+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); +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[] = { +"vcca" , +"vcc" , +"vccio" , +"vpll" , +}; + +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,
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 274
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ 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) {
Flip this to avoid indenting the whole function. ie:
if (!port)
return 0;
Quoted 12 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +12
-0+ 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 ;
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 296
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ } + + 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" );
This log should be DRM_DEBUG_KMS and you should be more descriptive in your message (ie: "Attached sn65dsi86 panel").
Quoted 55 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +55
-0+ } + +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 ; +
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 361
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ 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" );
Same comment here regarding being more descriptive.
Quoted 46 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +46
-0+/* 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 */ +static u32 ti_sn_bridge_ref_clk_table[] = { +12000 , +19200 , +26000 , +27000 , +38400 , +};
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 417
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ +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 )));
What if the refclk frequency isn't found?
Quoted 36 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +36
-0+} + +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) /
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 463
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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);
I think this can be simplified.
/* Array index corresponds to register value */
static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
};static void ti_sn_bridge_set_dsi_dp_rate(struct ti_sn_bridge *pdata)
{
...
for (i = ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i >= 0; i--) {
if (ti_sn_bridge_dp_rate_lut[i] <= dp_rate_mhz)
break;
}
regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG,
SN_DP_DATA_RATE_BITS, i << SN_DP_DATA_RATE_OFFSET);
}Quoted 23 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +23
-0+} + +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) >>
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 496
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ 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 */
You would probably be fine to set the upper bound to 10500 so we don't trigger an unnecessary interrupt.
Quoted 113 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +113
-0+} + +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); +/* in case drm_panel is connected then HPD is not supported */ +regmap_update_bits (pdata->regmap,SN_HPD_DISABLE_REG , +SN_HPD_DISABLE_BIT ,SN_HPD_DISABLE_BIT ); + } + +/* 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); +} + +static 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); +} + +static 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;
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 619
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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 );
pdata = devm_kzalloc(&client->dev, sizeof(struct ti_sn_bridge),
GFP_KERNEL);drivers/gpu/drm/bridge/ti-sn65dsi86.c line 624
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+if (!pdata) +return -ENOMEM ; + + pdata->dev = &client->dev; +DRM_DEBUG ("I2C address is %x\n" , client->addr);
unnecessary
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 627
Quoted 3 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +3
-0+ + pdata->regmap =devm_regmap_init_i2c (client, + &ti_sn_bridge_regmap_config);
indentation is wrong here, should be:
pdata->regmap = devm_regmap_init_i2c(client,
&ti_sn_bridge_regmap_config);drivers/gpu/drm/bridge/ti-sn65dsi86.c line 628
Quoted 1 line
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +1
-0+if (IS_ERR (pdata->regmap))
Print an error?
Quoted 13 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +13
-0+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" );
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 651
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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)
DRM_ERROR?
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 663
Quoted 12 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +12
-0+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" );
You've copied dev_dbg() logs, they should be DRM_DEBUG_KMS().
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 668
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+ } + +ti_sn_bridge_power_ctrl (pdata, true); + ret =ti_sn_bridge_read_device_rev (pdata); +ti_sn_bridge_power_ctrl (pdata, false);
This could be done before handling refclk or ddc.
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 680
Quoted 12 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +12
-0+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" );
unnecessary
Quoted 49 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +45
-0+ +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" , + .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" );Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Signature · 5 lines
Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v5 1/4] drm/bridge: add support for sn65dsi86 bridge driver
Quoting Sean Paul (2018-05-02 12:03:16)
Quoted 29 lines · Sandeep Panda
Quoted 28 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +27
-0+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)
Quoted 8 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 119
Quoted 3 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +3
-0+ pdata->ctrl_ref_count++; + else + pdata->ctrl_ref_count--;I think you should use a kref instead of rolling your own
ref_count. You can handle release by callingkref_put_mutex(), which will handle the reference and the lock. On the acquire side, you can usekref_get_unless_zerowhich will be fast if the reference is already active.
Why not use runtime PM?
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 152573164597.138124.14000479717180675318-n1Xw8LXHxjTHt/[email protected]
Re: [PATCH v5 1/4] drm/bridge: add support for sn65dsi86 bridge driver
Quoted 39 lines · Stephen Boyd
Quoting Sean Paul (2018-05-02 12:03:16)
Quoted 29 lines · Sandeep Panda
Quoted 28 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +27
-0+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)Quoted 8 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 119
Quoted 3 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +3
-0+ pdata->ctrl_ref_count++; + else + pdata->ctrl_ref_count--;I think you should use a kref instead of rolling your own
ref_count. You can handle release by callingkref_put_mutex(), which will handle the reference and the lock. On the acquire side, you can usekref_get_unless_zerowhich will be fast if the reference is already active.
Quoted 1 line
Why not use runtime PM?
I think PM runtime will be a better approach since we are trying to protect bridge power source related resources here.
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [PATCH v5 1/4] drm/bridge: add support for sn65dsi86 bridge driver
In reply to Sean PaulQuoted 199 lines · Sean Paul
Quoted 51 lines · Sandeep Panda
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 ani2c_adapterand usedrm_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 ofirq_gpioand 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).Quoted 11 lines
Changes in v4:
- Update License/Copyright (Sean Paul).
- AddKconfigandMakefilechanges (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 topower_ctrlAPI to avoid race conditions (Sean Paul).
- Add support to parse reference clk frequency from dt(optional).
- Update the bridge chip enable/disable sequence.It seems like you also added 2 new supply names, as well as remove the configurable gpios?
Quoted 132 lines
Changes in v5:
- FixedKbuildtest service reported warnings.Signed-off-by Sandeep Panda <[email protected]>--- drivers/gpu/drm/bridge/Kconfig | 9 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/ti-sn65dsi86.c | 725 ++++++++++++++++++++++++++++++++++ 3 files changed, 735 insertions(+) create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.cdrivers/gpu/drm/bridge/Kconfig +9
-0@@ -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"drivers/gpu/drm/bridge/Makefile +1
-0@@ -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/drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +83
-0@@ -0,0 +1,725 @@ +// 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_HPD_DISABLE_REG 0x5C +#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)) +#define SN_HPD_DISABLE_BIT BIT(0) + +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;
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 89
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+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;You only use this in one function, it should be a local.
Removed.
Quoted 29 lines
Quoted 29 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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 ={
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +12
-0+ .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, boolenable)
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+{ +int ret =0 ; + +mutex_lock (&pdata->lock); +if (enable)
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 119
Quoted 3 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +3
-0+ pdata->ctrl_ref_count++; + else + pdata->ctrl_ref_count--;I think you should use a kref instead of rolling your own
ref_count. You can handle release by callingkref_put_mutex(), which will handle the reference and the lock. On the acquire side, you can usekref_get_unless_zerowhich will be fast if the reference is already active.
As per comment from Stephen Boyd used PM runtime instead of our own ref_count.
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 125
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+ +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" );print ret on failure
Done.
Quoted 5 lines
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+ goto exit; + } + +gpiod_set_value (pdata->enable_gpio,1 ); + }else if (!enable && !pdata->ctrl_ref_count) {
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 136
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+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);No need for this.
Removed.
Quoted 22 lines
Quoted 22 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +15
-0+ } + +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)
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+{ +struct ti_sn_bridge *pdata =connector_to_ti_sn_bridge (connector); +struct drm_panel *panel = pdata->panel; +struct edid *edid; + +if (panel) {
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 163
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+DRM_DEBUG ("get mode from connected drm_panel\n" ); + pdata->num_modes =drm_panel_get_modes (panel); +return pdata->num_modes; + } + +/* get from EDID */ This comment isn't useful.
Removed.
Quoted 119 lines
Quoted 106 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +28
-0+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); +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= {drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+ .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, boolforce)
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +15
-0+{ +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= {
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+ .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,drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +4
-0+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static struct ti_sn_bridge *bridge_to_ti_sn_bridge(struct drm_bridge*bridge)
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +43
-0+{ + 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[] = { +"vcca" , +"vcc" , +"vccio" , +"vpll" , +}; + +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,drivers/gpu/drm/bridge/ti-sn65dsi86.c line 274
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ 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) {Flip this to avoid indenting the whole function. ie:
Quoted 3 lines
if (!port)
return 0;
Done.
Quoted 17 lines
Quoted 17 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +17
-0+ 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) {
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 296
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+DRM_ERROR ("no panel node found\n" ); +return -EINVAL ; + } +drm_panel_attach (pdata->panel, &pdata->connector); +DRM_DEBUG ("panel attached\n" );This log should be
DRM_DEBUG_KMSand you should be more descriptive in your message (ie: "Attached sn65dsi86 panel").
Updated the debug log.
Quoted 121 lines
Quoted 57 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +35
-0+ } + +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);drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +18
-0+ + 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|drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +2
-0+MIPI_DSI_MODE_EOT_PACKET |MIPI_DSI_MODE_VIDEO_HSE ; +drivers/gpu/drm/bridge/ti-sn65dsi86.c line 361
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+ 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" );Same comment here regarding being more descriptive.
Quoted 51 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +13
-0+/* 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",
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +37
-0+ 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 */ +static 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 ;
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 417
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-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 )));What if the refclk frequency isn't found?
If refclk frequency is not found then we will program i=5, which is also valid as per datasheet, this means 19.2MHz.
Quoted 66 lines
Quoted 46 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +36
-0+} + +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) /drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +8
-0+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;drivers/gpu/drm/bridge/ti-sn65dsi86.c line 463
Quoted 2 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +2
-0+regmap_update_bits (pdata->regmap,SN_DATARATE_CONFIG_REG , +SN_DP_DATA_RATE_BITS , val);I think this can be simplified.
/* Array index corresponds to register value */
static const unsigned int ti_sn_bridge_dp_rate_lut[] = { 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 };static void
ti_sn_bridge_set_dsi_dp_rate(struct ti_sn_bridge *pdata){ ... for (i = ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i >= 0; i--) { if (ti_sn_bridge_dp_rate_lut[i] <= dp_rate_mhz) break; } regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG, SN_DP_DATA_RATE_BITS, i <<
Quoted 3 lines
SN_DP_DATA_RATE_OFFSET);
}
As per datasheet we have to program the dp data rate greater than stream rate.
In order to support the panel stream bit rate, the SN65DSI86 eDP interface must be programmed so that the total eDP data rate is greater than the stream bit rate.
Quoted 29 lines
Quoted 29 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +3
-0+} + +static void ti_sn_bridge_set_video_timings(struct ti_sn_bridge*pdata)
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +25
-0+{ +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 );
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 496
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+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 */ You would probably be fine to set the upper bound to 10500 so we don't trigger an unnecessary interrupt.
Done.
Quoted 129 lines
Quoted 115 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +34
-0+} + +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); +/* in case drm_panel is connected then HPD is not supported */ +regmap_update_bits (pdata->regmap,SN_HPD_DISABLE_REG , +SN_HPD_DISABLE_BIT ,SN_HPD_DISABLE_BIT ); + } + +/* 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
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +2
-0+* this method is enabled by default. An eDP panel must support this +* authentication method. We need to enable this method in the eDP panel
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +77
-0+* 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); +} + +static 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); +} + +static 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;drivers/gpu/drm/bridge/ti-sn65dsi86.c line 619
Quoted 10 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +10
-0+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 );pdata = devm_kzalloc(&client->dev, sizeof(struct ti_sn_bridge), GFP_KERNEL);
Quoted 8 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 624
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+if (!pdata) +return -ENOMEM ; + + pdata->dev = &client->dev; +DRM_DEBUG ("I2C address is %x\n" , client->addr);unnecessary
Removed
Quoted 31 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 627
Quoted 3 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +3
-0+ + pdata->regmap =devm_regmap_init_i2c (client, + &ti_sn_bridge_regmap_config);indentation is wrong here, should be:
pdata->regmap = devm_regmap_init_i2c(client,
&ti_sn_bridge_regmap_config);drivers/gpu/drm/bridge/ti-sn65dsi86.c line 628
Quoted 1 line
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +1
-0+if (IS_ERR (pdata->regmap))Print an error?
Quoted 17 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +17
-0+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,
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 651
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+ "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)
DRM_ERROR?
I am already printing error in ti_sn_bridge_parse_dsi_host() so removed from here as per comment from Jordan Crouse.
Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+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);
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 663
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+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" );You've copied
dev_dbg()logs, they should beDRM_DEBUG_KMS().
Done.
Quoted 8 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 668
Quoted 5 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +5
-0+ } + +ti_sn_bridge_power_ctrl (pdata, true); + ret =ti_sn_bridge_read_device_rev (pdata); +ti_sn_bridge_power_ctrl (pdata, false);This could be done before handling refclk or ddc.
Moved before refclk and ddc handing.
Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+if (ret) +return ret; + +i2c_set_clientdata (client, pdata); +mutex_init (&pdata->lock); +
Quoted 9 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c line 680
Quoted 6 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +6
-0+ 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" );unnecessary
Removed
Quoted 41 lines
Quoted 41 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +41
-0+ +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" , + .of_match_table = ti_sn_bridge_match_table, + }, + .probe = ti_sn_bridge_probe, + .remove = ti_sn_bridge_remove, + .id_table = ti_sn_bridge_id, +};
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/bridge/ti-sn65dsi86.c new file +4
-1+ +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
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH v5 2/4 dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
In reply to a message not in the archiveDocument the bindings used for the sn65dsi86 DSI to eDP bridge.
Changes in v1:
- Rephrase the dt-binding descriptions to be more inline with existing bindings (Andrzej Hajda).
- Add missing dt-binding that are parsed by corresponding driver (Andrzej Hajda).
Changes in v2:
- Remove edp panel specific dt-binding entries. Only keep bridge
specific entries (Sean Paul).
- Remove custom-modes dt entry since its usage is removed from driver also (Sean Paul).
- Remove is-pluggable dt entry since this will not be needed anymore (Sean Paul).
Changes in v3:
- Remove irq-gpio dt entry and instead populate is an interrupt property (Rob Herring).
Changes in v4:
- Add link to bridge chip datasheet (Stephen Boyd)
- Add vpll and vcc regulator supply bindings (Stephen Boyd)
- Add ref clk optional dt binding (Stephen Boyd)
- Add gpio-controller optional dt binding (Stephen Boyd)
--- .../bindings/display/bridge/ti,sn65dsi86.txt | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt new file +76 -0
@@ -0,0 +1,76 @@ +SN65DSI86 DSI to eDP bridge chip +-------------------------------- + +This is the binding for Texas Instruments SN65DSI86 bridge. +http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf + +Required properties: +- compatible: Must be "ti,sn65dsi86" +- reg: i2c address of the chip, 0x2d as per datasheet +- enable-gpios: OF device-tree gpio specification for bridge_en pin + +- vccio-supply: A 1.8V supply that powers up the digital IOs. +- vpll-supply: A 1.8V supply that powers up the displayport PLL. +- vcca-supply: A 1.2V supply that powers up the analog circuits. +- vcc-supply: A 1.2V supply that powers up the digital core. + +Optional properties: +- interrupts: Specifier for the SN65DSI86 interrupt line. +- hpd-gpios: OF device-tree gpio specifications for HPD pin. + +- refclk-freq-khz: Value specifying the frequency of reference clock in KHz unit. + +- gpio-controller: Marks the device has a GPIO controller. +- #gpio-cells: Number of GPIO cells. Refer to binding document "gpio/gpio.txt" +- #pwm-cells : Number of cells used to specify a PWM. See pwm.txt in this directory + for a description of the cell formats. + +Required nodes: + +This device has two video ports. Their connections are modelled using the +OF graph bindings specified in Documentation/devicetree/bindings/graph.txt. + +- Video port 0 for DSI input +- Video port 1 for eDP output + +Example +------- + +edp-bridge@2d { + compatible = "ti,sn65dsi86"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2d>; + + enable-gpios = <&msmgpio 33 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio3>; + interrupts = <4 IRQ_TYPE_EDGE_FALLING>; + + vccio-supply = <&pm8916_l17>; + vcca-supply = <&pm8916_l6>; + vpll-supply = <&pm8916_l17>; + vcc-supply = <&pm8916_l6>; + + refclk-freq-khz = <19200>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + edp_bridge_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + + port@1 { + reg = <1>; + + edp_bridge_out: endpoint { + remote-endpoint = <&edp_panel_in>; + }; + }; + }; +}
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 1525235522-8954-3-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
Re: [PATCH v5 2/4] dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
Quoting Sandeep Panda (2018-05-01 21:32:00)
Quoted 17 lines
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt new file +11
-0@@ -0,0 +1,76 @@ +SN65DSI86 DSI to eDP bridge chip +-------------------------------- + +This is the binding for Texas Instruments SN65DSI86 bridge. +http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf + +Required properties: +- compatible: Must be "ti,sn65dsi86" +- reg: i2c address of the chip, 0x2d as per datasheet +- enable-gpios: OF device-tree gpio specification for bridge_en pin +
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt line 21
Quoted 10 lines
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt new file +10
-0+- vccio-supply: A 1.8V supply that powers up the digital IOs. +- vpll-supply: A 1.8V supply that powers up the displayport PLL. +- vcca-supply: A 1.2V supply that powers up the analog circuits. +- vcc-supply: A 1.2V supply that powers up the digital core. + +Optional properties: +- interrupts: Specifier for the SN65DSI86 interrupt line. +- hpd-gpios: OF device-tree gpio specifications for HPD pin. + +- refclk-freq-khz: Value specifying the frequency of reference clock in KHz unit.
Please use the clocks property instead. We may need to turn the clk on first before this can work so the driver would use the clk framework (at least in linux). clock-names could have 'refclk' because that's the pin name.
Is there a way in DRM to figure out the frequency of the clock frequency for DACP/N? It looks like if refclk is grounded, then the DACP/N pins from the DSI side should be one of a set of frequencies, so I'm just curious how that will work and if the binding would need to be updated to indicate what the frequency of the DSI clock lane is, or if DRM can tell this driver through the port/graph stuff somehow.
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt line 24
Quoted 3 lines
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt new file +3
-0+ +- gpio-controller: Marks the device has a GPIO controller. +- #gpio-cells: Number of GPIO cells. Refer to binding document "gpio/gpio.txt"
What's the number? 2?
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt line 26
Quoted 2 lines
Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt new file +2
-0+- #pwm-cells : Number of cells used to specify a PWM. See pwm.txt in this directory + for a description of the cell formats.
What's the number? 1? There's a pwm.txt in this directory?
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 152528047237.138124.6199225836688931193-n1Xw8LXHxjTHt/[email protected]
Re: [PATCH v5 2/4] dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
Quoted 36 lines · Stephen Boyd
Quoting Sandeep Panda (2018-05-01 21:32:00)
Quoted 28 lines
(quoted diff) +0
-0
b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txtDocumentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt new file +21
-0@@ -0,0 +1,76 @@ +SN65DSI86 DSI to eDP bridge chip +-------------------------------- + +This is the binding for Texas Instruments SN65DSI86 bridge. +http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf + +Required properties: +- compatible: Must be "ti,sn65dsi86" +- reg: i2c address of the chip, 0x2d as per datasheet +- enable-gpios: OF device-tree gpio specification for bridge_en pin + +- vccio-supply: A 1.8V supply that powers up the digital IOs. +- vpll-supply: A 1.8V supply that powers up the displayport PLL. +- vcca-supply: A 1.2V supply that powers up the analog circuits. +- vcc-supply: A 1.2V supply that powers up the digital core. + +Optional properties: +- interrupts: Specifier for the SN65DSI86 interrupt line. +- hpd-gpios: OF device-tree gpio specifications for HPD pin. + +- refclk-freq-khz: Value specifying the frequency of reference clockQuoted 1 line
in KHz unit.
Please use the clocks property instead. We may need to turn the clk on first before this can work so the driver would use the clk framework (at least in linux). clock-names could have 'refclk' because that's the pin name.
Quoted 7 lines
Is there a way in DRM to figure out the frequency of the clock frequency for DACP/N? It looks like if refclk is grounded, then the DACP/N pins from the DSI side should be one of a set of frequencies, so I'm just curious how that will work and if the binding would need to be updated to indicate what the frequency of the DSI clock lane is, or if DRM can tell this driver through the port/graph stuff somehow.
Can we do something like below?
1. Add a required dt-property to indicate what is the source of
refclk, ti,sn-refclk-src = <0> ---> means refclk is derived from refclk pin.
ti,sn-refclk-src = <1> ---> means refclk is derived from DACP/N pin.
2. Add a clock property to indicate the refclk frequency for refclk
pin.
3. In driver, parse the refclk source dt-property. If the source is
refclk pin then get the frquency from clock dt-property and program the i2c register accordingly.
Else if the source is DACP/N pin then calculate the DSIA frequency
based on current display mode (by the time we go for configuring refclk, drm_mode_set is already done and in diver we can calculate the frequency) and program the i2c register accordingly.
Quoted 6 lines
Quoted 4 lines
+
+- gpio-controller: Marks the device has a GPIO controller. +- #gpio-cells: Number of GPIO cells. Refer to binding document"
gpio/gpio.txt"What's the number? 2?
number is 4, i will update this in binding
Quoted 6 lines
Quoted 4 lines
+- #pwm-cells : Number of cells used to specify a PWM. See pwm.txt in this directory
+ for a description of the cell formats.What's the number? 1? There's a pwm.txt in this directory?
yes number is 1, i will update the binding. it should be pwm/pwm.txt
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 3c44e961a198e20a606742034152d456-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
Re: [PATCH v5 2/4] dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
Quoting [email protected] (2018-05-03 02:41:29)
Quoted 28 lines · Stephen Boyd
Quoted 13 lines
Quoting Sandeep Panda (2018-05-01 21:32:00)
Quoted 5 lines
(quoted diff) +0
-0
a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txtb/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txtnew file mode 100644
index 0000000..0d042cePlease use the clocks property instead. We may need to turn the clk on first before this can work so the driver would use the clk framework (at
least in linux). clock-names could have 'refclk' because that's the pin name.Quoted 8 lines
Is there a way in DRM to figure out the frequency of the clock frequency
for DACP/N? It looks like if refclk is grounded, then the DACP/N pins from the DSI side should be one of a set of frequencies, so I'm just curious how that will work and if the binding would need to be updated to indicate what the frequency of the DSI clock lane is, or if DRM can tell this driver through the port/graph stuff somehow.Can we do something like below?
1. Add a required dt-property to indicate what is the source of
refclk, ti,sn-refclk-src = <0> ---> means refclk is derived from refclk pin.
Quoted 10 lines
ti,sn-refclk-src = <1> ---> means refclk is derived from DACP/N pin.
2. Add a clock property to indicate the refclk frequency for refclk
pin.
3. In driver, parse the refclk source dt-property. If the source is
refclk pin then get the frquency from clock dt-property and program the i2c register accordingly.
Else if the source is DACP/N pin then calculate the DSIA frequency
based on current display mode (by the time we go for configuring refclk,drm_mode_setis already done and in diver we can calculate the frequency) and program the i2c register accordingly.
The presence or non-presence of the refclk should still be indicated via the standard clock property instead of some TI specific property. The driver can try to clk_get() the refclk and if its there it can call clk_get_rate() to figure out the reference clk frequency. It should also turn it on with clk_prepare_enable() to make sure the clk is clocking and turn it off when the driver isn't using it.
If the reference clk is recovered from the DACP/N pin then there won't be a clocks property, and the driver can do what you describe in #3.
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
+
+- gpio-controller: Marks the device has a GPIO controller. +- #gpio-cells: Number of GPIO cells. Refer to binding document"
gpio/gpio.txt"What's the number? 2?
number is 4, i will update this in binding
Really? What do you need 4 cells for? The number of cells doesn't indicate the number of GPIOs on the device.
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 152573150728.138124.7552894725134629406-n1Xw8LXHxjTHt/[email protected]
Re: [PATCH v5 2/4] dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
Quoted 60 lines · Stephen Boyd
Quoting [email protected] (2018-05-03 02:41:29)
Quoted 29 lines · Stephen Boyd
Quoted 13 lines
Quoting Sandeep Panda (2018-05-01 21:32:00)
Quoted 5 lines
diff --git
a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txtb/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txtnew file mode 100644
index 0000000..0d042cePlease use the clocks property instead. We may need to turn the clk on first before this can work so the driver would use the clk framework (at
least in linux). clock-names could have 'refclk' because that's the pin name.Quoted 8 lines
Is there a way in DRM to figure out the frequency of the clock frequency
for DACP/N? It looks like if refclk is grounded, then the DACP/N pins from the DSI side should be one of a set of frequencies, so I'm just curious how that will work and if the binding would need to be updated to indicate what the frequency of the DSI clock lane is, or if DRM can tell this driver through the port/graph stuff somehow.Can we do something like below?
1. Add a required dt-property to indicate what is the source of
refclk, ti,sn-refclk-src = <0> ---> means refclk is derived from refclk pin.ti,sn-refclk-src = <1> ---> means refclk is derived from DACP/NQuoted 13 lines
pin.
2. Add a clock property to indicate the refclk frequency for
refclk
pin.
3. In driver, parse the refclk source dt-property. If the source
is
refclk pin then get the frquency from clock dt-property and program the i2c register accordingly.
Else if the source is DACP/N pin then calculate the DSIA
frequency
based on current display mode (by the time we go for configuring refclk,drm_mode_setis already done and in diver we can calculate the frequency) and program the i2c register accordingly.The presence or non-presence of the refclk should still be indicated via the standard clock property instead of some TI specific property. The driver can try to
clk_get()the refclk and if its there it can callclk_get_rate()to figure out the reference clk frequency. It should also turn it on withclk_prepare_enable()to make sure the clk is clocking and turn it off when the driver isn't using it.If the reference clk is recovered from the DACP/N pin then there won't be a clocks property, and the driver can do what you describe in #3.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
+
+- gpio-controller: Marks the device has a GPIO controller. +- #gpio-cells: Number of GPIO cells. Refer to binding document"
gpio/gpio.txt"
Quoted 5 lines
Quoted 2 lines
Quoted 1 line
What's the number? 2?
number is 4, i will update this in binding
Really? What do you need 4 cells for? The number of cells doesn't indicate the number of GPIOs on the device.
It should be 2, got confused with number GPIOs.
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH v5 3/4 drm/panel: add Innolux TV123WAM panel driver support
In reply to a message not in the archiveAdd support for Innolux TV123WAM, which is a 12.3" eDP display panel with 2160x1440 resolution.
--- drivers/gpu/drm/panel/panel-simple.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
drivers/gpu/drm/panel/panel-simple.c +27 -0
@@ -1939,6 +1939,30 @@ static void panel_simple_shutdown(struct device *dev) .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; +static const struct drm_display_mode innolux_tv123wam_mode = { + .clock =206016 , + .hdisplay =2160 , + .hsync_start =2160 +48 , + .hsync_end =2160 +48 +32 , + .htotal =2160 +48 +32 +80 , + .vdisplay =1440 , + .vsync_start =1440 +3 , + .vsync_end =1440 +3 +10 , + .vtotal =1440 +3 +10 +27 , + .vrefresh =60 , + .flags =DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC , +}; + +static const struct panel_desc innolux_tv123wam = { + .modes = &innolux_tv123wam_mode, + .num_modes =1 , + .bpc =8 , + .size = { + .width =259 , + .height =173 , + }, +}; +static const struct of_device_id platform_of_match[] = { { .compatible ="ampire,am-480272h3tmqw-t01h" ,
@@ -2142,6 +2166,9 @@ static void panel_simple_shutdown(struct device *dev) .compatible = "winstar,wf35ltiacd", .data = &winstar_wf35ltiacd, }, { + .compatible = "innolux,tv123wam", + .data = &innolux_tv123wam, + }, {/* sentinel */ } };
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 1525235522-8954-4-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
Re: [PATCH v5 3/4] drm/panel: add Innolux TV123WAM panel driver support
Quoted 44 lines · Sandeep Panda
Add support for Innolux TV123WAM, which is a 12.3" eDP display panel with 2160x1440 resolution.
Signed-off-by Sandeep Panda <[email protected]>--- drivers/gpu/drm/panel/panel-simple.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)drivers/gpu/drm/panel/panel-simple.c +24
-0@@ -1939,6 +1939,30 @@ static void panel_simple_shutdown(struct device *dev) .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; +static const struct drm_display_mode innolux_tv123wam_mode = { + .clock =206016 , + .hdisplay =2160 , + .hsync_start =2160 +48 , + .hsync_end =2160 +48 +32 , + .htotal =2160 +48 +32 +80 , + .vdisplay =1440 , + .vsync_start =1440 +3 , + .vsync_end =1440 +3 +10 , + .vtotal =1440 +3 +10 +27 , + .vrefresh =60 , + .flags =DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC , +}; + +static const struct panel_desc innolux_tv123wam = { + .modes = &innolux_tv123wam_mode, + .num_modes =1 , + .bpc =8 , + .size = { + .width =259 , + .height =173 , + }, +}; +static const struct of_device_id platform_of_match[] = { { .compatible ="ampire,am-480272h3tmqw-t01h" ,
drivers/gpu/drm/panel/panel-simple.c static void panel_simple_shutdown(struct device *dev) · line 2171
Quoted 6 lines
drivers/gpu/drm/panel/panel-simple.c +3
-0@@ -2142,6 +2166,9 @@ static void panel_simple_shutdown(struct device *dev) .compatible = "winstar,wf35ltiacd", .data = &winstar_wf35ltiacd, }, { + .compatible = "innolux,tv123wam", + .data = &innolux_tv123wam, + }, {
These are alphabetically ordered, as are the drm_display_mode/panel_desc structs.
Sean
Quoted 7 lines
drivers/gpu/drm/panel/panel-simple.c +0
-0/* sentinel */ } };Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Signature · 5 lines
Sean Paul, Software Engineer, Google / Chromium OS _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [PATCH v5 3/4] drm/panel: add Innolux TV123WAM panel driver support
Quoted 57 lines · Sean Paul
Quoted 45 lines · Sandeep Panda
Add support for Innolux TV123WAM, which is a 12.3" eDP display panel with 2160x1440 resolution.
Signed-off-by Sandeep Panda <[email protected]>--- drivers/gpu/drm/panel/panel-simple.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)drivers/gpu/drm/panel/panel-simple.c +24
-0@@ -1939,6 +1939,30 @@ static void panel_simple_shutdown(struct device *dev) .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; +static const struct drm_display_mode innolux_tv123wam_mode = { + .clock =206016 , + .hdisplay =2160 , + .hsync_start =2160 +48 , + .hsync_end =2160 +48 +32 , + .htotal =2160 +48 +32 +80 , + .vdisplay =1440 , + .vsync_start =1440 +3 , + .vsync_end =1440 +3 +10 , + .vtotal =1440 +3 +10 +27 , + .vrefresh =60 , + .flags =DRM_MODE_FLAG_PHSYNC |DRM_MODE_FLAG_PVSYNC , +}; + +static const struct panel_desc innolux_tv123wam = { + .modes = &innolux_tv123wam_mode, + .num_modes =1 , + .bpc =8 , + .size = { + .width =259 , + .height =173 , + }, +}; +static const struct of_device_id platform_of_match[] = { {drivers/gpu/drm/panel/panel-simple.c +0
-0.compatible = "ampire,am-480272h3tmqw-t01h",drivers/gpu/drm/panel/panel-simple.c static void panel_simple_shutdown(struct device · line 2172
Quoted 7 lines
drivers/gpu/drm/panel/panel-simple.c +3
-0@@ -2142,6 +2166,9 @@ static void panel_simple_shutdown(struct device *dev) .compatible = "winstar,wf35ltiacd", .data = &winstar_wf35ltiacd, }, { + .compatible = "innolux,tv123wam", + .data = &innolux_tv123wam, + }, {These are alphabetically ordered, as are the drm_display_mode/panel_desc structs.
Quoted 2 lines
Sean
Done.
Quoted 7 lines
Quoted 7 lines
drivers/gpu/drm/panel/panel-simple.c +0
-0/* sentinel */ }};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
_______________________________________________
Freedreno mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH v5 4/4 dt-bindings: drm/panel: Document Innolux TV123WAM panel bindings
In reply to a message not in the archiveInnolux TV123WAM is a 12.3" eDP display panel with 2160x1440 resolution, which can be supported by simple panel driver.
Changes in v1:
- Make use of simple panel driver instead of creating a new driver for this panel (Sean Paul).
- Combine dt-binding and driver changes into one patch as done by other existing panel support changes.
Changes in v2:
- Separate driver change from dt-binding documentation (Rob Herring).
- Add the properties from simple-panel binding that are applicable to this panel (Rob Herring).
--- .../bindings/display/panel/innolux,tv123wam.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt
Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt new file +20 -0
@@ -0,0 +1,20 @@ +Innolux TV123WAM 12.3 inch eDP 2K display panel + +This binding is compatible with the simple-panel binding, which is specified +in simple-panel.txt in this directory. + +Required properties: +- compatible: should be "innolux,tv123wam" +- power-supply: regulator to provide the supply voltage + +Optional properties: +- enable-gpios: GPIO pin to enable or disable the panel +- backlight: phandle of the backlight device attached to the panel + +Example: + panel_edp: panel-edp { + compatible = "innolux,tv123wam"; + enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>; + power-supply = <&pm8916_l2>; + backlight = <&backlight>; + };
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
Re: [PATCH v5 4/4] dt-bindings: drm/panel: Document Innolux TV123WAM panel bindings
Quoted 15 lines · Sandeep Panda
Innolux TV123WAM is a 12.3" eDP display panel with 2160x1440 resolution, which can be supported by simple panel driver.
Changes in v1:
- Make use of simple panel driver instead of creating a new driver for this panel (Sean Paul).
- Combine dt-binding and driver changes into one patch as done by other existing panel support changes.Changes in v2:
- Separate driver change from dt-binding documentation (Rob Herring).
- Add the properties from simple-panel binding that are applicable to this panel (Rob Herring).
Quoted 5 lines
Signed-off-by Sandeep Panda <[email protected]>--- .../bindings/display/panel/innolux,tv123wam.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel