mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-21 11:48:06 +07:00
Merge branch 'drm-next-analogix-dp-v2' of github.com:yakir-Yang/linux into drm-next
This pull request want to land the analogix_dp driver into drm/bridge directory, which reused the Exynos DP code, and add Rockchip DP support. And those patches have been: * 'drm-next-analogix-dp-v2' of github.com:yakir-Yang/linux: drm: bridge: analogix/dp: Fix the possible dead lock in bridge disable time drm: bridge: analogix/dp: add panel prepare/unprepare in suspend/resume time drm: bridge: analogix/dp: add edid modes parse in get_modes method drm: bridge: analogix/dp: move hpd detect to connector detect function drm: bridge: analogix/dp: try force hpd after plug in lookup failed drm: bridge: analogix/dp: add max link rate and lane count limit for RK3288 drm: bridge: analogix/dp: add some rk3288 special registers setting dt-bindings: add document for rockchip variant of analogix_dp drm: rockchip: dp: add rockchip platform dp driver ARM: dts: exynos/dp: remove some properties that deprecated by analogix_dp driver dt-bindings: add document for analogix display port driver drm: bridge: analogix/dp: dynamic parse sync_pol & interlace & dynamic_range drm: bridge: analogix/dp: remove duplicate configuration of link rate and link count drm: bridge: analogix/dp: fix some obvious code style drm: bridge: analogix/dp: rename register constants drm/exynos: dp: rename implementation specific driver part drm: bridge: analogix/dp: split exynos dp driver to bridge directory
This commit is contained in:
commit
d00b39c175
@ -0,0 +1,52 @@
|
||||
Analogix Display Port bridge bindings
|
||||
|
||||
Required properties for dp-controller:
|
||||
-compatible:
|
||||
platform specific such as:
|
||||
* "samsung,exynos5-dp"
|
||||
* "rockchip,rk3288-dp"
|
||||
-reg:
|
||||
physical base address of the controller and length
|
||||
of memory mapped region.
|
||||
-interrupts:
|
||||
interrupt combiner values.
|
||||
-clocks:
|
||||
from common clock binding: handle to dp clock.
|
||||
-clock-names:
|
||||
from common clock binding: Shall be "dp".
|
||||
-interrupt-parent:
|
||||
phandle to Interrupt combiner node.
|
||||
-phys:
|
||||
from general PHY binding: the phandle for the PHY device.
|
||||
-phy-names:
|
||||
from general PHY binding: Should be "dp".
|
||||
|
||||
Optional properties for dp-controller:
|
||||
-force-hpd:
|
||||
Indicate driver need force hpd when hpd detect failed, this
|
||||
is used for some eDP screen which don't have hpd signal.
|
||||
-hpd-gpios:
|
||||
Hotplug detect GPIO.
|
||||
Indicates which GPIO should be used for hotplug detection
|
||||
-port@[X]: SoC specific port nodes with endpoint definitions as defined
|
||||
in Documentation/devicetree/bindings/media/video-interfaces.txt,
|
||||
please refer to the SoC specific binding document:
|
||||
* Documentation/devicetree/bindings/display/exynos/exynos_dp.txt
|
||||
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
|
||||
|
||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Example:
|
||||
|
||||
dp-controller {
|
||||
compatible = "samsung,exynos5-dp";
|
||||
reg = <0x145b0000 0x10000>;
|
||||
interrupts = <10 3>;
|
||||
interrupt-parent = <&combiner>;
|
||||
clocks = <&clock 342>;
|
||||
clock-names = "dp";
|
||||
|
||||
phys = <&dp_phy>;
|
||||
phy-names = "dp";
|
||||
};
|
@ -1,20 +1,3 @@
|
||||
Device-Tree bindings for Samsung Exynos Embedded DisplayPort Transmitter(eDP)
|
||||
|
||||
DisplayPort is industry standard to accommodate the growing board adoption
|
||||
of digital display technology within the PC and CE industries.
|
||||
It consolidates the internal and external connection methods to reduce device
|
||||
complexity and cost. It also supports necessary features for important cross
|
||||
industry applications and provides performance scalability to enable the next
|
||||
generation of displays that feature higher color depths, refresh rates, and
|
||||
display resolutions.
|
||||
|
||||
eDP (embedded display port) device is compliant with Embedded DisplayPort
|
||||
standard as follows,
|
||||
- DisplayPort standard 1.1a for Exynos5250 and Exynos5260.
|
||||
- DisplayPort standard 1.3 for Exynos5422s and Exynos5800.
|
||||
|
||||
eDP resides between FIMD and panel or FIMD and bridge such as LVDS.
|
||||
|
||||
The Exynos display port interface should be configured based on
|
||||
the type of panel connected to it.
|
||||
|
||||
@ -48,26 +31,6 @@ Required properties for dp-controller:
|
||||
from general PHY binding: the phandle for the PHY device.
|
||||
-phy-names:
|
||||
from general PHY binding: Should be "dp".
|
||||
-samsung,color-space:
|
||||
input video data format.
|
||||
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
|
||||
-samsung,dynamic-range:
|
||||
dynamic range for input video data.
|
||||
VESA = 0, CEA = 1
|
||||
-samsung,ycbcr-coeff:
|
||||
YCbCr co-efficients for input video.
|
||||
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
|
||||
-samsung,color-depth:
|
||||
number of bits per colour component.
|
||||
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
|
||||
-samsung,link-rate:
|
||||
link rate supported by the panel.
|
||||
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
|
||||
-samsung,lane-count:
|
||||
number of lanes supported by the panel.
|
||||
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
|
||||
- display-timings: timings for the connected panel as described by
|
||||
Documentation/devicetree/bindings/display/display-timing.txt
|
||||
|
||||
Optional properties for dp-controller:
|
||||
-interlaced:
|
||||
@ -83,17 +46,31 @@ Optional properties for dp-controller:
|
||||
Hotplug detect GPIO.
|
||||
Indicates which GPIO should be used for hotplug
|
||||
detection
|
||||
Video interfaces:
|
||||
Device node can contain video interface port nodes according to [1].
|
||||
The following are properties specific to those nodes:
|
||||
-video interfaces: Device node can contain video interface port
|
||||
nodes according to [1].
|
||||
- display-timings: timings for the connected panel as described by
|
||||
Documentation/devicetree/bindings/display/panel/display-timing.txt
|
||||
|
||||
endpoint node connected to bridge or panel node:
|
||||
- remote-endpoint: specifies the endpoint in panel or bridge node.
|
||||
This node is required in all kinds of exynos dp
|
||||
to represent the connection between dp and bridge
|
||||
or dp and panel.
|
||||
For the below properties, please refer to Analogix DP binding document:
|
||||
* Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
|
||||
-phys (required)
|
||||
-phy-names (required)
|
||||
-hpd-gpios (optional)
|
||||
force-hpd (optional)
|
||||
|
||||
[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
Deprecated properties for DisplayPort:
|
||||
-interlaced: deprecated prop that can parsed from drm_display_mode.
|
||||
-vsync-active-high: deprecated prop that can parsed from drm_display_mode.
|
||||
-hsync-active-high: deprecated prop that can parsed from drm_display_mode.
|
||||
-samsung,ycbcr-coeff: deprecated prop that can parsed from drm_display_mode.
|
||||
-samsung,dynamic-range: deprecated prop that can parsed from drm_display_mode.
|
||||
-samsung,color-space: deprecated prop that can parsed from drm_display_info.
|
||||
-samsung,color-depth: deprecated prop that can parsed from drm_display_info.
|
||||
-samsung,link-rate: deprecated prop that can reading from monitor by dpcd method.
|
||||
-samsung,lane-count: deprecated prop that can reading from monitor by dpcd method.
|
||||
-samsung,hpd-gpio: deprecated name for hpd-gpios.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Example:
|
||||
|
||||
@ -112,13 +89,6 @@ SOC specific portion:
|
||||
|
||||
Board Specific portion:
|
||||
dp-controller {
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <4>;
|
||||
|
||||
display-timings {
|
||||
native-mode = <&lcd_timing>;
|
||||
lcd_timing: 1366x768 {
|
||||
@ -135,18 +105,9 @@ Board Specific portion:
|
||||
};
|
||||
|
||||
ports {
|
||||
port {
|
||||
port@0 {
|
||||
dp_out: endpoint {
|
||||
remote-endpoint = <&dp_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel {
|
||||
...
|
||||
port {
|
||||
dp_in: endpoint {
|
||||
remote-endpoint = <&dp_out>;
|
||||
remote-endpoint = <&bridge_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,92 @@
|
||||
Rockchip RK3288 specific extensions to the Analogix Display Port
|
||||
================================
|
||||
|
||||
Required properties:
|
||||
- compatible: "rockchip,rk3288-edp";
|
||||
|
||||
- reg: physical base address of the controller and length
|
||||
|
||||
- clocks: from common clock binding: handle to dp clock.
|
||||
of memory mapped region.
|
||||
|
||||
- clock-names: from common clock binding:
|
||||
Required elements: "dp" "pclk"
|
||||
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
|
||||
- pinctrl-names: Names corresponding to the chip hotplug pinctrl states.
|
||||
- pinctrl-0: pin-control mode. should be <&edp_hpd>
|
||||
|
||||
- reset-names: Must include the name "dp"
|
||||
|
||||
- rockchip,grf: this soc should set GRF regs, so need get grf here.
|
||||
|
||||
- ports: there are 2 port nodes with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
Port 0: contained 2 endpoints, connecting to the output of vop.
|
||||
Port 1: contained 1 endpoint, connecting to the input of panel.
|
||||
|
||||
For the below properties, please refer to Analogix DP binding document:
|
||||
* Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
|
||||
- phys (required)
|
||||
- phy-names (required)
|
||||
- hpd-gpios (optional)
|
||||
- force-hpd (optional)
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Example:
|
||||
dp-controller: dp@ff970000 {
|
||||
compatible = "rockchip,rk3288-dp";
|
||||
reg = <0xff970000 0x4000>;
|
||||
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>;
|
||||
clock-names = "dp", "pclk";
|
||||
phys = <&dp_phy>;
|
||||
phy-names = "dp";
|
||||
|
||||
rockchip,grf = <&grf>;
|
||||
resets = <&cru 111>;
|
||||
reset-names = "dp";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&edp_hpd>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
edp_in: port@0 {
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
edp_in_vopb: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&vopb_out_edp>;
|
||||
};
|
||||
edp_in_vopl: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&vopl_out_edp>;
|
||||
};
|
||||
};
|
||||
|
||||
edp_out: port@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
edp_out_panel: endpoint {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&panel_in_edp>
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl {
|
||||
edp {
|
||||
edp_hpd: edp-hpd {
|
||||
rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
@ -124,8 +124,6 @@ &cpu0 {
|
||||
&dp {
|
||||
status = "okay";
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <4>;
|
||||
|
@ -80,8 +80,6 @@ &cpu0 {
|
||||
|
||||
&dp {
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <4>;
|
||||
|
@ -236,12 +236,10 @@ &dp {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dp_hpd>;
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <2>;
|
||||
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
|
||||
hpd-gpios = <&gpx0 7 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
ports {
|
||||
port@0 {
|
||||
|
@ -74,12 +74,10 @@ &dp {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dp_hpd_gpio>;
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <1>;
|
||||
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
|
||||
hpd-gpios = <&gpc3 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
&ehci {
|
||||
|
@ -157,12 +157,10 @@ &dp {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dp_hpd_gpio>;
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x06>;
|
||||
samsung,lane-count = <2>;
|
||||
samsung,hpd-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
|
||||
hpd-gpios = <&gpx2 6 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
ports {
|
||||
port@0 {
|
||||
|
@ -102,8 +102,6 @@ &dp {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dp_hpd>;
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <4>;
|
||||
|
@ -157,8 +157,6 @@ &dp {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dp_hpd_gpio>;
|
||||
samsung,color-space = <0>;
|
||||
samsung,dynamic-range = <0>;
|
||||
samsung,ycbcr-coeff = <0>;
|
||||
samsung,color-depth = <1>;
|
||||
samsung,link-rate = <0x0a>;
|
||||
samsung,lane-count = <2>;
|
||||
|
@ -40,4 +40,6 @@ config DRM_PARADE_PS8622
|
||||
---help---
|
||||
Parade eDP-LVDS bridge chip driver.
|
||||
|
||||
source "drivers/gpu/drm/bridge/analogix/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
|
||||
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
|
||||
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
|
||||
obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
|
||||
|
3
drivers/gpu/drm/bridge/analogix/Kconfig
Normal file
3
drivers/gpu/drm/bridge/analogix/Kconfig
Normal file
@ -0,0 +1,3 @@
|
||||
config DRM_ANALOGIX_DP
|
||||
tristate
|
||||
depends on DRM
|
2
drivers/gpu/drm/bridge/analogix/Makefile
Normal file
2
drivers/gpu/drm/bridge/analogix/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o
|
||||
obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o
|
1430
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
Normal file
1430
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
Normal file
File diff suppressed because it is too large
Load Diff
281
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
Normal file
281
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Header file for Analogix DP (Display Port) core interface driver.
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* Author: Jingoo Han <jg1.han@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ANALOGIX_DP_CORE_H
|
||||
#define _ANALOGIX_DP_CORE_H
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
#define DP_TIMEOUT_LOOP_COUNT 100
|
||||
#define MAX_CR_LOOP 5
|
||||
#define MAX_EQ_LOOP 5
|
||||
|
||||
/* I2C EDID Chip ID, Slave Address */
|
||||
#define I2C_EDID_DEVICE_ADDR 0x50
|
||||
#define I2C_E_EDID_DEVICE_ADDR 0x30
|
||||
|
||||
#define EDID_BLOCK_LENGTH 0x80
|
||||
#define EDID_HEADER_PATTERN 0x00
|
||||
#define EDID_EXTENSION_FLAG 0x7e
|
||||
#define EDID_CHECKSUM 0x7f
|
||||
|
||||
/* DP_MAX_LANE_COUNT */
|
||||
#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
|
||||
#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
|
||||
|
||||
/* DP_LANE_COUNT_SET */
|
||||
#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
|
||||
|
||||
/* DP_TRAINING_LANE0_SET */
|
||||
#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
|
||||
#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
|
||||
#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
|
||||
#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
|
||||
|
||||
enum link_lane_count_type {
|
||||
LANE_COUNT1 = 1,
|
||||
LANE_COUNT2 = 2,
|
||||
LANE_COUNT4 = 4
|
||||
};
|
||||
|
||||
enum link_training_state {
|
||||
START,
|
||||
CLOCK_RECOVERY,
|
||||
EQUALIZER_TRAINING,
|
||||
FINISHED,
|
||||
FAILED
|
||||
};
|
||||
|
||||
enum voltage_swing_level {
|
||||
VOLTAGE_LEVEL_0,
|
||||
VOLTAGE_LEVEL_1,
|
||||
VOLTAGE_LEVEL_2,
|
||||
VOLTAGE_LEVEL_3,
|
||||
};
|
||||
|
||||
enum pre_emphasis_level {
|
||||
PRE_EMPHASIS_LEVEL_0,
|
||||
PRE_EMPHASIS_LEVEL_1,
|
||||
PRE_EMPHASIS_LEVEL_2,
|
||||
PRE_EMPHASIS_LEVEL_3,
|
||||
};
|
||||
|
||||
enum pattern_set {
|
||||
PRBS7,
|
||||
D10_2,
|
||||
TRAINING_PTN1,
|
||||
TRAINING_PTN2,
|
||||
DP_NONE
|
||||
};
|
||||
|
||||
enum color_space {
|
||||
COLOR_RGB,
|
||||
COLOR_YCBCR422,
|
||||
COLOR_YCBCR444
|
||||
};
|
||||
|
||||
enum color_depth {
|
||||
COLOR_6,
|
||||
COLOR_8,
|
||||
COLOR_10,
|
||||
COLOR_12
|
||||
};
|
||||
|
||||
enum color_coefficient {
|
||||
COLOR_YCBCR601,
|
||||
COLOR_YCBCR709
|
||||
};
|
||||
|
||||
enum dynamic_range {
|
||||
VESA,
|
||||
CEA
|
||||
};
|
||||
|
||||
enum pll_status {
|
||||
PLL_UNLOCKED,
|
||||
PLL_LOCKED
|
||||
};
|
||||
|
||||
enum clock_recovery_m_value_type {
|
||||
CALCULATED_M,
|
||||
REGISTER_M
|
||||
};
|
||||
|
||||
enum video_timing_recognition_type {
|
||||
VIDEO_TIMING_FROM_CAPTURE,
|
||||
VIDEO_TIMING_FROM_REGISTER
|
||||
};
|
||||
|
||||
enum analog_power_block {
|
||||
AUX_BLOCK,
|
||||
CH0_BLOCK,
|
||||
CH1_BLOCK,
|
||||
CH2_BLOCK,
|
||||
CH3_BLOCK,
|
||||
ANALOG_TOTAL,
|
||||
POWER_ALL
|
||||
};
|
||||
|
||||
enum dp_irq_type {
|
||||
DP_IRQ_TYPE_HP_CABLE_IN,
|
||||
DP_IRQ_TYPE_HP_CABLE_OUT,
|
||||
DP_IRQ_TYPE_HP_CHANGE,
|
||||
DP_IRQ_TYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
struct video_info {
|
||||
char *name;
|
||||
|
||||
bool h_sync_polarity;
|
||||
bool v_sync_polarity;
|
||||
bool interlaced;
|
||||
|
||||
enum color_space color_space;
|
||||
enum dynamic_range dynamic_range;
|
||||
enum color_coefficient ycbcr_coeff;
|
||||
enum color_depth color_depth;
|
||||
|
||||
int max_link_rate;
|
||||
enum link_lane_count_type max_lane_count;
|
||||
};
|
||||
|
||||
struct link_train {
|
||||
int eq_loop;
|
||||
int cr_loop[4];
|
||||
|
||||
u8 link_rate;
|
||||
u8 lane_count;
|
||||
u8 training_lane[4];
|
||||
|
||||
enum link_training_state lt_state;
|
||||
};
|
||||
|
||||
struct analogix_dp_device {
|
||||
struct drm_encoder *encoder;
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge *bridge;
|
||||
struct clk *clock;
|
||||
unsigned int irq;
|
||||
void __iomem *reg_base;
|
||||
|
||||
struct video_info video_info;
|
||||
struct link_train link_train;
|
||||
struct phy *phy;
|
||||
int dpms_mode;
|
||||
int hpd_gpio;
|
||||
bool force_hpd;
|
||||
unsigned char edid[EDID_BLOCK_LENGTH * 2];
|
||||
|
||||
struct analogix_dp_plat_data *plat_data;
|
||||
};
|
||||
|
||||
/* analogix_dp_reg.c */
|
||||
void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable);
|
||||
void analogix_dp_stop_video(struct analogix_dp_device *dp);
|
||||
void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable);
|
||||
void analogix_dp_init_analog_param(struct analogix_dp_device *dp);
|
||||
void analogix_dp_init_interrupt(struct analogix_dp_device *dp);
|
||||
void analogix_dp_reset(struct analogix_dp_device *dp);
|
||||
void analogix_dp_swreset(struct analogix_dp_device *dp);
|
||||
void analogix_dp_config_interrupt(struct analogix_dp_device *dp);
|
||||
void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp);
|
||||
void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp);
|
||||
enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp);
|
||||
void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable);
|
||||
void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
|
||||
enum analog_power_block block,
|
||||
bool enable);
|
||||
void analogix_dp_init_analog_func(struct analogix_dp_device *dp);
|
||||
void analogix_dp_init_hpd(struct analogix_dp_device *dp);
|
||||
void analogix_dp_force_hpd(struct analogix_dp_device *dp);
|
||||
enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp);
|
||||
void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp);
|
||||
void analogix_dp_reset_aux(struct analogix_dp_device *dp);
|
||||
void analogix_dp_init_aux(struct analogix_dp_device *dp);
|
||||
int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp);
|
||||
void analogix_dp_enable_sw_function(struct analogix_dp_device *dp);
|
||||
int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp);
|
||||
int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned char data);
|
||||
int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned char *data);
|
||||
int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned int count,
|
||||
unsigned char data[]);
|
||||
int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned int count,
|
||||
unsigned char data[]);
|
||||
int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
|
||||
unsigned int device_addr,
|
||||
unsigned int reg_addr);
|
||||
int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
|
||||
unsigned int device_addr,
|
||||
unsigned int reg_addr,
|
||||
unsigned int *data);
|
||||
int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
|
||||
unsigned int device_addr,
|
||||
unsigned int reg_addr,
|
||||
unsigned int count,
|
||||
unsigned char edid[]);
|
||||
void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype);
|
||||
void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype);
|
||||
void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count);
|
||||
void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count);
|
||||
void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
|
||||
bool enable);
|
||||
void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
|
||||
enum pattern_set pattern);
|
||||
void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp,
|
||||
u32 level);
|
||||
void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp,
|
||||
u32 level);
|
||||
void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp,
|
||||
u32 level);
|
||||
void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp,
|
||||
u32 level);
|
||||
void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp,
|
||||
u32 training_lane);
|
||||
void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp,
|
||||
u32 training_lane);
|
||||
void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp,
|
||||
u32 training_lane);
|
||||
void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp,
|
||||
u32 training_lane);
|
||||
u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp);
|
||||
u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp);
|
||||
u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp);
|
||||
u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp);
|
||||
void analogix_dp_reset_macro(struct analogix_dp_device *dp);
|
||||
void analogix_dp_init_video(struct analogix_dp_device *dp);
|
||||
|
||||
void analogix_dp_set_video_color_format(struct analogix_dp_device *dp);
|
||||
int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp);
|
||||
void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,
|
||||
enum clock_recovery_m_value_type type,
|
||||
u32 m_value,
|
||||
u32 n_value);
|
||||
void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type);
|
||||
void analogix_dp_enable_video_master(struct analogix_dp_device *dp,
|
||||
bool enable);
|
||||
void analogix_dp_start_video(struct analogix_dp_device *dp);
|
||||
int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp);
|
||||
void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp);
|
||||
void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
|
||||
void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
|
||||
#endif /* _ANALOGIX_DP_CORE_H */
|
1320
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
Normal file
1320
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Register definition file for Samsung DP driver
|
||||
* Register definition file for Analogix DP core driver
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* Author: Jingoo Han <jg1.han@samsung.com>
|
||||
@ -9,96 +9,104 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _EXYNOS_DP_REG_H
|
||||
#define _EXYNOS_DP_REG_H
|
||||
#ifndef _ANALOGIX_DP_REG_H
|
||||
#define _ANALOGIX_DP_REG_H
|
||||
|
||||
#define EXYNOS_DP_TX_SW_RESET 0x14
|
||||
#define EXYNOS_DP_FUNC_EN_1 0x18
|
||||
#define EXYNOS_DP_FUNC_EN_2 0x1C
|
||||
#define EXYNOS_DP_VIDEO_CTL_1 0x20
|
||||
#define EXYNOS_DP_VIDEO_CTL_2 0x24
|
||||
#define EXYNOS_DP_VIDEO_CTL_3 0x28
|
||||
#define ANALOGIX_DP_TX_SW_RESET 0x14
|
||||
#define ANALOGIX_DP_FUNC_EN_1 0x18
|
||||
#define ANALOGIX_DP_FUNC_EN_2 0x1C
|
||||
#define ANALOGIX_DP_VIDEO_CTL_1 0x20
|
||||
#define ANALOGIX_DP_VIDEO_CTL_2 0x24
|
||||
#define ANALOGIX_DP_VIDEO_CTL_3 0x28
|
||||
|
||||
#define EXYNOS_DP_VIDEO_CTL_8 0x3C
|
||||
#define EXYNOS_DP_VIDEO_CTL_10 0x44
|
||||
#define ANALOGIX_DP_VIDEO_CTL_8 0x3C
|
||||
#define ANALOGIX_DP_VIDEO_CTL_10 0x44
|
||||
|
||||
#define EXYNOS_DP_LANE_MAP 0x35C
|
||||
#define ANALOGIX_DP_PLL_REG_1 0xfc
|
||||
#define ANALOGIX_DP_PLL_REG_2 0x9e4
|
||||
#define ANALOGIX_DP_PLL_REG_3 0x9e8
|
||||
#define ANALOGIX_DP_PLL_REG_4 0x9ec
|
||||
#define ANALOGIX_DP_PLL_REG_5 0xa00
|
||||
|
||||
#define EXYNOS_DP_ANALOG_CTL_1 0x370
|
||||
#define EXYNOS_DP_ANALOG_CTL_2 0x374
|
||||
#define EXYNOS_DP_ANALOG_CTL_3 0x378
|
||||
#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C
|
||||
#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380
|
||||
#define ANALOGIX_DP_PD 0x12c
|
||||
|
||||
#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390
|
||||
#define ANALOGIX_DP_LANE_MAP 0x35C
|
||||
|
||||
#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4
|
||||
#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8
|
||||
#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC
|
||||
#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0
|
||||
#define EXYNOS_DP_INT_STA 0x3DC
|
||||
#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0
|
||||
#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4
|
||||
#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8
|
||||
#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC
|
||||
#define EXYNOS_DP_INT_STA_MASK 0x3F8
|
||||
#define EXYNOS_DP_INT_CTL 0x3FC
|
||||
#define ANALOGIX_DP_ANALOG_CTL_1 0x370
|
||||
#define ANALOGIX_DP_ANALOG_CTL_2 0x374
|
||||
#define ANALOGIX_DP_ANALOG_CTL_3 0x378
|
||||
#define ANALOGIX_DP_PLL_FILTER_CTL_1 0x37C
|
||||
#define ANALOGIX_DP_TX_AMP_TUNING_CTL 0x380
|
||||
|
||||
#define EXYNOS_DP_SYS_CTL_1 0x600
|
||||
#define EXYNOS_DP_SYS_CTL_2 0x604
|
||||
#define EXYNOS_DP_SYS_CTL_3 0x608
|
||||
#define EXYNOS_DP_SYS_CTL_4 0x60C
|
||||
#define ANALOGIX_DP_AUX_HW_RETRY_CTL 0x390
|
||||
|
||||
#define EXYNOS_DP_PKT_SEND_CTL 0x640
|
||||
#define EXYNOS_DP_HDCP_CTL 0x648
|
||||
#define ANALOGIX_DP_COMMON_INT_STA_1 0x3C4
|
||||
#define ANALOGIX_DP_COMMON_INT_STA_2 0x3C8
|
||||
#define ANALOGIX_DP_COMMON_INT_STA_3 0x3CC
|
||||
#define ANALOGIX_DP_COMMON_INT_STA_4 0x3D0
|
||||
#define ANALOGIX_DP_INT_STA 0x3DC
|
||||
#define ANALOGIX_DP_COMMON_INT_MASK_1 0x3E0
|
||||
#define ANALOGIX_DP_COMMON_INT_MASK_2 0x3E4
|
||||
#define ANALOGIX_DP_COMMON_INT_MASK_3 0x3E8
|
||||
#define ANALOGIX_DP_COMMON_INT_MASK_4 0x3EC
|
||||
#define ANALOGIX_DP_INT_STA_MASK 0x3F8
|
||||
#define ANALOGIX_DP_INT_CTL 0x3FC
|
||||
|
||||
#define EXYNOS_DP_LINK_BW_SET 0x680
|
||||
#define EXYNOS_DP_LANE_COUNT_SET 0x684
|
||||
#define EXYNOS_DP_TRAINING_PTN_SET 0x688
|
||||
#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C
|
||||
#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690
|
||||
#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694
|
||||
#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698
|
||||
#define ANALOGIX_DP_SYS_CTL_1 0x600
|
||||
#define ANALOGIX_DP_SYS_CTL_2 0x604
|
||||
#define ANALOGIX_DP_SYS_CTL_3 0x608
|
||||
#define ANALOGIX_DP_SYS_CTL_4 0x60C
|
||||
|
||||
#define EXYNOS_DP_DEBUG_CTL 0x6C0
|
||||
#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4
|
||||
#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8
|
||||
#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0
|
||||
#define ANALOGIX_DP_PKT_SEND_CTL 0x640
|
||||
#define ANALOGIX_DP_HDCP_CTL 0x648
|
||||
|
||||
#define EXYNOS_DP_M_VID_0 0x700
|
||||
#define EXYNOS_DP_M_VID_1 0x704
|
||||
#define EXYNOS_DP_M_VID_2 0x708
|
||||
#define EXYNOS_DP_N_VID_0 0x70C
|
||||
#define EXYNOS_DP_N_VID_1 0x710
|
||||
#define EXYNOS_DP_N_VID_2 0x714
|
||||
#define ANALOGIX_DP_LINK_BW_SET 0x680
|
||||
#define ANALOGIX_DP_LANE_COUNT_SET 0x684
|
||||
#define ANALOGIX_DP_TRAINING_PTN_SET 0x688
|
||||
#define ANALOGIX_DP_LN0_LINK_TRAINING_CTL 0x68C
|
||||
#define ANALOGIX_DP_LN1_LINK_TRAINING_CTL 0x690
|
||||
#define ANALOGIX_DP_LN2_LINK_TRAINING_CTL 0x694
|
||||
#define ANALOGIX_DP_LN3_LINK_TRAINING_CTL 0x698
|
||||
|
||||
#define EXYNOS_DP_PLL_CTL 0x71C
|
||||
#define EXYNOS_DP_PHY_PD 0x720
|
||||
#define EXYNOS_DP_PHY_TEST 0x724
|
||||
#define ANALOGIX_DP_DEBUG_CTL 0x6C0
|
||||
#define ANALOGIX_DP_HPD_DEGLITCH_L 0x6C4
|
||||
#define ANALOGIX_DP_HPD_DEGLITCH_H 0x6C8
|
||||
#define ANALOGIX_DP_LINK_DEBUG_CTL 0x6E0
|
||||
|
||||
#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730
|
||||
#define EXYNOS_DP_AUDIO_MARGIN 0x73C
|
||||
#define ANALOGIX_DP_M_VID_0 0x700
|
||||
#define ANALOGIX_DP_M_VID_1 0x704
|
||||
#define ANALOGIX_DP_M_VID_2 0x708
|
||||
#define ANALOGIX_DP_N_VID_0 0x70C
|
||||
#define ANALOGIX_DP_N_VID_1 0x710
|
||||
#define ANALOGIX_DP_N_VID_2 0x714
|
||||
|
||||
#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764
|
||||
#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778
|
||||
#define EXYNOS_DP_AUX_CH_STA 0x780
|
||||
#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788
|
||||
#define EXYNOS_DP_AUX_RX_COMM 0x78C
|
||||
#define EXYNOS_DP_BUFFER_DATA_CTL 0x790
|
||||
#define EXYNOS_DP_AUX_CH_CTL_1 0x794
|
||||
#define EXYNOS_DP_AUX_ADDR_7_0 0x798
|
||||
#define EXYNOS_DP_AUX_ADDR_15_8 0x79C
|
||||
#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0
|
||||
#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4
|
||||
#define ANALOGIX_DP_PLL_CTL 0x71C
|
||||
#define ANALOGIX_DP_PHY_PD 0x720
|
||||
#define ANALOGIX_DP_PHY_TEST 0x724
|
||||
|
||||
#define EXYNOS_DP_BUF_DATA_0 0x7C0
|
||||
#define ANALOGIX_DP_VIDEO_FIFO_THRD 0x730
|
||||
#define ANALOGIX_DP_AUDIO_MARGIN 0x73C
|
||||
|
||||
#define EXYNOS_DP_SOC_GENERAL_CTL 0x800
|
||||
#define ANALOGIX_DP_M_VID_GEN_FILTER_TH 0x764
|
||||
#define ANALOGIX_DP_M_AUD_GEN_FILTER_TH 0x778
|
||||
#define ANALOGIX_DP_AUX_CH_STA 0x780
|
||||
#define ANALOGIX_DP_AUX_CH_DEFER_CTL 0x788
|
||||
#define ANALOGIX_DP_AUX_RX_COMM 0x78C
|
||||
#define ANALOGIX_DP_BUFFER_DATA_CTL 0x790
|
||||
#define ANALOGIX_DP_AUX_CH_CTL_1 0x794
|
||||
#define ANALOGIX_DP_AUX_ADDR_7_0 0x798
|
||||
#define ANALOGIX_DP_AUX_ADDR_15_8 0x79C
|
||||
#define ANALOGIX_DP_AUX_ADDR_19_16 0x7A0
|
||||
#define ANALOGIX_DP_AUX_CH_CTL_2 0x7A4
|
||||
|
||||
/* EXYNOS_DP_TX_SW_RESET */
|
||||
#define ANALOGIX_DP_BUF_DATA_0 0x7C0
|
||||
|
||||
#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800
|
||||
|
||||
/* ANALOGIX_DP_TX_SW_RESET */
|
||||
#define RESET_DP_TX (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_FUNC_EN_1 */
|
||||
/* ANALOGIX_DP_FUNC_EN_1 */
|
||||
#define MASTER_VID_FUNC_EN_N (0x1 << 7)
|
||||
#define SLAVE_VID_FUNC_EN_N (0x1 << 5)
|
||||
#define AUD_FIFO_FUNC_EN_N (0x1 << 4)
|
||||
@ -107,17 +115,17 @@
|
||||
#define CRC_FUNC_EN_N (0x1 << 1)
|
||||
#define SW_FUNC_EN_N (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_FUNC_EN_2 */
|
||||
/* ANALOGIX_DP_FUNC_EN_2 */
|
||||
#define SSC_FUNC_EN_N (0x1 << 7)
|
||||
#define AUX_FUNC_EN_N (0x1 << 2)
|
||||
#define SERDES_FIFO_FUNC_EN_N (0x1 << 1)
|
||||
#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_VIDEO_CTL_1 */
|
||||
/* ANALOGIX_DP_VIDEO_CTL_1 */
|
||||
#define VIDEO_EN (0x1 << 7)
|
||||
#define HDCP_VIDEO_MUTE (0x1 << 6)
|
||||
|
||||
/* EXYNOS_DP_VIDEO_CTL_1 */
|
||||
/* ANALOGIX_DP_VIDEO_CTL_1 */
|
||||
#define IN_D_RANGE_MASK (0x1 << 7)
|
||||
#define IN_D_RANGE_SHIFT (7)
|
||||
#define IN_D_RANGE_CEA (0x1 << 7)
|
||||
@ -134,7 +142,7 @@
|
||||
#define IN_COLOR_F_YCBCR422 (0x1 << 0)
|
||||
#define IN_COLOR_F_RGB (0x0 << 0)
|
||||
|
||||
/* EXYNOS_DP_VIDEO_CTL_3 */
|
||||
/* ANALOGIX_DP_VIDEO_CTL_3 */
|
||||
#define IN_YC_COEFFI_MASK (0x1 << 7)
|
||||
#define IN_YC_COEFFI_SHIFT (7)
|
||||
#define IN_YC_COEFFI_ITU709 (0x1 << 7)
|
||||
@ -144,17 +152,21 @@
|
||||
#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4)
|
||||
#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
|
||||
|
||||
/* EXYNOS_DP_VIDEO_CTL_8 */
|
||||
/* ANALOGIX_DP_VIDEO_CTL_8 */
|
||||
#define VID_HRES_TH(x) (((x) & 0xf) << 4)
|
||||
#define VID_VRES_TH(x) (((x) & 0xf) << 0)
|
||||
|
||||
/* EXYNOS_DP_VIDEO_CTL_10 */
|
||||
/* ANALOGIX_DP_VIDEO_CTL_10 */
|
||||
#define FORMAT_SEL (0x1 << 4)
|
||||
#define INTERACE_SCAN_CFG (0x1 << 2)
|
||||
#define VSYNC_POLARITY_CFG (0x1 << 1)
|
||||
#define HSYNC_POLARITY_CFG (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_LANE_MAP */
|
||||
/* ANALOGIX_DP_PLL_REG_1 */
|
||||
#define REF_CLK_24M (0x1 << 1)
|
||||
#define REF_CLK_27M (0x0 << 1)
|
||||
|
||||
/* ANALOGIX_DP_LANE_MAP */
|
||||
#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
|
||||
#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6)
|
||||
#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6)
|
||||
@ -172,30 +184,30 @@
|
||||
#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0)
|
||||
#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
|
||||
|
||||
/* EXYNOS_DP_ANALOG_CTL_1 */
|
||||
/* ANALOGIX_DP_ANALOG_CTL_1 */
|
||||
#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4)
|
||||
|
||||
/* EXYNOS_DP_ANALOG_CTL_2 */
|
||||
/* ANALOGIX_DP_ANALOG_CTL_2 */
|
||||
#define SEL_24M (0x1 << 3)
|
||||
#define TX_DVDD_BIT_1_0625V (0x4 << 0)
|
||||
|
||||
/* EXYNOS_DP_ANALOG_CTL_3 */
|
||||
/* ANALOGIX_DP_ANALOG_CTL_3 */
|
||||
#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5)
|
||||
#define VCO_BIT_600_MICRO (0x5 << 0)
|
||||
|
||||
/* EXYNOS_DP_PLL_FILTER_CTL_1 */
|
||||
/* ANALOGIX_DP_PLL_FILTER_CTL_1 */
|
||||
#define PD_RING_OSC (0x1 << 6)
|
||||
#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4)
|
||||
#define TX_CUR1_2X (0x1 << 2)
|
||||
#define TX_CUR_16_MA (0x3 << 0)
|
||||
|
||||
/* EXYNOS_DP_TX_AMP_TUNING_CTL */
|
||||
/* ANALOGIX_DP_TX_AMP_TUNING_CTL */
|
||||
#define CH3_AMP_400_MV (0x0 << 24)
|
||||
#define CH2_AMP_400_MV (0x0 << 16)
|
||||
#define CH1_AMP_400_MV (0x0 << 8)
|
||||
#define CH0_AMP_400_MV (0x0 << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_HW_RETRY_CTL */
|
||||
/* ANALOGIX_DP_AUX_HW_RETRY_CTL */
|
||||
#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8)
|
||||
#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3)
|
||||
#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
|
||||
@ -204,7 +216,7 @@
|
||||
#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3)
|
||||
#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0)
|
||||
|
||||
/* EXYNOS_DP_COMMON_INT_STA_1 */
|
||||
/* ANALOGIX_DP_COMMON_INT_STA_1 */
|
||||
#define VSYNC_DET (0x1 << 7)
|
||||
#define PLL_LOCK_CHG (0x1 << 6)
|
||||
#define SPDIF_ERR (0x1 << 5)
|
||||
@ -214,19 +226,19 @@
|
||||
#define VID_CLK_CHG (0x1 << 1)
|
||||
#define SW_INT (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_COMMON_INT_STA_2 */
|
||||
/* ANALOGIX_DP_COMMON_INT_STA_2 */
|
||||
#define ENC_EN_CHG (0x1 << 6)
|
||||
#define HW_BKSV_RDY (0x1 << 3)
|
||||
#define HW_SHA_DONE (0x1 << 2)
|
||||
#define HW_AUTH_STATE_CHG (0x1 << 1)
|
||||
#define HW_AUTH_DONE (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_COMMON_INT_STA_3 */
|
||||
/* ANALOGIX_DP_COMMON_INT_STA_3 */
|
||||
#define AFIFO_UNDER (0x1 << 7)
|
||||
#define AFIFO_OVER (0x1 << 6)
|
||||
#define R0_CHK_FLAG (0x1 << 5)
|
||||
|
||||
/* EXYNOS_DP_COMMON_INT_STA_4 */
|
||||
/* ANALOGIX_DP_COMMON_INT_STA_4 */
|
||||
#define PSR_ACTIVE (0x1 << 7)
|
||||
#define PSR_INACTIVE (0x1 << 6)
|
||||
#define SPDIF_BI_PHASE_ERR (0x1 << 5)
|
||||
@ -234,29 +246,29 @@
|
||||
#define HPD_LOST (0x1 << 1)
|
||||
#define PLUG (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_INT_STA */
|
||||
/* ANALOGIX_DP_INT_STA */
|
||||
#define INT_HPD (0x1 << 6)
|
||||
#define HW_TRAINING_FINISH (0x1 << 5)
|
||||
#define RPLY_RECEIV (0x1 << 1)
|
||||
#define AUX_ERR (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_INT_CTL */
|
||||
/* ANALOGIX_DP_INT_CTL */
|
||||
#define SOFT_INT_CTRL (0x1 << 2)
|
||||
#define INT_POL1 (0x1 << 1)
|
||||
#define INT_POL0 (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_SYS_CTL_1 */
|
||||
/* ANALOGIX_DP_SYS_CTL_1 */
|
||||
#define DET_STA (0x1 << 2)
|
||||
#define FORCE_DET (0x1 << 1)
|
||||
#define DET_CTRL (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_SYS_CTL_2 */
|
||||
/* ANALOGIX_DP_SYS_CTL_2 */
|
||||
#define CHA_CRI(x) (((x) & 0xf) << 4)
|
||||
#define CHA_STA (0x1 << 2)
|
||||
#define FORCE_CHA (0x1 << 1)
|
||||
#define CHA_CTRL (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_SYS_CTL_3 */
|
||||
/* ANALOGIX_DP_SYS_CTL_3 */
|
||||
#define HPD_STATUS (0x1 << 6)
|
||||
#define F_HPD (0x1 << 5)
|
||||
#define HPD_CTRL (0x1 << 4)
|
||||
@ -265,13 +277,13 @@
|
||||
#define F_VALID (0x1 << 1)
|
||||
#define VALID_CTRL (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_SYS_CTL_4 */
|
||||
/* ANALOGIX_DP_SYS_CTL_4 */
|
||||
#define FIX_M_AUD (0x1 << 4)
|
||||
#define ENHANCED (0x1 << 3)
|
||||
#define FIX_M_VID (0x1 << 2)
|
||||
#define M_VID_UPDATE_CTRL (0x3 << 0)
|
||||
|
||||
/* EXYNOS_DP_TRAINING_PTN_SET */
|
||||
/* ANALOGIX_DP_TRAINING_PTN_SET */
|
||||
#define SCRAMBLER_TYPE (0x1 << 9)
|
||||
#define HW_LINK_TRAINING_PATTERN (0x1 << 8)
|
||||
#define SCRAMBLING_DISABLE (0x1 << 5)
|
||||
@ -285,24 +297,24 @@
|
||||
#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0)
|
||||
#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
|
||||
|
||||
/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
|
||||
/* ANALOGIX_DP_LN0_LINK_TRAINING_CTL */
|
||||
#define PRE_EMPHASIS_SET_MASK (0x3 << 3)
|
||||
#define PRE_EMPHASIS_SET_SHIFT (3)
|
||||
|
||||
/* EXYNOS_DP_DEBUG_CTL */
|
||||
/* ANALOGIX_DP_DEBUG_CTL */
|
||||
#define PLL_LOCK (0x1 << 4)
|
||||
#define F_PLL_LOCK (0x1 << 3)
|
||||
#define PLL_LOCK_CTRL (0x1 << 2)
|
||||
#define PN_INV (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_PLL_CTL */
|
||||
/* ANALOGIX_DP_PLL_CTL */
|
||||
#define DP_PLL_PD (0x1 << 7)
|
||||
#define DP_PLL_RESET (0x1 << 6)
|
||||
#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4)
|
||||
#define DP_PLL_REF_BIT_1_1250V (0x5 << 0)
|
||||
#define DP_PLL_REF_BIT_1_2500V (0x7 << 0)
|
||||
|
||||
/* EXYNOS_DP_PHY_PD */
|
||||
/* ANALOGIX_DP_PHY_PD */
|
||||
#define DP_PHY_PD (0x1 << 5)
|
||||
#define AUX_PD (0x1 << 4)
|
||||
#define CH3_PD (0x1 << 3)
|
||||
@ -310,28 +322,28 @@
|
||||
#define CH1_PD (0x1 << 1)
|
||||
#define CH0_PD (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_PHY_TEST */
|
||||
/* ANALOGIX_DP_PHY_TEST */
|
||||
#define MACRO_RST (0x1 << 5)
|
||||
#define CH1_TEST (0x1 << 1)
|
||||
#define CH0_TEST (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_CH_STA */
|
||||
/* ANALOGIX_DP_AUX_CH_STA */
|
||||
#define AUX_BUSY (0x1 << 4)
|
||||
#define AUX_STATUS_MASK (0xf << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_CH_DEFER_CTL */
|
||||
/* ANALOGIX_DP_AUX_CH_DEFER_CTL */
|
||||
#define DEFER_CTRL_EN (0x1 << 7)
|
||||
#define DEFER_COUNT(x) (((x) & 0x7f) << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_RX_COMM */
|
||||
/* ANALOGIX_DP_AUX_RX_COMM */
|
||||
#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
|
||||
#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
|
||||
|
||||
/* EXYNOS_DP_BUFFER_DATA_CTL */
|
||||
/* ANALOGIX_DP_BUFFER_DATA_CTL */
|
||||
#define BUF_CLR (0x1 << 7)
|
||||
#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_CH_CTL_1 */
|
||||
/* ANALOGIX_DP_AUX_CH_CTL_1 */
|
||||
#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4)
|
||||
#define AUX_TX_COMM_MASK (0xf << 0)
|
||||
#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3)
|
||||
@ -340,20 +352,20 @@
|
||||
#define AUX_TX_COMM_WRITE (0x0 << 0)
|
||||
#define AUX_TX_COMM_READ (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_ADDR_7_0 */
|
||||
/* ANALOGIX_DP_AUX_ADDR_7_0 */
|
||||
#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
|
||||
|
||||
/* EXYNOS_DP_AUX_ADDR_15_8 */
|
||||
/* ANALOGIX_DP_AUX_ADDR_15_8 */
|
||||
#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
|
||||
|
||||
/* EXYNOS_DP_AUX_ADDR_19_16 */
|
||||
/* ANALOGIX_DP_AUX_ADDR_19_16 */
|
||||
#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
|
||||
|
||||
/* EXYNOS_DP_AUX_CH_CTL_2 */
|
||||
/* ANALOGIX_DP_AUX_CH_CTL_2 */
|
||||
#define ADDR_ONLY (0x1 << 1)
|
||||
#define AUX_EN (0x1 << 0)
|
||||
|
||||
/* EXYNOS_DP_SOC_GENERAL_CTL */
|
||||
/* ANALOGIX_DP_SOC_GENERAL_CTL */
|
||||
#define AUDIO_MODE_SPDIF_MODE (0x1 << 8)
|
||||
#define AUDIO_MODE_MASTER_MODE (0x0 << 8)
|
||||
#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4)
|
||||
@ -363,4 +375,4 @@
|
||||
#define VIDEO_MODE_SLAVE_MODE (0x1 << 0)
|
||||
#define VIDEO_MODE_MASTER_MODE (0x0 << 0)
|
||||
|
||||
#endif /* _EXYNOS_DP_REG_H */
|
||||
#endif /* _ANALOGIX_DP_REG_H */
|
@ -71,8 +71,9 @@ config DRM_EXYNOS_DSI
|
||||
This enables support for Exynos MIPI-DSI device.
|
||||
|
||||
config DRM_EXYNOS_DP
|
||||
bool "Display Port"
|
||||
bool "EXYNOS specific extensions for Analogix DP driver"
|
||||
depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
|
||||
select DRM_ANALOGIX_DP
|
||||
default DRM_EXYNOS
|
||||
select DRM_PANEL
|
||||
help
|
||||
|
@ -12,7 +12,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER) += exynos_mixer.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o
|
||||
exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
|
||||
|
314
drivers/gpu/drm/exynos/exynos_dp.c
Normal file
314
drivers/gpu/drm/exynos/exynos_dp.c
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Samsung SoC DP (Display Port) interface driver.
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* Author: Jingoo Han <jg1.han@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/component.h>
|
||||
#include <video/of_display_timing.h>
|
||||
#include <video/of_videomode.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <drm/bridge/analogix_dp.h>
|
||||
#include <drm/exynos_drm.h>
|
||||
|
||||
#include "exynos_drm_crtc.h"
|
||||
|
||||
#define to_dp(nm) container_of(nm, struct exynos_dp_device, nm)
|
||||
|
||||
struct exynos_dp_device {
|
||||
struct drm_encoder encoder;
|
||||
struct drm_connector connector;
|
||||
struct drm_bridge *ptn_bridge;
|
||||
struct drm_device *drm_dev;
|
||||
struct device *dev;
|
||||
|
||||
struct videomode vm;
|
||||
struct analogix_dp_plat_data plat_data;
|
||||
};
|
||||
|
||||
int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data,
|
||||
bool enable)
|
||||
{
|
||||
struct exynos_dp_device *dp = to_dp(plat_data);
|
||||
struct drm_encoder *encoder = &dp->encoder;
|
||||
struct exynos_drm_crtc *crtc;
|
||||
|
||||
if (!encoder)
|
||||
return -1;
|
||||
|
||||
crtc = to_exynos_crtc(encoder->crtc);
|
||||
if (crtc && crtc->ops && crtc->ops->clock_enable)
|
||||
crtc->ops->clock_enable(crtc, enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_dp_poweron(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
return exynos_dp_crtc_clock_enable(plat_data, true);
|
||||
}
|
||||
|
||||
static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
return exynos_dp_crtc_clock_enable(plat_data, false);
|
||||
}
|
||||
|
||||
static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct exynos_dp_device *dp = to_dp(plat_data);
|
||||
struct drm_connector *connector = &dp->connector;
|
||||
struct drm_display_mode *mode;
|
||||
int num_modes = 0;
|
||||
|
||||
if (dp->plat_data.panel)
|
||||
return num_modes;
|
||||
|
||||
mode = drm_mode_create(connector->dev);
|
||||
if (!mode) {
|
||||
DRM_ERROR("failed to create a new display mode.\n");
|
||||
return num_modes;
|
||||
}
|
||||
|
||||
drm_display_mode_from_videomode(&dp->vm, mode);
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return num_modes + 1;
|
||||
}
|
||||
|
||||
static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
|
||||
struct drm_bridge *bridge,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct exynos_dp_device *dp = to_dp(plat_data);
|
||||
struct drm_encoder *encoder = &dp->encoder;
|
||||
int ret;
|
||||
|
||||
drm_connector_register(connector);
|
||||
|
||||
/* Pre-empt DP connector creation if there's a bridge */
|
||||
if (dp->ptn_bridge) {
|
||||
bridge->next = dp->ptn_bridge;
|
||||
dp->ptn_bridge->encoder = encoder;
|
||||
ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to attach bridge to drm\n");
|
||||
bridge->next = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_dp_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
}
|
||||
|
||||
static void exynos_dp_nop(struct drm_encoder *encoder)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
|
||||
.mode_set = exynos_dp_mode_set,
|
||||
.enable = exynos_dp_nop,
|
||||
.disable = exynos_dp_nop,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs exynos_dp_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = of_get_videomode(dp->dev->of_node, &dp->vm, OF_USE_NATIVE_MODE);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
||||
struct drm_encoder *encoder = &dp->encoder;
|
||||
struct drm_device *drm_dev = data;
|
||||
int pipe, ret;
|
||||
|
||||
/*
|
||||
* Just like the probe function said, we don't need the
|
||||
* device drvrate anymore, we should leave the charge to
|
||||
* analogix dp driver, set the device drvdata to NULL.
|
||||
*/
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
dp->dev = dev;
|
||||
dp->drm_dev = drm_dev;
|
||||
|
||||
dp->plat_data.dev_type = EXYNOS_DP;
|
||||
dp->plat_data.power_on = exynos_dp_poweron;
|
||||
dp->plat_data.power_off = exynos_dp_poweroff;
|
||||
dp->plat_data.attach = exynos_dp_bridge_attach;
|
||||
dp->plat_data.get_modes = exynos_dp_get_modes;
|
||||
|
||||
if (!dp->plat_data.panel && !dp->ptn_bridge) {
|
||||
ret = exynos_dp_dt_parse_panel(dp);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
|
||||
EXYNOS_DISPLAY_TYPE_LCD);
|
||||
if (pipe < 0)
|
||||
return pipe;
|
||||
|
||||
encoder->possible_crtcs = 1 << pipe;
|
||||
|
||||
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
|
||||
|
||||
drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
||||
drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
|
||||
|
||||
dp->plat_data.encoder = encoder;
|
||||
|
||||
return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
}
|
||||
|
||||
static void exynos_dp_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
return analogix_dp_unbind(dev, master, data);
|
||||
}
|
||||
|
||||
static const struct component_ops exynos_dp_ops = {
|
||||
.bind = exynos_dp_bind,
|
||||
.unbind = exynos_dp_unbind,
|
||||
};
|
||||
|
||||
static int exynos_dp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = NULL, *endpoint = NULL;
|
||||
struct exynos_dp_device *dp;
|
||||
|
||||
dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
|
||||
GFP_KERNEL);
|
||||
if (!dp)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* We just use the drvdata until driver run into component
|
||||
* add function, and then we would set drvdata to null, so
|
||||
* that analogix dp driver would take charge of the drvdata.
|
||||
*/
|
||||
platform_set_drvdata(pdev, dp);
|
||||
|
||||
/* This is for the backward compatibility. */
|
||||
np = of_parse_phandle(dev->of_node, "panel", 0);
|
||||
if (np) {
|
||||
dp->plat_data.panel = of_drm_find_panel(np);
|
||||
of_node_put(np);
|
||||
if (!dp->plat_data.panel)
|
||||
return -EPROBE_DEFER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
|
||||
if (endpoint) {
|
||||
np = of_graph_get_remote_port_parent(endpoint);
|
||||
if (np) {
|
||||
/* The remote port can be either a panel or a bridge */
|
||||
dp->plat_data.panel = of_drm_find_panel(np);
|
||||
if (!dp->plat_data.panel) {
|
||||
dp->ptn_bridge = of_drm_find_bridge(np);
|
||||
if (!dp->ptn_bridge) {
|
||||
of_node_put(np);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
of_node_put(np);
|
||||
} else {
|
||||
DRM_ERROR("no remote endpoint device node found.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
DRM_ERROR("no port endpoint subnode found.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
return component_add(&pdev->dev, &exynos_dp_ops);
|
||||
}
|
||||
|
||||
static int exynos_dp_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &exynos_dp_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int exynos_dp_suspend(struct device *dev)
|
||||
{
|
||||
return analogix_dp_suspend(dev);
|
||||
}
|
||||
|
||||
static int exynos_dp_resume(struct device *dev)
|
||||
{
|
||||
return analogix_dp_resume(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops exynos_dp_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(exynos_dp_suspend, exynos_dp_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id exynos_dp_match[] = {
|
||||
{ .compatible = "samsung,exynos5-dp" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, exynos_dp_match);
|
||||
|
||||
struct platform_driver dp_driver = {
|
||||
.probe = exynos_dp_probe,
|
||||
.remove = exynos_dp_remove,
|
||||
.driver = {
|
||||
.name = "exynos-dp",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &exynos_dp_pm_ops,
|
||||
.of_match_table = exynos_dp_match,
|
||||
},
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
|
||||
MODULE_DESCRIPTION("Samsung Specific Analogix-DP Driver Extension");
|
||||
MODULE_LICENSE("GPL v2");
|
File diff suppressed because it is too large
Load Diff
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* Header file for Samsung DP (Display Port) interface driver.
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co., Ltd.
|
||||
* Author: Jingoo Han <jg1.han@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _EXYNOS_DP_CORE_H
|
||||
#define _EXYNOS_DP_CORE_H
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/exynos_drm.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include "exynos_drm_drv.h"
|
||||
|
||||
#define DP_TIMEOUT_LOOP_COUNT 100
|
||||
#define MAX_CR_LOOP 5
|
||||
#define MAX_EQ_LOOP 5
|
||||
|
||||
enum link_rate_type {
|
||||
LINK_RATE_1_62GBPS = 0x06,
|
||||
LINK_RATE_2_70GBPS = 0x0a
|
||||
};
|
||||
|
||||
enum link_lane_count_type {
|
||||
LANE_COUNT1 = 1,
|
||||
LANE_COUNT2 = 2,
|
||||
LANE_COUNT4 = 4
|
||||
};
|
||||
|
||||
enum link_training_state {
|
||||
START,
|
||||
CLOCK_RECOVERY,
|
||||
EQUALIZER_TRAINING,
|
||||
FINISHED,
|
||||
FAILED
|
||||
};
|
||||
|
||||
enum voltage_swing_level {
|
||||
VOLTAGE_LEVEL_0,
|
||||
VOLTAGE_LEVEL_1,
|
||||
VOLTAGE_LEVEL_2,
|
||||
VOLTAGE_LEVEL_3,
|
||||
};
|
||||
|
||||
enum pre_emphasis_level {
|
||||
PRE_EMPHASIS_LEVEL_0,
|
||||
PRE_EMPHASIS_LEVEL_1,
|
||||
PRE_EMPHASIS_LEVEL_2,
|
||||
PRE_EMPHASIS_LEVEL_3,
|
||||
};
|
||||
|
||||
enum pattern_set {
|
||||
PRBS7,
|
||||
D10_2,
|
||||
TRAINING_PTN1,
|
||||
TRAINING_PTN2,
|
||||
DP_NONE
|
||||
};
|
||||
|
||||
enum color_space {
|
||||
COLOR_RGB,
|
||||
COLOR_YCBCR422,
|
||||
COLOR_YCBCR444
|
||||
};
|
||||
|
||||
enum color_depth {
|
||||
COLOR_6,
|
||||
COLOR_8,
|
||||
COLOR_10,
|
||||
COLOR_12
|
||||
};
|
||||
|
||||
enum color_coefficient {
|
||||
COLOR_YCBCR601,
|
||||
COLOR_YCBCR709
|
||||
};
|
||||
|
||||
enum dynamic_range {
|
||||
VESA,
|
||||
CEA
|
||||
};
|
||||
|
||||
enum pll_status {
|
||||
PLL_UNLOCKED,
|
||||
PLL_LOCKED
|
||||
};
|
||||
|
||||
enum clock_recovery_m_value_type {
|
||||
CALCULATED_M,
|
||||
REGISTER_M
|
||||
};
|
||||
|
||||
enum video_timing_recognition_type {
|
||||
VIDEO_TIMING_FROM_CAPTURE,
|
||||
VIDEO_TIMING_FROM_REGISTER
|
||||
};
|
||||
|
||||
enum analog_power_block {
|
||||
AUX_BLOCK,
|
||||
CH0_BLOCK,
|
||||
CH1_BLOCK,
|
||||
CH2_BLOCK,
|
||||
CH3_BLOCK,
|
||||
ANALOG_TOTAL,
|
||||
POWER_ALL
|
||||
};
|
||||
|
||||
enum dp_irq_type {
|
||||
DP_IRQ_TYPE_HP_CABLE_IN,
|
||||
DP_IRQ_TYPE_HP_CABLE_OUT,
|
||||
DP_IRQ_TYPE_HP_CHANGE,
|
||||
DP_IRQ_TYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
struct video_info {
|
||||
char *name;
|
||||
|
||||
bool h_sync_polarity;
|
||||
bool v_sync_polarity;
|
||||
bool interlaced;
|
||||
|
||||
enum color_space color_space;
|
||||
enum dynamic_range dynamic_range;
|
||||
enum color_coefficient ycbcr_coeff;
|
||||
enum color_depth color_depth;
|
||||
|
||||
enum link_rate_type link_rate;
|
||||
enum link_lane_count_type lane_count;
|
||||
};
|
||||
|
||||
struct link_train {
|
||||
int eq_loop;
|
||||
int cr_loop[4];
|
||||
|
||||
u8 link_rate;
|
||||
u8 lane_count;
|
||||
u8 training_lane[4];
|
||||
|
||||
enum link_training_state lt_state;
|
||||
};
|
||||
|
||||
struct exynos_dp_device {
|
||||
struct drm_encoder encoder;
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
struct drm_connector connector;
|
||||
struct drm_panel *panel;
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_bridge *ptn_bridge;
|
||||
struct clk *clock;
|
||||
unsigned int irq;
|
||||
void __iomem *reg_base;
|
||||
|
||||
struct video_info *video_info;
|
||||
struct link_train link_train;
|
||||
struct work_struct hotplug_work;
|
||||
struct phy *phy;
|
||||
int dpms_mode;
|
||||
int hpd_gpio;
|
||||
struct videomode vm;
|
||||
};
|
||||
|
||||
/* exynos_dp_reg.c */
|
||||
void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_stop_video(struct exynos_dp_device *dp);
|
||||
void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
|
||||
void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
|
||||
void exynos_dp_reset(struct exynos_dp_device *dp);
|
||||
void exynos_dp_swreset(struct exynos_dp_device *dp);
|
||||
void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
|
||||
enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
|
||||
void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
|
||||
enum analog_power_block block,
|
||||
bool enable);
|
||||
void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
|
||||
void exynos_dp_init_hpd(struct exynos_dp_device *dp);
|
||||
enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
|
||||
void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
|
||||
void exynos_dp_reset_aux(struct exynos_dp_device *dp);
|
||||
void exynos_dp_init_aux(struct exynos_dp_device *dp);
|
||||
int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
|
||||
void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
|
||||
int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
|
||||
int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned char data);
|
||||
int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned char *data);
|
||||
int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned int count,
|
||||
unsigned char data[]);
|
||||
int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
|
||||
unsigned int reg_addr,
|
||||
unsigned int count,
|
||||
unsigned char data[]);
|
||||
int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
|
||||
unsigned int device_addr,
|
||||
unsigned int reg_addr);
|
||||
int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
|
||||
unsigned int device_addr,
|
||||
unsigned int reg_addr,
|
||||
unsigned int *data);
|
||||
int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
|
||||
unsigned int device_addr,
|
||||
unsigned int reg_addr,
|
||||
unsigned int count,
|
||||
unsigned char edid[]);
|
||||
void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
|
||||
void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
|
||||
void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
|
||||
void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
|
||||
void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
|
||||
enum pattern_set pattern);
|
||||
void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
|
||||
void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
|
||||
void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
|
||||
void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
|
||||
void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
|
||||
u32 training_lane);
|
||||
void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
|
||||
u32 training_lane);
|
||||
void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
|
||||
u32 training_lane);
|
||||
void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
|
||||
u32 training_lane);
|
||||
u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
|
||||
u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
|
||||
u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
|
||||
u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
|
||||
void exynos_dp_reset_macro(struct exynos_dp_device *dp);
|
||||
void exynos_dp_init_video(struct exynos_dp_device *dp);
|
||||
|
||||
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
|
||||
int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
|
||||
void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
|
||||
enum clock_recovery_m_value_type type,
|
||||
u32 m_value,
|
||||
u32 n_value);
|
||||
void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
|
||||
void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_start_video(struct exynos_dp_device *dp);
|
||||
int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
|
||||
void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
|
||||
void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
|
||||
void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
|
||||
|
||||
/* I2C EDID Chip ID, Slave Address */
|
||||
#define I2C_EDID_DEVICE_ADDR 0x50
|
||||
#define I2C_E_EDID_DEVICE_ADDR 0x30
|
||||
|
||||
#define EDID_BLOCK_LENGTH 0x80
|
||||
#define EDID_HEADER_PATTERN 0x00
|
||||
#define EDID_EXTENSION_FLAG 0x7e
|
||||
#define EDID_CHECKSUM 0x7f
|
||||
|
||||
/* DP_MAX_LANE_COUNT */
|
||||
#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
|
||||
#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
|
||||
|
||||
/* DP_LANE_COUNT_SET */
|
||||
#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
|
||||
|
||||
/* DP_TRAINING_LANE0_SET */
|
||||
#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
|
||||
#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
|
||||
#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
|
||||
#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
|
||||
|
||||
#endif /* _EXYNOS_DP_CORE_H */
|
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,15 @@ config DRM_ROCKCHIP
|
||||
2D or 3D acceleration; acceleration is performed by other
|
||||
IP found on the SoC.
|
||||
|
||||
config ROCKCHIP_ANALOGIX_DP
|
||||
tristate "Rockchip specific extensions for Analogix DP driver"
|
||||
depends on DRM_ROCKCHIP
|
||||
select DRM_ANALOGIX_DP
|
||||
help
|
||||
This selects support for Rockchip SoC specific extensions
|
||||
for the Analogix Core DP driver. If you want to enable DP
|
||||
on RK3288 based SoC, you should selet this option.
|
||||
|
||||
config ROCKCHIP_DW_HDMI
|
||||
tristate "Rockchip specific extensions for Synopsys DW HDMI"
|
||||
depends on DRM_ROCKCHIP
|
||||
|
@ -6,6 +6,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
|
||||
rockchip_drm_gem.o rockchip_drm_vop.o
|
||||
rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
|
||||
|
||||
obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
|
||||
obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
|
||||
obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
|
||||
obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
|
||||
|
384
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
Normal file
384
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Rockchip SoC DP (Display Port) interface driver.
|
||||
*
|
||||
* Copyright (C) Fuzhou Rockchip Electronics Co., Ltd.
|
||||
* Author: Andy Yan <andy.yan@rock-chips.com>
|
||||
* Yakir Yang <ykk@rock-chips.com>
|
||||
* Jeff Chen <jeff.chen@rock-chips.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/component.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <video/of_videomode.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include <drm/bridge/analogix_dp.h>
|
||||
|
||||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_vop.h"
|
||||
|
||||
#define to_dp(nm) container_of(nm, struct rockchip_dp_device, nm)
|
||||
|
||||
/* dp grf register offset */
|
||||
#define GRF_SOC_CON6 0x025c
|
||||
#define GRF_EDP_LCD_SEL_MASK BIT(5)
|
||||
#define GRF_EDP_SEL_VOP_LIT BIT(5)
|
||||
#define GRF_EDP_SEL_VOP_BIG 0
|
||||
|
||||
struct rockchip_dp_device {
|
||||
struct drm_device *drm_dev;
|
||||
struct device *dev;
|
||||
struct drm_encoder encoder;
|
||||
struct drm_display_mode mode;
|
||||
|
||||
struct clk *pclk;
|
||||
struct regmap *grf;
|
||||
struct reset_control *rst;
|
||||
|
||||
struct analogix_dp_plat_data plat_data;
|
||||
};
|
||||
|
||||
static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
|
||||
{
|
||||
reset_control_assert(dp->rst);
|
||||
usleep_range(10, 20);
|
||||
reset_control_deassert(dp->rst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct rockchip_dp_device *dp = to_dp(plat_data);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(dp->pclk);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to enable pclk %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rockchip_dp_pre_init(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to dp pre init %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct rockchip_dp_device *dp = to_dp(plat_data);
|
||||
|
||||
clk_disable_unprepare(dp->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* do nothing */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct rockchip_dp_device *dp = to_dp(encoder);
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* FIXME(Yakir): driver should configure the CRTC output video
|
||||
* mode with the display information which indicated the monitor
|
||||
* support colorimetry.
|
||||
*
|
||||
* But don't know why the CRTC driver seems could only output the
|
||||
* RGBaaa rightly. For example, if connect the "innolux,n116bge"
|
||||
* eDP screen, EDID would indicated that screen only accepted the
|
||||
* 6bpc mode. But if I configure CRTC to RGB666 output, then eDP
|
||||
* screen would show a blue picture (RGB888 show a green picture).
|
||||
* But if I configure CTRC to RGBaaa, and eDP driver still keep
|
||||
* RGB666 input video mode, then screen would works prefect.
|
||||
*/
|
||||
ret = rockchip_drm_crtc_mode_config(encoder->crtc,
|
||||
DRM_MODE_CONNECTOR_eDP,
|
||||
ROCKCHIP_OUT_MODE_AAAA);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "Could not set crtc mode config (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (ret)
|
||||
val = GRF_EDP_SEL_VOP_LIT | (GRF_EDP_LCD_SEL_MASK << 16);
|
||||
else
|
||||
val = GRF_EDP_SEL_VOP_BIG | (GRF_EDP_LCD_SEL_MASK << 16);
|
||||
|
||||
dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
|
||||
|
||||
ret = regmap_write(dp->grf, GRF_SOC_CON6, val);
|
||||
if (ret != 0) {
|
||||
dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
|
||||
.mode_fixup = rockchip_dp_drm_encoder_mode_fixup,
|
||||
.mode_set = rockchip_dp_drm_encoder_mode_set,
|
||||
.enable = rockchip_dp_drm_encoder_enable,
|
||||
.disable = rockchip_dp_drm_encoder_nop,
|
||||
};
|
||||
|
||||
static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
}
|
||||
|
||||
static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
|
||||
.destroy = rockchip_dp_drm_encoder_destroy,
|
||||
};
|
||||
|
||||
static int rockchip_dp_init(struct rockchip_dp_device *dp)
|
||||
{
|
||||
struct device *dev = dp->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
||||
if (IS_ERR(dp->grf)) {
|
||||
dev_err(dev, "failed to get rockchip,grf property\n");
|
||||
return PTR_ERR(dp->grf);
|
||||
}
|
||||
|
||||
dp->pclk = devm_clk_get(dev, "pclk");
|
||||
if (IS_ERR(dp->pclk)) {
|
||||
dev_err(dev, "failed to get pclk property\n");
|
||||
return PTR_ERR(dp->pclk);
|
||||
}
|
||||
|
||||
dp->rst = devm_reset_control_get(dev, "dp");
|
||||
if (IS_ERR(dp->rst)) {
|
||||
dev_err(dev, "failed to get dp reset control\n");
|
||||
return PTR_ERR(dp->rst);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dp->pclk);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to enable pclk %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rockchip_dp_pre_init(dp);
|
||||
if (ret < 0) {
|
||||
dev_err(dp->dev, "failed to pre init %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dp_drm_create_encoder(struct rockchip_dp_device *dp)
|
||||
{
|
||||
struct drm_encoder *encoder = &dp->encoder;
|
||||
struct drm_device *drm_dev = dp->drm_dev;
|
||||
struct device *dev = dp->dev;
|
||||
int ret;
|
||||
|
||||
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
|
||||
dev->of_node);
|
||||
DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
|
||||
|
||||
ret = drm_encoder_init(drm_dev, encoder, &rockchip_dp_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize encoder with drm\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_encoder_helper_add(encoder, &rockchip_dp_encoder_helper_funcs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dp_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Just like the probe function said, we don't need the
|
||||
* device drvrate anymore, we should leave the charge to
|
||||
* analogix dp driver, set the device drvdata to NULL.
|
||||
*/
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
ret = rockchip_dp_init(dp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dp->drm_dev = drm_dev;
|
||||
|
||||
ret = rockchip_dp_drm_create_encoder(dp);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create drm encoder\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dp->plat_data.encoder = &dp->encoder;
|
||||
|
||||
dp->plat_data.dev_type = RK3288_DP;
|
||||
dp->plat_data.power_on = rockchip_dp_poweron;
|
||||
dp->plat_data.power_off = rockchip_dp_powerdown;
|
||||
|
||||
return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
}
|
||||
|
||||
static void rockchip_dp_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
return analogix_dp_unbind(dev, master, data);
|
||||
}
|
||||
|
||||
static const struct component_ops rockchip_dp_component_ops = {
|
||||
.bind = rockchip_dp_bind,
|
||||
.unbind = rockchip_dp_unbind,
|
||||
};
|
||||
|
||||
static int rockchip_dp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *panel_node, *port, *endpoint;
|
||||
struct rockchip_dp_device *dp;
|
||||
struct drm_panel *panel;
|
||||
|
||||
port = of_graph_get_port_by_id(dev->of_node, 1);
|
||||
if (!port) {
|
||||
dev_err(dev, "can't find output port\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
endpoint = of_get_child_by_name(port, "endpoint");
|
||||
of_node_put(port);
|
||||
if (!endpoint) {
|
||||
dev_err(dev, "no output endpoint found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
panel_node = of_graph_get_remote_port_parent(endpoint);
|
||||
of_node_put(endpoint);
|
||||
if (!panel_node) {
|
||||
dev_err(dev, "no output node found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
panel = of_drm_find_panel(panel_node);
|
||||
if (!panel) {
|
||||
DRM_ERROR("failed to find panel\n");
|
||||
of_node_put(panel_node);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
of_node_put(panel_node);
|
||||
|
||||
dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
|
||||
if (!dp)
|
||||
return -ENOMEM;
|
||||
|
||||
dp->dev = dev;
|
||||
|
||||
dp->plat_data.panel = panel;
|
||||
|
||||
/*
|
||||
* We just use the drvdata until driver run into component
|
||||
* add function, and then we would set drvdata to null, so
|
||||
* that analogix dp driver could take charge of the drvdata.
|
||||
*/
|
||||
platform_set_drvdata(pdev, dp);
|
||||
|
||||
return component_add(dev, &rockchip_dp_component_ops);
|
||||
}
|
||||
|
||||
static int rockchip_dp_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &rockchip_dp_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rockchip_dp_suspend(struct device *dev)
|
||||
{
|
||||
return analogix_dp_suspend(dev);
|
||||
}
|
||||
|
||||
static int rockchip_dp_resume(struct device *dev)
|
||||
{
|
||||
return analogix_dp_resume(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops rockchip_dp_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(rockchip_dp_suspend, rockchip_dp_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id rockchip_dp_dt_ids[] = {
|
||||
{.compatible = "rockchip,rk3288-dp",},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
|
||||
|
||||
static struct platform_driver rockchip_dp_driver = {
|
||||
.probe = rockchip_dp_probe,
|
||||
.remove = rockchip_dp_remove,
|
||||
.driver = {
|
||||
.name = "rockchip-dp",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &rockchip_dp_pm_ops,
|
||||
.of_match_table = of_match_ptr(rockchip_dp_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rockchip_dp_driver);
|
||||
|
||||
MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
|
||||
MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension");
|
||||
MODULE_LICENSE("GPL v2");
|
41
include/drm/bridge/analogix_dp.h
Normal file
41
include/drm/bridge/analogix_dp.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Analogix DP (Display Port) Core interface driver.
|
||||
*
|
||||
* Copyright (C) 2015 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef _ANALOGIX_DP_H_
|
||||
#define _ANALOGIX_DP_H_
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
enum analogix_dp_devtype {
|
||||
EXYNOS_DP,
|
||||
RK3288_DP,
|
||||
};
|
||||
|
||||
struct analogix_dp_plat_data {
|
||||
enum analogix_dp_devtype dev_type;
|
||||
struct drm_panel *panel;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
|
||||
int (*power_on)(struct analogix_dp_plat_data *);
|
||||
int (*power_off)(struct analogix_dp_plat_data *);
|
||||
int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *,
|
||||
struct drm_connector *);
|
||||
int (*get_modes)(struct analogix_dp_plat_data *);
|
||||
};
|
||||
|
||||
int analogix_dp_resume(struct device *dev);
|
||||
int analogix_dp_suspend(struct device *dev);
|
||||
|
||||
int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
||||
struct analogix_dp_plat_data *plat_data);
|
||||
void analogix_dp_unbind(struct device *dev, struct device *master, void *data);
|
||||
|
||||
#endif /* _ANALOGIX_DP_H_ */
|
Loading…
Reference in New Issue
Block a user