Commit dec72739 authored by Thierry Reding's avatar Thierry Reding

drm/tegra: Add DSI support

This commit adds support for both DSI outputs found on Tegra. Only very
minimal functionality is implemented, so advanced features like ganged
mode won't work.

Due to the lack of other test hardware, some sections of the driver are
hardcoded to work with Dalmore.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent b5190022
...@@ -171,11 +171,21 @@ of the following host1x client modules: ...@@ -171,11 +171,21 @@ of the following host1x client modules:
- clock-names: Must include the following entries: - clock-names: Must include the following entries:
- dsi - dsi
This MUST be the first entry. This MUST be the first entry.
- lp
- parent - parent
- resets: Must contain an entry for each entry in reset-names. - resets: Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details. See ../reset/reset.txt for details.
- reset-names: Must include the following entries: - reset-names: Must include the following entries:
- dsi - dsi
- nvidia,mipi-calibrate: Should contain a phandle and a specifier specifying
which pads are used by this DSI output and need to be calibrated. See also
../mipi/nvidia,tegra114-mipi.txt.
Optional properties:
- nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
- nvidia,edid: supplies a binary EDID blob
- nvidia,panel: phandle of a display panel
Example: Example:
......
...@@ -6,6 +6,7 @@ config DRM_TEGRA ...@@ -6,6 +6,7 @@ config DRM_TEGRA
select TEGRA_HOST1X select TEGRA_HOST1X
select DRM_KMS_HELPER select DRM_KMS_HELPER
select DRM_KMS_FB_HELPER select DRM_KMS_FB_HELPER
select DRM_MIPI_DSI
select DRM_PANEL select DRM_PANEL
select FB_SYS_FILLRECT select FB_SYS_FILLRECT
select FB_SYS_COPYAREA select FB_SYS_COPYAREA
......
...@@ -9,6 +9,8 @@ tegra-drm-y := \ ...@@ -9,6 +9,8 @@ tegra-drm-y := \
output.o \ output.o \
rgb.o \ rgb.o \
hdmi.o \ hdmi.o \
mipi-phy.o \
dsi.o \
gr2d.o \ gr2d.o \
gr3d.o gr3d.o
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define DISP_CTRL_MODE_STOP (0 << 5) #define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) #define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) #define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
#define DISP_CTRL_MODE_MASK (3 << 5)
#define DC_CMD_SIGNAL_RAISE 0x033 #define DC_CMD_SIGNAL_RAISE 0x033
#define DC_CMD_DISPLAY_POWER_CONTROL 0x036 #define DC_CMD_DISPLAY_POWER_CONTROL 0x036
#define PW0_ENABLE (1 << 0) #define PW0_ENABLE (1 << 0)
...@@ -116,6 +117,7 @@ ...@@ -116,6 +117,7 @@
#define DC_DISP_DISP_WIN_OPTIONS 0x402 #define DC_DISP_DISP_WIN_OPTIONS 0x402
#define HDMI_ENABLE (1 << 30) #define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE (1 << 29)
#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403
#define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) #define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24)
......
...@@ -653,6 +653,7 @@ static const struct of_device_id host1x_drm_subdevs[] = { ...@@ -653,6 +653,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra30-hdmi", }, { .compatible = "nvidia,tegra30-hdmi", },
{ .compatible = "nvidia,tegra30-gr2d", }, { .compatible = "nvidia,tegra30-gr2d", },
{ .compatible = "nvidia,tegra30-gr3d", }, { .compatible = "nvidia,tegra30-gr3d", },
{ .compatible = "nvidia,tegra114-dsi", },
{ .compatible = "nvidia,tegra114-hdmi", }, { .compatible = "nvidia,tegra114-hdmi", },
{ .compatible = "nvidia,tegra114-gr3d", }, { .compatible = "nvidia,tegra114-gr3d", },
{ /* sentinel */ } { /* sentinel */ }
...@@ -677,10 +678,14 @@ static int __init host1x_drm_init(void) ...@@ -677,10 +678,14 @@ static int __init host1x_drm_init(void)
if (err < 0) if (err < 0)
goto unregister_host1x; goto unregister_host1x;
err = platform_driver_register(&tegra_hdmi_driver); err = platform_driver_register(&tegra_dsi_driver);
if (err < 0) if (err < 0)
goto unregister_dc; goto unregister_dc;
err = platform_driver_register(&tegra_hdmi_driver);
if (err < 0)
goto unregister_dsi;
err = platform_driver_register(&tegra_gr2d_driver); err = platform_driver_register(&tegra_gr2d_driver);
if (err < 0) if (err < 0)
goto unregister_hdmi; goto unregister_hdmi;
...@@ -695,6 +700,8 @@ static int __init host1x_drm_init(void) ...@@ -695,6 +700,8 @@ static int __init host1x_drm_init(void)
platform_driver_unregister(&tegra_gr2d_driver); platform_driver_unregister(&tegra_gr2d_driver);
unregister_hdmi: unregister_hdmi:
platform_driver_unregister(&tegra_hdmi_driver); platform_driver_unregister(&tegra_hdmi_driver);
unregister_dsi:
platform_driver_unregister(&tegra_dsi_driver);
unregister_dc: unregister_dc:
platform_driver_unregister(&tegra_dc_driver); platform_driver_unregister(&tegra_dc_driver);
unregister_host1x: unregister_host1x:
...@@ -708,6 +715,7 @@ static void __exit host1x_drm_exit(void) ...@@ -708,6 +715,7 @@ static void __exit host1x_drm_exit(void)
platform_driver_unregister(&tegra_gr3d_driver); platform_driver_unregister(&tegra_gr3d_driver);
platform_driver_unregister(&tegra_gr2d_driver); platform_driver_unregister(&tegra_gr2d_driver);
platform_driver_unregister(&tegra_hdmi_driver); platform_driver_unregister(&tegra_hdmi_driver);
platform_driver_unregister(&tegra_dsi_driver);
platform_driver_unregister(&tegra_dc_driver); platform_driver_unregister(&tegra_dc_driver);
host1x_driver_unregister(&host1x_drm_driver); host1x_driver_unregister(&host1x_drm_driver);
} }
......
...@@ -177,6 +177,7 @@ struct tegra_output_ops { ...@@ -177,6 +177,7 @@ struct tegra_output_ops {
enum tegra_output_type { enum tegra_output_type {
TEGRA_OUTPUT_RGB, TEGRA_OUTPUT_RGB,
TEGRA_OUTPUT_HDMI, TEGRA_OUTPUT_HDMI,
TEGRA_OUTPUT_DSI,
}; };
struct tegra_output { struct tegra_output {
...@@ -267,6 +268,7 @@ extern void tegra_drm_fb_exit(struct drm_device *drm); ...@@ -267,6 +268,7 @@ extern void tegra_drm_fb_exit(struct drm_device *drm);
extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
extern struct platform_driver tegra_dc_driver; extern struct platform_driver tegra_dc_driver;
extern struct platform_driver tegra_dsi_driver;
extern struct platform_driver tegra_hdmi_driver; extern struct platform_driver tegra_hdmi_driver;
extern struct platform_driver tegra_gr2d_driver; extern struct platform_driver tegra_gr2d_driver;
extern struct platform_driver tegra_gr3d_driver; extern struct platform_driver tegra_gr3d_driver;
......
This diff is collapsed.
/*
* Copyright (C) 2013 NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef DRM_TEGRA_DSI_H
#define DRM_TEGRA_DSI_H
#define DSI_INCR_SYNCPT 0x00
#define DSI_INCR_SYNCPT_CONTROL 0x01
#define DSI_INCR_SYNCPT_ERROR 0x02
#define DSI_CTXSW 0x08
#define DSI_RD_DATA 0x09
#define DSI_WR_DATA 0x0a
#define DSI_POWER_CONTROL 0x0b
#define DSI_POWER_CONTROL_ENABLE (1 << 0)
#define DSI_INT_ENABLE 0x0c
#define DSI_INT_STATUS 0x0d
#define DSI_INT_MASK 0x0e
#define DSI_HOST_CONTROL 0x0f
#define DSI_HOST_CONTROL_RAW (1 << 6)
#define DSI_HOST_CONTROL_HS (1 << 5)
#define DSI_HOST_CONTROL_BTA (1 << 2)
#define DSI_HOST_CONTROL_CS (1 << 1)
#define DSI_HOST_CONTROL_ECC (1 << 0)
#define DSI_CONTROL 0x10
#define DSI_CONTROL_HS_CLK_CTRL (1 << 20)
#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16)
#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12)
#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8)
#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4)
#define DSI_CONTROL_DCS_ENABLE (1 << 3)
#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2)
#define DSI_CONTROL_VIDEO_ENABLE (1 << 1)
#define DSI_CONTROL_HOST_ENABLE (1 << 0)
#define DSI_SOL_DELAY 0x11
#define DSI_MAX_THRESHOLD 0x12
#define DSI_TRIGGER 0x13
#define DSI_TX_CRC 0x14
#define DSI_STATUS 0x15
#define DSI_STATUS_IDLE (1 << 10)
#define DSI_INIT_SEQ_CONTROL 0x1a
#define DSI_INIT_SEQ_DATA_0 0x1b
#define DSI_INIT_SEQ_DATA_1 0x1c
#define DSI_INIT_SEQ_DATA_2 0x1d
#define DSI_INIT_SEQ_DATA_3 0x1e
#define DSI_INIT_SEQ_DATA_4 0x1f
#define DSI_INIT_SEQ_DATA_5 0x20
#define DSI_INIT_SEQ_DATA_6 0x21
#define DSI_INIT_SEQ_DATA_7 0x22
#define DSI_PKT_SEQ_0_LO 0x23
#define DSI_PKT_SEQ_0_HI 0x24
#define DSI_PKT_SEQ_1_LO 0x25
#define DSI_PKT_SEQ_1_HI 0x26
#define DSI_PKT_SEQ_2_LO 0x27
#define DSI_PKT_SEQ_2_HI 0x28
#define DSI_PKT_SEQ_3_LO 0x29
#define DSI_PKT_SEQ_3_HI 0x2a
#define DSI_PKT_SEQ_4_LO 0x2b
#define DSI_PKT_SEQ_4_HI 0x2c
#define DSI_PKT_SEQ_5_LO 0x2d
#define DSI_PKT_SEQ_5_HI 0x2e
#define DSI_DCS_CMDS 0x33
#define DSI_PKT_LEN_0_1 0x34
#define DSI_PKT_LEN_2_3 0x35
#define DSI_PKT_LEN_4_5 0x36
#define DSI_PKT_LEN_6_7 0x37
#define DSI_PHY_TIMING_0 0x3c
#define DSI_PHY_TIMING_1 0x3d
#define DSI_PHY_TIMING_2 0x3e
#define DSI_BTA_TIMING 0x3f
#define DSI_TIMING_FIELD(value, period, hwinc) \
((DIV_ROUND_CLOSEST(value, period) - (hwinc)) & 0xff)
#define DSI_TIMEOUT_0 0x44
#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0)
#define DSI_TIMEOUT_1 0x45
#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16)
#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0)
#define DSI_TO_TALLY 0x46
#define DSI_TALLY_TA(x) (((x) & 0xff) << 16)
#define DSI_TALLY_LRX(x) (((x) & 0xff) << 8)
#define DSI_TALLY_HTX(x) (((x) & 0xff) << 0)
#define DSI_PAD_CONTROL_0 0x4b
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24)
#define DSI_PAD_CONTROL_CD 0x4c
#define DSI_PAD_CD_STATUS 0x4d
#define DSI_VIDEO_MODE_CONTROL 0x4e
#define DSI_PAD_CONTROL_1 0x4f
#define DSI_PAD_CONTROL_2 0x50
#define DSI_PAD_OUT_CLK(x) (((x) & 0x7) << 0)
#define DSI_PAD_LP_DN(x) (((x) & 0x7) << 4)
#define DSI_PAD_LP_UP(x) (((x) & 0x7) << 8)
#define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12)
#define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16)
#define DSI_PAD_CONTROL_3 0x51
#define DSI_PAD_CONTROL_4 0x52
#define DSI_GANGED_MODE_CONTROL 0x53
#define DSI_GANGED_MODE_START 0x54
#define DSI_GANGED_MODE_SIZE 0x55
#define DSI_RAW_DATA_BYTE_COUNT 0x56
#define DSI_ULTRA_LOW_POWER_CONTROL 0x57
#define DSI_INIT_SEQ_DATA_8 0x58
#define DSI_INIT_SEQ_DATA_9 0x59
#define DSI_INIT_SEQ_DATA_10 0x5a
#define DSI_INIT_SEQ_DATA_11 0x5b
#define DSI_INIT_SEQ_DATA_12 0x5c
#define DSI_INIT_SEQ_DATA_13 0x5d
#define DSI_INIT_SEQ_DATA_14 0x5e
#define DSI_INIT_SEQ_DATA_15 0x5f
#endif
/*
* Copyright (C) 2013 NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <linux/kernel.h>
#include "mipi-phy.h"
/*
* Default D-PHY timings based on MIPI D-PHY specification. Derived from
* the valid ranges specified in Section 5.9 of the D-PHY specification
* with minor adjustments.
*/
int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
unsigned long period)
{
timing->clkmiss = 0;
timing->clkpost = 70 + 52 * period;
timing->clkpre = 8;
timing->clkprepare = 65;
timing->clksettle = 95;
timing->clktermen = 0;
timing->clktrail = 80;
timing->clkzero = 260;
timing->dtermen = 0;
timing->eot = 0;
timing->hsexit = 120;
timing->hsprepare = 65 + 5 * period;
timing->hszero = 145 + 5 * period;
timing->hssettle = 85 + 6 * period;
timing->hsskip = 40;
timing->hstrail = max(8 * period, 60 + 4 * period);
timing->init = 100000;
timing->lpx = 60;
timing->taget = 5 * timing->lpx;
timing->tago = 4 * timing->lpx;
timing->tasure = 2 * timing->lpx;
timing->wakeup = 1000000;
return 0;
}
/*
* Validate D-PHY timing according to MIPI Alliance Specification for D-PHY,
* Section 5.9 "Global Operation Timing Parameters".
*/
int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
unsigned long period)
{
if (timing->clkmiss > 60)
return -EINVAL;
if (timing->clkpost < (60 + 52 * period))
return -EINVAL;
if (timing->clkpre < 8)
return -EINVAL;
if (timing->clkprepare < 38 || timing->clkprepare > 95)
return -EINVAL;
if (timing->clksettle < 95 || timing->clksettle > 300)
return -EINVAL;
if (timing->clktermen > 38)
return -EINVAL;
if (timing->clktrail < 60)
return -EINVAL;
if (timing->clkprepare + timing->clkzero < 300)
return -EINVAL;
if (timing->dtermen > 35 + 4 * period)
return -EINVAL;
if (timing->eot > 105 + 12 * period)
return -EINVAL;
if (timing->hsexit < 100)
return -EINVAL;
if (timing->hsprepare < 40 + 4 * period ||
timing->hsprepare > 85 + 6 * period)
return -EINVAL;
if (timing->hsprepare + timing->hszero < 145 + 10 * period)
return -EINVAL;
if ((timing->hssettle < 85 + 6 * period) ||
(timing->hssettle > 145 + 10 * period))
return -EINVAL;
if (timing->hsskip < 40 || timing->hsskip > 55 + 4 * period)
return -EINVAL;
if (timing->hstrail < max(8 * period, 60 + 4 * period))
return -EINVAL;
if (timing->init < 100000)
return -EINVAL;
if (timing->lpx < 50)
return -EINVAL;
if (timing->taget != 5 * timing->lpx)
return -EINVAL;
if (timing->tago != 4 * timing->lpx)
return -EINVAL;
if (timing->tasure < timing->lpx || timing->tasure > 2 * timing->lpx)
return -EINVAL;
if (timing->wakeup < 1000000)
return -EINVAL;
return 0;
}
/*
* Copyright (C) 2013 NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef DRM_TEGRA_MIPI_PHY_H
#define DRM_TEGRA_MIPI_PHY_H
/*
* D-PHY timing parameters
*
* A detailed description of these parameters can be found in the MIPI
* Alliance Specification for D-PHY, Section 5.9 "Global Operation Timing
* Parameters".
*
* All parameters are specified in nanoseconds.
*/
struct mipi_dphy_timing {
unsigned int clkmiss;
unsigned int clkpost;
unsigned int clkpre;
unsigned int clkprepare;
unsigned int clksettle;
unsigned int clktermen;
unsigned int clktrail;
unsigned int clkzero;
unsigned int dtermen;
unsigned int eot;
unsigned int hsexit;
unsigned int hsprepare;
unsigned int hszero;
unsigned int hssettle;
unsigned int hsskip;
unsigned int hstrail;
unsigned int init;
unsigned int lpx;
unsigned int taget;
unsigned int tago;
unsigned int tasure;
unsigned int wakeup;
};
int mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing,
unsigned long period);
int mipi_dphy_timing_validate(struct mipi_dphy_timing *timing,
unsigned long period);
#endif
...@@ -284,6 +284,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) ...@@ -284,6 +284,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
encoder = DRM_MODE_ENCODER_TMDS; encoder = DRM_MODE_ENCODER_TMDS;
break; break;
case TEGRA_OUTPUT_DSI:
connector = DRM_MODE_CONNECTOR_DSI;
encoder = DRM_MODE_ENCODER_DSI;
break;
default: default:
connector = DRM_MODE_CONNECTOR_Unknown; connector = DRM_MODE_CONNECTOR_Unknown;
encoder = DRM_MODE_ENCODER_NONE; encoder = DRM_MODE_ENCODER_NONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment