drm-misc-next for 5.7:
UAPI Changes: Cross-subsystem Changes: Core Changes: - dp-mst: Remove register_connector callback, add drm_dp_destroy_connector - Changes to scnprintf on multiple instances Driver Changes: - meson: Support for YUV420 - panel: Support Ortustech COM37H3M, idk-1110wr and idk-2121wr, multiple dotclock fixes -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCXnCKJwAKCRDj7w1vZxhR xT/GAP9nd1PSQ4eyIoo1LV33W7tm6b29eZbcNjk4uKMTpD3zwQD/S8X7URIJH14o sexsAp9WaUU2n0HQCRKUjgFPBilk8gE= =IdAG -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-03-17' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for 5.7: UAPI Changes: Cross-subsystem Changes: Core Changes: - dp-mst: Remove register_connector callback, add drm_dp_destroy_connector - Changes to scnprintf on multiple instances Driver Changes: - meson: Support for YUV420 - panel: Support Ortustech COM37H3M, idk-1110wr and idk-2121wr, multiple dotclock fixes Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200317082858.lubmvlmvoprn2tuh@gilmour.lan
This commit is contained in:
Коммит
d5152d3595
|
@ -0,0 +1,69 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/advantech,idk-1110wr.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Advantech IDK-1110WR 10.1" WSVGA LVDS Display Panel
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
|
||||||
|
- Thierry Reding <thierry.reding@gmail.com>
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: lvds.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: advantech,idk-1110wr
|
||||||
|
- {} # panel-lvds, but not listed here to avoid false select
|
||||||
|
|
||||||
|
data-mapping:
|
||||||
|
const: jeida-24
|
||||||
|
|
||||||
|
width-mm:
|
||||||
|
const: 223
|
||||||
|
|
||||||
|
height-mm:
|
||||||
|
const: 125
|
||||||
|
|
||||||
|
panel-timing: true
|
||||||
|
port: true
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |+
|
||||||
|
panel {
|
||||||
|
compatible = "advantech,idk-1110wr", "panel-lvds";
|
||||||
|
|
||||||
|
width-mm = <223>;
|
||||||
|
height-mm = <125>;
|
||||||
|
|
||||||
|
data-mapping = "jeida-24";
|
||||||
|
|
||||||
|
panel-timing {
|
||||||
|
/* 1024x600 @60Hz */
|
||||||
|
clock-frequency = <51200000>;
|
||||||
|
hactive = <1024>;
|
||||||
|
vactive = <600>;
|
||||||
|
hsync-len = <240>;
|
||||||
|
hfront-porch = <40>;
|
||||||
|
hback-porch = <40>;
|
||||||
|
vsync-len = <10>;
|
||||||
|
vfront-porch = <15>;
|
||||||
|
vback-porch = <10>;
|
||||||
|
};
|
||||||
|
|
||||||
|
port {
|
||||||
|
panel_in: endpoint {
|
||||||
|
remote-endpoint = <&lvds_encoder>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
|
@ -0,0 +1,122 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/display/panel/advantech,idk-2121wr.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Advantech IDK-2121WR 21.5" Full-HD dual-LVDS panel
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
|
||||||
|
- Thierry Reding <thierry.reding@gmail.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The IDK-2121WR from Advantech is a Full-HD dual-LVDS panel.
|
||||||
|
A dual-LVDS interface is a dual-link connection with even pixels traveling
|
||||||
|
on one link, and with odd pixels traveling on the other link.
|
||||||
|
|
||||||
|
The panel expects odd pixels on the first port, and even pixels on the
|
||||||
|
second port, therefore the ports must be marked accordingly (with either
|
||||||
|
dual-lvds-odd-pixels or dual-lvds-even-pixels).
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: advantech,idk-2121wr
|
||||||
|
- {} # panel-lvds, but not listed here to avoid false select
|
||||||
|
|
||||||
|
width-mm:
|
||||||
|
const: 476
|
||||||
|
|
||||||
|
height-mm:
|
||||||
|
const: 268
|
||||||
|
|
||||||
|
data-mapping:
|
||||||
|
const: vesa-24
|
||||||
|
|
||||||
|
panel-timing: true
|
||||||
|
|
||||||
|
ports:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
port@0:
|
||||||
|
type: object
|
||||||
|
description: The sink for odd pixels.
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
dual-lvds-odd-pixels: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- reg
|
||||||
|
- dual-lvds-odd-pixels
|
||||||
|
|
||||||
|
port@1:
|
||||||
|
type: object
|
||||||
|
description: The sink for even pixels.
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
dual-lvds-even-pixels: true
|
||||||
|
|
||||||
|
required:
|
||||||
|
- reg
|
||||||
|
- dual-lvds-even-pixels
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- width-mm
|
||||||
|
- height-mm
|
||||||
|
- data-mapping
|
||||||
|
- panel-timing
|
||||||
|
- ports
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |+
|
||||||
|
panel-lvds {
|
||||||
|
compatible = "advantech,idk-2121wr", "panel-lvds";
|
||||||
|
|
||||||
|
width-mm = <476>;
|
||||||
|
height-mm = <268>;
|
||||||
|
|
||||||
|
data-mapping = "vesa-24";
|
||||||
|
|
||||||
|
panel-timing {
|
||||||
|
clock-frequency = <148500000>;
|
||||||
|
hactive = <1920>;
|
||||||
|
vactive = <1080>;
|
||||||
|
hsync-len = <44>;
|
||||||
|
hfront-porch = <88>;
|
||||||
|
hback-porch = <148>;
|
||||||
|
vfront-porch = <4>;
|
||||||
|
vback-porch = <36>;
|
||||||
|
vsync-len = <5>;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
port@0 {
|
||||||
|
reg = <0>;
|
||||||
|
dual-lvds-odd-pixels;
|
||||||
|
panel_in0: endpoint {
|
||||||
|
remote-endpoint = <&lvds0_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
port@1 {
|
||||||
|
reg = <1>;
|
||||||
|
dual-lvds-even-pixels;
|
||||||
|
panel_in1: endpoint {
|
||||||
|
remote-endpoint = <&lvds1_out>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
|
@ -34,7 +34,7 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
dsi@ff450000 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
panel@0 {
|
panel@0 {
|
||||||
|
|
|
@ -34,7 +34,7 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
dsi@ff450000 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0xff450000 0x1000>;
|
reg = <0xff450000 0x1000>;
|
||||||
|
|
|
@ -40,10 +40,10 @@ examples:
|
||||||
- |
|
- |
|
||||||
#include <dt-bindings/gpio/gpio.h>
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
dsi@a0351000 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
panel {
|
panel@0 {
|
||||||
compatible = "hydis,hva40wv1", "novatek,nt35510";
|
compatible = "hydis,hva40wv1", "novatek,nt35510";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
vdd-supply = <&ab8500_ldo_aux4_reg>;
|
vdd-supply = <&ab8500_ldo_aux4_reg>;
|
||||||
|
|
|
@ -39,7 +39,7 @@ required:
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
dsi@0 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
panel@0 {
|
panel@0 {
|
||||||
|
|
|
@ -48,7 +48,7 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
panel@0 {
|
panel {
|
||||||
compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
|
compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
|
||||||
label = "osddisplay";
|
label = "osddisplay";
|
||||||
power-supply = <&vcc_supply>;
|
power-supply = <&vcc_supply>;
|
||||||
|
|
|
@ -50,7 +50,7 @@ required:
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
mdss_dsi@fd922800 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
panel@0 {
|
panel@0 {
|
||||||
|
|
|
@ -42,7 +42,7 @@ required:
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
dsi@0 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
panel@0 {
|
panel@0 {
|
||||||
|
|
|
@ -34,7 +34,7 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
dsi@ff450000 {
|
dsi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0xff450000 0x1000>;
|
reg = <0xff450000 0x1000>;
|
||||||
|
|
|
@ -458,15 +458,9 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
drm_connector_put(connector);
|
drm_connector_put(connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dm_dp_mst_register_connector(struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
drm_connector_register(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
|
static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
|
||||||
.add_connector = dm_dp_add_mst_connector,
|
.add_connector = dm_dp_add_mst_connector,
|
||||||
.destroy_connector = dm_dp_destroy_mst_connector,
|
.destroy_connector = dm_dp_destroy_mst_connector,
|
||||||
.register_connector = dm_dp_mst_register_connector
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
||||||
|
|
|
@ -1814,13 +1814,32 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||||
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
|
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
|
||||||
unsigned int vdisplay, hdisplay;
|
unsigned int vdisplay, hdisplay;
|
||||||
|
|
||||||
vmode->mtmdsclock = vmode->mpixelclock = mode->clock * 1000;
|
vmode->mpixelclock = mode->clock * 1000;
|
||||||
|
|
||||||
dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
|
dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
|
||||||
|
|
||||||
|
vmode->mtmdsclock = vmode->mpixelclock;
|
||||||
|
|
||||||
|
if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
|
||||||
|
switch (hdmi_bus_fmt_color_depth(
|
||||||
|
hdmi->hdmi_data.enc_out_bus_format)) {
|
||||||
|
case 16:
|
||||||
|
vmode->mtmdsclock = vmode->mpixelclock * 2;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
vmode->mtmdsclock = vmode->mpixelclock * 3 / 2;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
vmode->mtmdsclock = vmode->mpixelclock * 5 / 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format))
|
if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format))
|
||||||
vmode->mtmdsclock /= 2;
|
vmode->mtmdsclock /= 2;
|
||||||
|
|
||||||
|
dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock);
|
||||||
|
|
||||||
/* Set up HDMI_FC_INVIDCONF */
|
/* Set up HDMI_FC_INVIDCONF */
|
||||||
inv_val = (hdmi->hdmi_data.hdcp_enable ||
|
inv_val = (hdmi->hdmi_data.hdcp_enable ||
|
||||||
(dw_hdmi_support_scdc(hdmi) &&
|
(dw_hdmi_support_scdc(hdmi) &&
|
||||||
|
@ -2078,11 +2097,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||||
hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
|
hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
|
||||||
hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
|
hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
|
||||||
|
|
||||||
/* TOFIX: Get input format from plat data or fallback to RGB888 */
|
|
||||||
if (hdmi->plat_data->input_bus_format)
|
if (hdmi->plat_data->input_bus_format)
|
||||||
hdmi->hdmi_data.enc_in_bus_format =
|
hdmi->hdmi_data.enc_in_bus_format =
|
||||||
hdmi->plat_data->input_bus_format;
|
hdmi->plat_data->input_bus_format;
|
||||||
else
|
else if (hdmi->hdmi_data.enc_in_bus_format == MEDIA_BUS_FMT_FIXED)
|
||||||
hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
|
||||||
/* TOFIX: Get input encoding from plat data or fallback to none */
|
/* TOFIX: Get input encoding from plat data or fallback to none */
|
||||||
|
@ -2092,8 +2110,8 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
|
||||||
else
|
else
|
||||||
hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
|
hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
|
||||||
|
|
||||||
/* TOFIX: Default to RGB888 output format */
|
if (hdmi->hdmi_data.enc_out_bus_format == MEDIA_BUS_FMT_FIXED)
|
||||||
hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
|
||||||
hdmi->hdmi_data.pix_repet_factor = 0;
|
hdmi->hdmi_data.pix_repet_factor = 0;
|
||||||
hdmi->hdmi_data.hdcp_enable = 0;
|
hdmi->hdmi_data.hdcp_enable = 0;
|
||||||
|
@ -2371,6 +2389,277 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
|
||||||
.atomic_check = dw_hdmi_connector_atomic_check,
|
.atomic_check = dw_hdmi_connector_atomic_check,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible output formats :
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY16_0_5X48,
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY12_0_5X36,
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY10_0_5X30,
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY8_0_5X24,
|
||||||
|
* - MEDIA_BUS_FMT_YUV16_1X48,
|
||||||
|
* - MEDIA_BUS_FMT_RGB161616_1X48,
|
||||||
|
* - MEDIA_BUS_FMT_UYVY12_1X24,
|
||||||
|
* - MEDIA_BUS_FMT_YUV12_1X36,
|
||||||
|
* - MEDIA_BUS_FMT_RGB121212_1X36,
|
||||||
|
* - MEDIA_BUS_FMT_UYVY10_1X20,
|
||||||
|
* - MEDIA_BUS_FMT_YUV10_1X30,
|
||||||
|
* - MEDIA_BUS_FMT_RGB101010_1X30,
|
||||||
|
* - MEDIA_BUS_FMT_UYVY8_1X16,
|
||||||
|
* - MEDIA_BUS_FMT_YUV8_1X24,
|
||||||
|
* - MEDIA_BUS_FMT_RGB888_1X24,
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Can return a maximum of 11 possible output formats for a mode/connector */
|
||||||
|
#define MAX_OUTPUT_SEL_FORMATS 11
|
||||||
|
|
||||||
|
static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state,
|
||||||
|
unsigned int *num_output_fmts)
|
||||||
|
{
|
||||||
|
struct drm_connector *conn = conn_state->connector;
|
||||||
|
struct drm_display_info *info = &conn->display_info;
|
||||||
|
struct drm_display_mode *mode = &crtc_state->mode;
|
||||||
|
u8 max_bpc = conn_state->max_requested_bpc;
|
||||||
|
bool is_hdmi2_sink = info->hdmi.scdc.supported ||
|
||||||
|
(info->color_formats & DRM_COLOR_FORMAT_YCRCB420);
|
||||||
|
u32 *output_fmts;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
*num_output_fmts = 0;
|
||||||
|
|
||||||
|
output_fmts = kcalloc(MAX_OUTPUT_SEL_FORMATS, sizeof(*output_fmts),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!output_fmts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* If dw-hdmi is the only bridge, avoid negociating with ourselves */
|
||||||
|
if (list_is_singular(&bridge->encoder->bridge_chain)) {
|
||||||
|
*num_output_fmts = 1;
|
||||||
|
output_fmts[0] = MEDIA_BUS_FMT_FIXED;
|
||||||
|
|
||||||
|
return output_fmts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the current mode enforces 4:2:0, force the output but format
|
||||||
|
* to 4:2:0 and do not add the YUV422/444/RGB formats
|
||||||
|
*/
|
||||||
|
if (conn->ycbcr_420_allowed &&
|
||||||
|
(drm_mode_is_420_only(info, mode) ||
|
||||||
|
(is_hdmi2_sink && drm_mode_is_420_also(info, mode)))) {
|
||||||
|
|
||||||
|
/* Order bus formats from 16bit to 8bit if supported */
|
||||||
|
if (max_bpc >= 16 && info->bpc == 16 &&
|
||||||
|
(info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48))
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48;
|
||||||
|
|
||||||
|
if (max_bpc >= 12 && info->bpc >= 12 &&
|
||||||
|
(info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36))
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36;
|
||||||
|
|
||||||
|
if (max_bpc >= 10 && info->bpc >= 10 &&
|
||||||
|
(info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30))
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
|
||||||
|
|
||||||
|
/* Default 8bit fallback */
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
|
||||||
|
|
||||||
|
*num_output_fmts = i;
|
||||||
|
|
||||||
|
return output_fmts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Order bus formats from 16bit to 8bit and from YUV422 to RGB
|
||||||
|
* if supported. In any case the default RGB888 format is added
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (max_bpc >= 16 && info->bpc == 16) {
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
|
||||||
|
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_bpc >= 12 && info->bpc >= 12) {
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
|
||||||
|
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
|
||||||
|
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_bpc >= 10 && info->bpc >= 10) {
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
|
||||||
|
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
|
||||||
|
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
|
|
||||||
|
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||||
|
|
||||||
|
/* Default 8bit RGB fallback */
|
||||||
|
output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
|
||||||
|
*num_output_fmts = i;
|
||||||
|
|
||||||
|
return output_fmts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Possible input formats :
|
||||||
|
* - MEDIA_BUS_FMT_RGB888_1X24
|
||||||
|
* - MEDIA_BUS_FMT_YUV8_1X24
|
||||||
|
* - MEDIA_BUS_FMT_UYVY8_1X16
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY8_0_5X24
|
||||||
|
* - MEDIA_BUS_FMT_RGB101010_1X30
|
||||||
|
* - MEDIA_BUS_FMT_YUV10_1X30
|
||||||
|
* - MEDIA_BUS_FMT_UYVY10_1X20
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY10_0_5X30
|
||||||
|
* - MEDIA_BUS_FMT_RGB121212_1X36
|
||||||
|
* - MEDIA_BUS_FMT_YUV12_1X36
|
||||||
|
* - MEDIA_BUS_FMT_UYVY12_1X24
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY12_0_5X36
|
||||||
|
* - MEDIA_BUS_FMT_RGB161616_1X48
|
||||||
|
* - MEDIA_BUS_FMT_YUV16_1X48
|
||||||
|
* - MEDIA_BUS_FMT_UYYVYY16_0_5X48
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Can return a maximum of 3 possible input formats for an output format */
|
||||||
|
#define MAX_INPUT_SEL_FORMATS 3
|
||||||
|
|
||||||
|
static u32 *dw_hdmi_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state,
|
||||||
|
u32 output_fmt,
|
||||||
|
unsigned int *num_input_fmts)
|
||||||
|
{
|
||||||
|
u32 *input_fmts;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
*num_input_fmts = 0;
|
||||||
|
|
||||||
|
input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!input_fmts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (output_fmt) {
|
||||||
|
/* If MEDIA_BUS_FMT_FIXED is tested, return default bus format */
|
||||||
|
case MEDIA_BUS_FMT_FIXED:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
break;
|
||||||
|
/* 8bit */
|
||||||
|
case MEDIA_BUS_FMT_RGB888_1X24:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_YUV8_1X24:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 10bit */
|
||||||
|
case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_YUV10_1X30:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_UYVY10_1X20:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 12bit */
|
||||||
|
case MEDIA_BUS_FMT_RGB121212_1X36:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_YUV12_1X36:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_UYVY12_1X24:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* 16bit */
|
||||||
|
case MEDIA_BUS_FMT_RGB161616_1X48:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_YUV16_1X48:
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
|
||||||
|
input_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*YUV 4:2:0 */
|
||||||
|
case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
|
||||||
|
case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
|
||||||
|
case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
|
||||||
|
case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
|
||||||
|
input_fmts[i++] = output_fmt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*num_input_fmts = i;
|
||||||
|
|
||||||
|
if (*num_input_fmts == 0) {
|
||||||
|
kfree(input_fmts);
|
||||||
|
input_fmts = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input_fmts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
struct dw_hdmi *hdmi = bridge->driver_private;
|
||||||
|
|
||||||
|
hdmi->hdmi_data.enc_out_bus_format =
|
||||||
|
bridge_state->output_bus_cfg.format;
|
||||||
|
|
||||||
|
hdmi->hdmi_data.enc_in_bus_format =
|
||||||
|
bridge_state->input_bus_cfg.format;
|
||||||
|
|
||||||
|
dev_dbg(hdmi->dev, "input format 0x%04x, output format 0x%04x\n",
|
||||||
|
bridge_state->input_bus_cfg.format,
|
||||||
|
bridge_state->output_bus_cfg.format);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
|
static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
|
||||||
enum drm_bridge_attach_flags flags)
|
enum drm_bridge_attach_flags flags)
|
||||||
{
|
{
|
||||||
|
@ -2395,6 +2684,14 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
|
||||||
DRM_MODE_CONNECTOR_HDMIA,
|
DRM_MODE_CONNECTOR_HDMIA,
|
||||||
hdmi->ddc);
|
hdmi->ddc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* drm_connector_attach_max_bpc_property() requires the
|
||||||
|
* connector to have a state.
|
||||||
|
*/
|
||||||
|
drm_atomic_helper_connector_reset(connector);
|
||||||
|
|
||||||
|
drm_connector_attach_max_bpc_property(connector, 8, 16);
|
||||||
|
|
||||||
if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe)
|
if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe)
|
||||||
drm_object_attach_property(&connector->base,
|
drm_object_attach_property(&connector->base,
|
||||||
connector->dev->mode_config.hdr_output_metadata_property, 0);
|
connector->dev->mode_config.hdr_output_metadata_property, 0);
|
||||||
|
@ -2479,8 +2776,14 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
||||||
|
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||||
|
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||||
|
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||||
.attach = dw_hdmi_bridge_attach,
|
.attach = dw_hdmi_bridge_attach,
|
||||||
.detach = dw_hdmi_bridge_detach,
|
.detach = dw_hdmi_bridge_detach,
|
||||||
|
.atomic_check = dw_hdmi_bridge_atomic_check,
|
||||||
|
.atomic_get_output_bus_fmts = dw_hdmi_bridge_atomic_get_output_bus_fmts,
|
||||||
|
.atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts,
|
||||||
.enable = dw_hdmi_bridge_enable,
|
.enable = dw_hdmi_bridge_enable,
|
||||||
.disable = dw_hdmi_bridge_disable,
|
.disable = dw_hdmi_bridge_disable,
|
||||||
.mode_set = dw_hdmi_bridge_mode_set,
|
.mode_set = dw_hdmi_bridge_mode_set,
|
||||||
|
@ -2949,6 +3252,12 @@ __dw_hdmi_probe(struct platform_device *pdev,
|
||||||
hdmi->bridge.of_node = pdev->dev.of_node;
|
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (hdmi->version >= 0x200a)
|
||||||
|
hdmi->connector.ycbcr_420_allowed =
|
||||||
|
hdmi->plat_data->ycbcr_420_allowed;
|
||||||
|
else
|
||||||
|
hdmi->connector.ycbcr_420_allowed = false;
|
||||||
|
|
||||||
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
memset(&pdevinfo, 0, sizeof(pdevinfo));
|
||||||
pdevinfo.parent = dev;
|
pdevinfo.parent = dev;
|
||||||
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
pdevinfo.id = PLATFORM_DEVID_AUTO;
|
||||||
|
|
|
@ -134,7 +134,7 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
|
||||||
shift, add);
|
shift, add);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Core function to create a range of memory available for mapping by a
|
* Core function to create a range of memory available for mapping by a
|
||||||
* non-root process.
|
* non-root process.
|
||||||
*
|
*
|
||||||
|
@ -398,7 +398,7 @@ struct drm_local_map *drm_legacy_findmap(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_legacy_findmap);
|
EXPORT_SYMBOL(drm_legacy_findmap);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Ioctl to specify a range of memory that is available for mapping by a
|
* Ioctl to specify a range of memory that is available for mapping by a
|
||||||
* non-root process.
|
* non-root process.
|
||||||
*
|
*
|
||||||
|
@ -499,7 +499,7 @@ int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Remove a map private from list and deallocate resources if the mapping
|
* Remove a map private from list and deallocate resources if the mapping
|
||||||
* isn't in use.
|
* isn't in use.
|
||||||
*
|
*
|
||||||
|
@ -659,7 +659,7 @@ int drm_legacy_rmmap_ioctl(struct drm_device *dev, void *data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Cleanup after an error on one of the addbufs() functions.
|
* Cleanup after an error on one of the addbufs() functions.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -694,7 +694,7 @@ static void drm_cleanup_buf_error(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_AGP)
|
#if IS_ENABLED(CONFIG_AGP)
|
||||||
/**
|
/*
|
||||||
* Add AGP buffers for DMA transfers.
|
* Add AGP buffers for DMA transfers.
|
||||||
*
|
*
|
||||||
* \param dev struct drm_device to which the buffers are to be added.
|
* \param dev struct drm_device to which the buffers are to be added.
|
||||||
|
@ -1230,7 +1230,7 @@ static int drm_legacy_addbufs_sg(struct drm_device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Add buffers for DMA transfers (ioctl).
|
* Add buffers for DMA transfers (ioctl).
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -1271,7 +1271,7 @@ int drm_legacy_addbufs(struct drm_device *dev, void *data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Get information about the buffer mappings.
|
* Get information about the buffer mappings.
|
||||||
*
|
*
|
||||||
* This was originally mean for debugging purposes, or by a sophisticated
|
* This was originally mean for debugging purposes, or by a sophisticated
|
||||||
|
@ -1362,7 +1362,7 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data,
|
||||||
return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf);
|
return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Specifies a low and high water mark for buffer allocation
|
* Specifies a low and high water mark for buffer allocation
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -1411,7 +1411,7 @@ int drm_legacy_markbufs(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Unreserve the buffers in list, previously reserved using drmDMA.
|
* Unreserve the buffers in list, previously reserved using drmDMA.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -1463,7 +1463,7 @@ int drm_legacy_freebufs(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Maps all of the DMA buffers into client-virtual space (ioctl).
|
* Maps all of the DMA buffers into client-virtual space (ioctl).
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct drm_ctx_list {
|
||||||
/** \name Context bitmap support */
|
/** \name Context bitmap support */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Free a handle from the context bitmap.
|
* Free a handle from the context bitmap.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -68,7 +68,7 @@ void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Context bitmap allocation.
|
* Context bitmap allocation.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -88,7 +88,7 @@ static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Context bitmap initialization.
|
* Context bitmap initialization.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -104,7 +104,7 @@ void drm_legacy_ctxbitmap_init(struct drm_device * dev)
|
||||||
idr_init(&dev->ctx_idr);
|
idr_init(&dev->ctx_idr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Context bitmap cleanup.
|
* Context bitmap cleanup.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -163,7 +163,7 @@ void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
|
||||||
/** \name Per Context SAREA Support */
|
/** \name Per Context SAREA Support */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Get per-context SAREA.
|
* Get per-context SAREA.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -211,7 +211,7 @@ int drm_legacy_getsareactx(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Set per-context SAREA.
|
* Set per-context SAREA.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -263,7 +263,7 @@ int drm_legacy_setsareactx(struct drm_device *dev, void *data,
|
||||||
/** \name The actual DRM context handling routines */
|
/** \name The actual DRM context handling routines */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Switch context.
|
* Switch context.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -290,7 +290,7 @@ static int drm_context_switch(struct drm_device * dev, int old, int new)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Complete context switch.
|
* Complete context switch.
|
||||||
*
|
*
|
||||||
* \param dev DRM device.
|
* \param dev DRM device.
|
||||||
|
@ -318,7 +318,7 @@ static int drm_context_switch_complete(struct drm_device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Reserve contexts.
|
* Reserve contexts.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -351,7 +351,7 @@ int drm_legacy_resctx(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Add context.
|
* Add context.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -404,7 +404,7 @@ int drm_legacy_addctx(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Get context.
|
* Get context.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -428,7 +428,7 @@ int drm_legacy_getctx(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Switch context.
|
* Switch context.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -452,7 +452,7 @@ int drm_legacy_switchctx(struct drm_device *dev, void *data,
|
||||||
return drm_context_switch(dev, dev->last_context, ctx->handle);
|
return drm_context_switch(dev, dev->last_context, ctx->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* New context.
|
* New context.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -478,7 +478,7 @@ int drm_legacy_newctx(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Remove context.
|
* Remove context.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
|
|
@ -2063,7 +2063,7 @@ ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
|
||||||
* sideband messaging as drm_dp_dpcd_write() does for local
|
* sideband messaging as drm_dp_dpcd_write() does for local
|
||||||
* devices via actual AUX CH.
|
* devices via actual AUX CH.
|
||||||
*
|
*
|
||||||
* Return: 0 on success, negative error code on failure.
|
* Return: number of bytes written on success, negative error code on failure.
|
||||||
*/
|
*/
|
||||||
ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
|
ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux,
|
||||||
unsigned int offset, void *buffer, size_t size)
|
unsigned int offset, void *buffer, size_t size)
|
||||||
|
@ -2092,7 +2092,10 @@ static int drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
if (ret < 16 && ret > 0)
|
||||||
|
return -EPROTO;
|
||||||
|
|
||||||
|
return ret == 16 ? 0 : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
|
static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
|
||||||
|
@ -2175,7 +2178,7 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch *mstb,
|
||||||
drm_connector_set_tile_property(port->connector);
|
drm_connector_set_tile_property(port->connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
mgr->cbs->register_connector(port->connector);
|
drm_connector_register(port->connector);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -2907,8 +2910,14 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
drm_dp_dump_link_address(reply);
|
drm_dp_dump_link_address(reply);
|
||||||
|
|
||||||
ret = drm_dp_check_mstb_guid(mstb, reply->guid);
|
ret = drm_dp_check_mstb_guid(mstb, reply->guid);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
drm_dp_mst_rad_to_str(mstb->rad, mstb->lct, buf, sizeof(buf));
|
||||||
|
DRM_ERROR("GUID check on %s failed: %d\n",
|
||||||
|
buf, ret);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < reply->nports; i++) {
|
for (i = 0; i < reply->nports; i++) {
|
||||||
port_mask |= BIT(reply->ports[i].port_number);
|
port_mask |= BIT(reply->ports[i].port_number);
|
||||||
|
@ -3428,12 +3437,9 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
drm_dp_queue_down_tx(mgr, txmsg);
|
drm_dp_queue_down_tx(mgr, txmsg);
|
||||||
|
|
||||||
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
|
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
|
||||||
if (ret > 0) {
|
if (ret > 0 && txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
|
||||||
if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK)
|
ret = -EIO;
|
||||||
ret = -EIO;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
kfree(txmsg);
|
kfree(txmsg);
|
||||||
fail_put:
|
fail_put:
|
||||||
drm_dp_mst_topology_put_mstb(mstb);
|
drm_dp_mst_topology_put_mstb(mstb);
|
||||||
|
@ -4667,11 +4673,23 @@ static void drm_dp_tx_work(struct work_struct *work)
|
||||||
mutex_unlock(&mgr->qlock);
|
mutex_unlock(&mgr->qlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void drm_dp_destroy_connector(struct drm_dp_mst_port *port)
|
||||||
|
{
|
||||||
|
if (!port->connector)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (port->mgr->cbs->destroy_connector) {
|
||||||
|
port->mgr->cbs->destroy_connector(port->mgr, port->connector);
|
||||||
|
} else {
|
||||||
|
drm_connector_unregister(port->connector);
|
||||||
|
drm_connector_put(port->connector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
drm_dp_delayed_destroy_port(struct drm_dp_mst_port *port)
|
drm_dp_delayed_destroy_port(struct drm_dp_mst_port *port)
|
||||||
{
|
{
|
||||||
if (port->connector)
|
drm_dp_destroy_connector(port);
|
||||||
port->mgr->cbs->destroy_connector(port->mgr, port->connector);
|
|
||||||
|
|
||||||
drm_dp_port_set_pdt(port, DP_PEER_DEVICE_NONE, port->mcs);
|
drm_dp_port_set_pdt(port, DP_PEER_DEVICE_NONE, port->mcs);
|
||||||
drm_dp_mst_put_port_malloc(port);
|
drm_dp_mst_put_port_malloc(port);
|
||||||
|
|
|
@ -4434,6 +4434,7 @@ static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
||||||
|
|
||||||
if (cea_revision(cea) >= 3) {
|
if (cea_revision(cea) >= 3) {
|
||||||
int i, start, end;
|
int i, start, end;
|
||||||
|
int sad_count;
|
||||||
|
|
||||||
if (cea_db_offsets(cea, &start, &end)) {
|
if (cea_db_offsets(cea, &start, &end)) {
|
||||||
start = 0;
|
start = 0;
|
||||||
|
@ -4445,8 +4446,6 @@ static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
||||||
dbl = cea_db_payload_len(db);
|
dbl = cea_db_payload_len(db);
|
||||||
|
|
||||||
switch (cea_db_tag(db)) {
|
switch (cea_db_tag(db)) {
|
||||||
int sad_count;
|
|
||||||
|
|
||||||
case AUDIO_BLOCK:
|
case AUDIO_BLOCK:
|
||||||
/* Audio Data Block, contains SADs */
|
/* Audio Data Block, contains SADs */
|
||||||
sad_count = min(dbl / 3, 15 - total_sad_count);
|
sad_count = min(dbl / 3, 15 - total_sad_count);
|
||||||
|
@ -4938,6 +4937,47 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void get_monitor_range(struct detailed_timing *timing,
|
||||||
|
void *info_monitor_range)
|
||||||
|
{
|
||||||
|
struct drm_monitor_range_info *monitor_range = info_monitor_range;
|
||||||
|
const struct detailed_non_pixel *data = &timing->data.other_data;
|
||||||
|
const struct detailed_data_monitor_range *range = &data->data.range;
|
||||||
|
|
||||||
|
if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_MONITOR_RANGE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for flag range limits only. If flag == 1 then
|
||||||
|
* no additional timing information provided.
|
||||||
|
* Default GTF, GTF Secondary curve and CVT are not
|
||||||
|
* supported
|
||||||
|
*/
|
||||||
|
if (range->flags != DRM_EDID_RANGE_LIMITS_ONLY_FLAG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
monitor_range->min_vfreq = range->min_vfreq;
|
||||||
|
monitor_range->max_vfreq = range->max_vfreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void drm_get_monitor_range(struct drm_connector *connector,
|
||||||
|
const struct edid *edid)
|
||||||
|
{
|
||||||
|
struct drm_display_info *info = &connector->display_info;
|
||||||
|
|
||||||
|
if (!version_greater(edid, 1, 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
drm_for_each_detailed_block((u8 *)edid, get_monitor_range,
|
||||||
|
&info->monitor_range);
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
|
||||||
|
info->monitor_range.min_vfreq,
|
||||||
|
info->monitor_range.max_vfreq);
|
||||||
|
}
|
||||||
|
|
||||||
/* A connector has no EDID information, so we've got no EDID to compute quirks from. Reset
|
/* A connector has no EDID information, so we've got no EDID to compute quirks from. Reset
|
||||||
* all of the values which would have been set from EDID
|
* all of the values which would have been set from EDID
|
||||||
*/
|
*/
|
||||||
|
@ -4960,6 +5000,7 @@ drm_reset_display_info(struct drm_connector *connector)
|
||||||
memset(&info->hdmi, 0, sizeof(info->hdmi));
|
memset(&info->hdmi, 0, sizeof(info->hdmi));
|
||||||
|
|
||||||
info->non_desktop = 0;
|
info->non_desktop = 0;
|
||||||
|
memset(&info->monitor_range, 0, sizeof(info->monitor_range));
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid)
|
u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid)
|
||||||
|
@ -4975,6 +5016,8 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
|
||||||
|
|
||||||
info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
|
info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
|
||||||
|
|
||||||
|
drm_get_monitor_range(connector, edid);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
|
DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
|
||||||
|
|
||||||
if (edid->revision < 3)
|
if (edid->revision < 3)
|
||||||
|
|
|
@ -218,7 +218,7 @@ drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
|
||||||
struct drm_device *dev = obj->dev;
|
struct drm_device *dev = obj->dev;
|
||||||
bool final = false;
|
bool final = false;
|
||||||
|
|
||||||
if (WARN_ON(obj->handle_count == 0))
|
if (WARN_ON(READ_ONCE(obj->handle_count) == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
|
static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Take the heavyweight lock.
|
* Take the heavyweight lock.
|
||||||
*
|
*
|
||||||
* \param lock lock pointer.
|
* \param lock lock pointer.
|
||||||
|
@ -93,7 +93,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This takes a lock forcibly and hands it to context. Should ONLY be used
|
* This takes a lock forcibly and hands it to context. Should ONLY be used
|
||||||
* inside *_unlock to give lock to kernel before calling *_dma_schedule.
|
* inside *_unlock to give lock to kernel before calling *_dma_schedule.
|
||||||
*
|
*
|
||||||
|
@ -150,7 +150,7 @@ static int drm_legacy_lock_free(struct drm_lock_data *lock_data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Lock ioctl.
|
* Lock ioctl.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -243,7 +243,7 @@ int drm_legacy_lock(struct drm_device *dev, void *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Unlock ioctl.
|
* Unlock ioctl.
|
||||||
*
|
*
|
||||||
* \param inode device inode.
|
* \param inode device inode.
|
||||||
|
@ -275,7 +275,7 @@ int drm_legacy_unlock(struct drm_device *dev, void *data, struct drm_file *file_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This function returns immediately and takes the hw lock
|
* This function returns immediately and takes the hw lock
|
||||||
* with the kernel context if it is free, otherwise it gets the highest priority when and if
|
* with the kernel context if it is free, otherwise it gets the highest priority when and if
|
||||||
* it is eventually released.
|
* it is eventually released.
|
||||||
|
@ -287,7 +287,6 @@ int drm_legacy_unlock(struct drm_device *dev, void *data, struct drm_file *file_
|
||||||
* This should be sufficient to wait for GPU idle without
|
* This should be sufficient to wait for GPU idle without
|
||||||
* having to worry about starvation.
|
* having to worry about starvation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void drm_legacy_idlelock_take(struct drm_lock_data *lock_data)
|
void drm_legacy_idlelock_take(struct drm_lock_data *lock_data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -405,10 +405,10 @@ next_hole(struct drm_mm *mm,
|
||||||
*/
|
*/
|
||||||
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
|
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
|
||||||
{
|
{
|
||||||
u64 end = node->start + node->size;
|
|
||||||
struct drm_mm_node *hole;
|
struct drm_mm_node *hole;
|
||||||
u64 hole_start, hole_end;
|
u64 hole_start, hole_end;
|
||||||
u64 adj_start, adj_end;
|
u64 adj_start, adj_end;
|
||||||
|
u64 end;
|
||||||
|
|
||||||
end = node->start + node->size;
|
end = node->start + node->size;
|
||||||
if (unlikely(end <= node->start))
|
if (unlikely(end <= node->start))
|
||||||
|
|
|
@ -228,7 +228,7 @@ static ssize_t modes_show(struct device *device,
|
||||||
|
|
||||||
mutex_lock(&connector->dev->mode_config.mutex);
|
mutex_lock(&connector->dev->mode_config.mutex);
|
||||||
list_for_each_entry(mode, &connector->modes, head) {
|
list_for_each_entry(mode, &connector->modes, head) {
|
||||||
written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
|
written += scnprintf(buf + written, PAGE_SIZE - written, "%s\n",
|
||||||
mode->name);
|
mode->name);
|
||||||
}
|
}
|
||||||
mutex_unlock(&connector->dev->mode_config.mutex);
|
mutex_unlock(&connector->dev->mode_config.mutex);
|
||||||
|
|
|
@ -102,7 +102,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \c fault method for AGP virtual memory.
|
* \c fault method for AGP virtual memory.
|
||||||
*
|
*
|
||||||
* \param vma virtual memory area.
|
* \param vma virtual memory area.
|
||||||
|
@ -192,7 +192,7 @@ static vm_fault_t drm_vm_fault(struct vm_fault *vmf)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \c nopage method for shared virtual memory.
|
* \c nopage method for shared virtual memory.
|
||||||
*
|
*
|
||||||
* \param vma virtual memory area.
|
* \param vma virtual memory area.
|
||||||
|
@ -225,7 +225,7 @@ static vm_fault_t drm_vm_shm_fault(struct vm_fault *vmf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \c close method for shared virtual memory.
|
* \c close method for shared virtual memory.
|
||||||
*
|
*
|
||||||
* \param vma virtual memory area.
|
* \param vma virtual memory area.
|
||||||
|
@ -294,7 +294,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \c fault method for DMA virtual memory.
|
* \c fault method for DMA virtual memory.
|
||||||
*
|
*
|
||||||
* \param address access address.
|
* \param address access address.
|
||||||
|
@ -329,7 +329,7 @@ static vm_fault_t drm_vm_dma_fault(struct vm_fault *vmf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \c fault method for scatter-gather virtual memory.
|
* \c fault method for scatter-gather virtual memory.
|
||||||
*
|
*
|
||||||
* \param address access address.
|
* \param address access address.
|
||||||
|
@ -435,7 +435,7 @@ static void drm_vm_close_locked(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* \c close method for all virtual memory types.
|
* \c close method for all virtual memory types.
|
||||||
*
|
*
|
||||||
* \param vma virtual memory area.
|
* \param vma virtual memory area.
|
||||||
|
@ -453,7 +453,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* mmap DMA memory.
|
* mmap DMA memory.
|
||||||
*
|
*
|
||||||
* \param file_priv DRM file private.
|
* \param file_priv DRM file private.
|
||||||
|
@ -513,7 +513,7 @@ static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* mmap DMA memory.
|
* mmap DMA memory.
|
||||||
*
|
*
|
||||||
* \param file_priv DRM file private.
|
* \param file_priv DRM file private.
|
||||||
|
|
|
@ -748,24 +748,8 @@ err:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_dp_register_mst_connector(struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
drm_connector_register(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|
||||||
struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name);
|
|
||||||
drm_connector_unregister(connector);
|
|
||||||
|
|
||||||
drm_connector_put(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct drm_dp_mst_topology_cbs mst_cbs = {
|
static const struct drm_dp_mst_topology_cbs mst_cbs = {
|
||||||
.add_connector = intel_dp_add_mst_connector,
|
.add_connector = intel_dp_add_mst_connector,
|
||||||
.register_connector = intel_dp_register_mst_connector,
|
|
||||||
.destroy_connector = intel_dp_destroy_mst_connector,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct intel_dp_mst_encoder *
|
static struct intel_dp_mst_encoder *
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <drm/bridge/dw_hdmi.h>
|
#include <drm/bridge/dw_hdmi.h>
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
|
#include <drm/drm_bridge.h>
|
||||||
#include <drm/drm_device.h>
|
#include <drm/drm_device.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
|
@ -135,6 +136,7 @@ struct meson_dw_hdmi_data {
|
||||||
|
|
||||||
struct meson_dw_hdmi {
|
struct meson_dw_hdmi {
|
||||||
struct drm_encoder encoder;
|
struct drm_encoder encoder;
|
||||||
|
struct drm_bridge bridge;
|
||||||
struct dw_hdmi_plat_data dw_plat_data;
|
struct dw_hdmi_plat_data dw_plat_data;
|
||||||
struct meson_drm *priv;
|
struct meson_drm *priv;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
@ -148,9 +150,12 @@ struct meson_dw_hdmi {
|
||||||
struct regulator *hdmi_supply;
|
struct regulator *hdmi_supply;
|
||||||
u32 irq_stat;
|
u32 irq_stat;
|
||||||
struct dw_hdmi *hdmi;
|
struct dw_hdmi *hdmi;
|
||||||
|
unsigned long output_bus_fmt;
|
||||||
};
|
};
|
||||||
#define encoder_to_meson_dw_hdmi(x) \
|
#define encoder_to_meson_dw_hdmi(x) \
|
||||||
container_of(x, struct meson_dw_hdmi, encoder)
|
container_of(x, struct meson_dw_hdmi, encoder)
|
||||||
|
#define bridge_to_meson_dw_hdmi(x) \
|
||||||
|
container_of(x, struct meson_dw_hdmi, bridge)
|
||||||
|
|
||||||
static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
|
static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
|
||||||
const char *compat)
|
const char *compat)
|
||||||
|
@ -297,6 +302,10 @@ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
|
||||||
struct meson_drm *priv = dw_hdmi->priv;
|
struct meson_drm *priv = dw_hdmi->priv;
|
||||||
unsigned int pixel_clock = mode->clock;
|
unsigned int pixel_clock = mode->clock;
|
||||||
|
|
||||||
|
/* For 420, pixel clock is half unlike venc clock */
|
||||||
|
if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
|
||||||
|
pixel_clock /= 2;
|
||||||
|
|
||||||
if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
|
if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
|
||||||
dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
|
dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
|
||||||
if (pixel_clock >= 371250) {
|
if (pixel_clock >= 371250) {
|
||||||
|
@ -368,29 +377,40 @@ static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
|
static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
|
||||||
struct drm_display_mode *mode)
|
const struct drm_display_mode *mode)
|
||||||
{
|
{
|
||||||
struct meson_drm *priv = dw_hdmi->priv;
|
struct meson_drm *priv = dw_hdmi->priv;
|
||||||
int vic = drm_match_cea_mode(mode);
|
int vic = drm_match_cea_mode(mode);
|
||||||
|
unsigned int phy_freq;
|
||||||
unsigned int vclk_freq;
|
unsigned int vclk_freq;
|
||||||
unsigned int venc_freq;
|
unsigned int venc_freq;
|
||||||
unsigned int hdmi_freq;
|
unsigned int hdmi_freq;
|
||||||
|
|
||||||
vclk_freq = mode->clock;
|
vclk_freq = mode->clock;
|
||||||
|
|
||||||
|
/* For 420, pixel clock is half unlike venc clock */
|
||||||
|
if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
|
||||||
|
vclk_freq /= 2;
|
||||||
|
|
||||||
|
/* TMDS clock is pixel_clock * 10 */
|
||||||
|
phy_freq = vclk_freq * 10;
|
||||||
|
|
||||||
if (!vic) {
|
if (!vic) {
|
||||||
meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, vclk_freq,
|
meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
|
||||||
vclk_freq, vclk_freq, false);
|
vclk_freq, vclk_freq, vclk_freq, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 480i/576i needs global pixel doubling */
|
||||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||||
vclk_freq *= 2;
|
vclk_freq *= 2;
|
||||||
|
|
||||||
venc_freq = vclk_freq;
|
venc_freq = vclk_freq;
|
||||||
hdmi_freq = vclk_freq;
|
hdmi_freq = vclk_freq;
|
||||||
|
|
||||||
if (meson_venc_hdmi_venc_repeat(vic))
|
/* VENC double pixels for 1080i, 720p and YUV420 modes */
|
||||||
|
if (meson_venc_hdmi_venc_repeat(vic) ||
|
||||||
|
dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
|
||||||
venc_freq *= 2;
|
venc_freq *= 2;
|
||||||
|
|
||||||
vclk_freq = max(venc_freq, hdmi_freq);
|
vclk_freq = max(venc_freq, hdmi_freq);
|
||||||
|
@ -398,11 +418,11 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
|
||||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||||
venc_freq /= 2;
|
venc_freq /= 2;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
|
DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
|
||||||
vclk_freq, venc_freq, hdmi_freq,
|
phy_freq, vclk_freq, venc_freq, hdmi_freq,
|
||||||
priv->venc.hdmi_use_enci);
|
priv->venc.hdmi_use_enci);
|
||||||
|
|
||||||
meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
|
meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
|
||||||
venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
|
venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,8 +457,9 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
|
||||||
/* Enable normal output to PHY */
|
/* Enable normal output to PHY */
|
||||||
dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
|
dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
|
||||||
|
|
||||||
/* TMDS pattern setup (TOFIX Handle the YUV420 case) */
|
/* TMDS pattern setup */
|
||||||
if (mode->clock > 340000) {
|
if (mode->clock > 340000 &&
|
||||||
|
dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
|
||||||
dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
|
dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
|
||||||
0);
|
0);
|
||||||
dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
|
dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
|
||||||
|
@ -613,6 +634,8 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
|
||||||
const struct drm_display_mode *mode)
|
const struct drm_display_mode *mode)
|
||||||
{
|
{
|
||||||
struct meson_drm *priv = connector->dev->dev_private;
|
struct meson_drm *priv = connector->dev->dev_private;
|
||||||
|
bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
|
||||||
|
unsigned int phy_freq;
|
||||||
unsigned int vclk_freq;
|
unsigned int vclk_freq;
|
||||||
unsigned int venc_freq;
|
unsigned int venc_freq;
|
||||||
unsigned int hdmi_freq;
|
unsigned int hdmi_freq;
|
||||||
|
@ -621,9 +644,11 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
|
DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
|
||||||
|
|
||||||
/* If sink max TMDS clock, we reject the mode */
|
/* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
|
||||||
if (connector->display_info.max_tmds_clock &&
|
if (connector->display_info.max_tmds_clock &&
|
||||||
mode->clock > connector->display_info.max_tmds_clock)
|
mode->clock > connector->display_info.max_tmds_clock &&
|
||||||
|
!drm_mode_is_420_only(&connector->display_info, mode) &&
|
||||||
|
!drm_mode_is_420_also(&connector->display_info, mode))
|
||||||
return MODE_BAD;
|
return MODE_BAD;
|
||||||
|
|
||||||
/* Check against non-VIC supported modes */
|
/* Check against non-VIC supported modes */
|
||||||
|
@ -639,6 +664,15 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
|
||||||
|
|
||||||
vclk_freq = mode->clock;
|
vclk_freq = mode->clock;
|
||||||
|
|
||||||
|
/* For 420, pixel clock is half unlike venc clock */
|
||||||
|
if (drm_mode_is_420_only(&connector->display_info, mode) ||
|
||||||
|
(!is_hdmi2_sink &&
|
||||||
|
drm_mode_is_420_also(&connector->display_info, mode)))
|
||||||
|
vclk_freq /= 2;
|
||||||
|
|
||||||
|
/* TMDS clock is pixel_clock * 10 */
|
||||||
|
phy_freq = vclk_freq * 10;
|
||||||
|
|
||||||
/* 480i/576i needs global pixel doubling */
|
/* 480i/576i needs global pixel doubling */
|
||||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||||
vclk_freq *= 2;
|
vclk_freq *= 2;
|
||||||
|
@ -646,8 +680,11 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
|
||||||
venc_freq = vclk_freq;
|
venc_freq = vclk_freq;
|
||||||
hdmi_freq = vclk_freq;
|
hdmi_freq = vclk_freq;
|
||||||
|
|
||||||
/* VENC double pixels for 1080i and 720p modes */
|
/* VENC double pixels for 1080i, 720p and YUV420 modes */
|
||||||
if (meson_venc_hdmi_venc_repeat(vic))
|
if (meson_venc_hdmi_venc_repeat(vic) ||
|
||||||
|
drm_mode_is_420_only(&connector->display_info, mode) ||
|
||||||
|
(!is_hdmi2_sink &&
|
||||||
|
drm_mode_is_420_also(&connector->display_info, mode)))
|
||||||
venc_freq *= 2;
|
venc_freq *= 2;
|
||||||
|
|
||||||
vclk_freq = max(venc_freq, hdmi_freq);
|
vclk_freq = max(venc_freq, hdmi_freq);
|
||||||
|
@ -655,14 +692,19 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
|
||||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||||
venc_freq /= 2;
|
venc_freq /= 2;
|
||||||
|
|
||||||
dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
|
dev_dbg(connector->dev->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
|
||||||
vclk_freq, venc_freq, hdmi_freq);
|
__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
|
||||||
|
|
||||||
return meson_vclk_vic_supported_freq(vclk_freq);
|
return meson_vclk_vic_supported_freq(phy_freq, vclk_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encoder */
|
/* Encoder */
|
||||||
|
|
||||||
|
static const u32 meson_dw_hdmi_out_bus_fmts[] = {
|
||||||
|
MEDIA_BUS_FMT_YUV8_1X24,
|
||||||
|
MEDIA_BUS_FMT_UYYVYY8_0_5X24,
|
||||||
|
};
|
||||||
|
|
||||||
static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
|
static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
|
||||||
{
|
{
|
||||||
drm_encoder_cleanup(encoder);
|
drm_encoder_cleanup(encoder);
|
||||||
|
@ -672,16 +714,54 @@ static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
|
||||||
.destroy = meson_venc_hdmi_encoder_destroy,
|
.destroy = meson_venc_hdmi_encoder_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
|
static u32 *
|
||||||
|
meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state,
|
||||||
|
u32 output_fmt,
|
||||||
|
unsigned int *num_input_fmts)
|
||||||
|
{
|
||||||
|
u32 *input_fmts = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
*num_input_fmts = 0;
|
||||||
|
|
||||||
|
for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
|
||||||
|
if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
|
||||||
|
*num_input_fmts = 1;
|
||||||
|
input_fmts = kcalloc(*num_input_fmts,
|
||||||
|
sizeof(*input_fmts),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!input_fmts)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
input_fmts[0] = output_fmt;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return input_fmts;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
struct drm_crtc_state *crtc_state,
|
struct drm_crtc_state *crtc_state,
|
||||||
struct drm_connector_state *conn_state)
|
struct drm_connector_state *conn_state)
|
||||||
{
|
{
|
||||||
|
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
|
||||||
|
|
||||||
|
dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
|
||||||
|
|
||||||
|
DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
|
static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
|
||||||
{
|
{
|
||||||
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
|
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
|
||||||
struct meson_drm *priv = dw_hdmi->priv;
|
struct meson_drm *priv = dw_hdmi->priv;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("\n");
|
DRM_DEBUG_DRIVER("\n");
|
||||||
|
@ -693,9 +773,9 @@ static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
|
||||||
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
|
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
|
static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
|
||||||
{
|
{
|
||||||
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
|
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
|
||||||
struct meson_drm *priv = dw_hdmi->priv;
|
struct meson_drm *priv = dw_hdmi->priv;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
|
DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
|
||||||
|
@ -706,32 +786,47 @@ static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
|
||||||
writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
|
writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
|
static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
|
||||||
struct drm_display_mode *mode,
|
const struct drm_display_mode *mode,
|
||||||
struct drm_display_mode *adjusted_mode)
|
const struct drm_display_mode *adjusted_mode)
|
||||||
{
|
{
|
||||||
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
|
struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
|
||||||
struct meson_drm *priv = dw_hdmi->priv;
|
struct meson_drm *priv = dw_hdmi->priv;
|
||||||
int vic = drm_match_cea_mode(mode);
|
int vic = drm_match_cea_mode(mode);
|
||||||
|
unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
|
||||||
|
bool yuv420_mode = false;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
|
DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
|
||||||
|
|
||||||
|
if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
|
||||||
|
ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
|
||||||
|
yuv420_mode = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* VENC + VENC-DVI Mode setup */
|
/* VENC + VENC-DVI Mode setup */
|
||||||
meson_venc_hdmi_mode_set(priv, vic, mode);
|
meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
|
||||||
|
|
||||||
/* VCLK Set clock */
|
/* VCLK Set clock */
|
||||||
dw_hdmi_set_vclk(dw_hdmi, mode);
|
dw_hdmi_set_vclk(dw_hdmi, mode);
|
||||||
|
|
||||||
/* Setup YUV444 to HDMI-TX, no 10bit diphering */
|
if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
|
||||||
writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
|
/* Setup YUV420 to HDMI-TX, no 10bit diphering */
|
||||||
|
writel_relaxed(2 | (2 << 2),
|
||||||
|
priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
|
||||||
|
else
|
||||||
|
/* Setup YUV444 to HDMI-TX, no 10bit diphering */
|
||||||
|
writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_encoder_helper_funcs
|
static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
|
||||||
meson_venc_hdmi_encoder_helper_funcs = {
|
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||||
.atomic_check = meson_venc_hdmi_encoder_atomic_check,
|
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||||
.disable = meson_venc_hdmi_encoder_disable,
|
.atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
|
||||||
.enable = meson_venc_hdmi_encoder_enable,
|
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||||
.mode_set = meson_venc_hdmi_encoder_mode_set,
|
.atomic_check = meson_venc_hdmi_encoder_atomic_check,
|
||||||
|
.enable = meson_venc_hdmi_encoder_enable,
|
||||||
|
.disable = meson_venc_hdmi_encoder_disable,
|
||||||
|
.mode_set = meson_venc_hdmi_encoder_mode_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* DW HDMI Regmap */
|
/* DW HDMI Regmap */
|
||||||
|
@ -852,6 +947,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
struct drm_device *drm = data;
|
struct drm_device *drm = data;
|
||||||
struct meson_drm *priv = drm->dev_private;
|
struct meson_drm *priv = drm->dev_private;
|
||||||
struct dw_hdmi_plat_data *dw_plat_data;
|
struct dw_hdmi_plat_data *dw_plat_data;
|
||||||
|
struct drm_bridge *next_bridge;
|
||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int irq;
|
int irq;
|
||||||
|
@ -953,8 +1049,6 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
|
||||||
/* Encoder */
|
/* Encoder */
|
||||||
|
|
||||||
drm_encoder_helper_add(encoder, &meson_venc_hdmi_encoder_helper_funcs);
|
|
||||||
|
|
||||||
ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
|
ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
|
||||||
DRM_MODE_ENCODER_TMDS, "meson_hdmi");
|
DRM_MODE_ENCODER_TMDS, "meson_hdmi");
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -962,6 +1056,9 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
|
||||||
|
drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
|
||||||
|
|
||||||
encoder->possible_crtcs = BIT(0);
|
encoder->possible_crtcs = BIT(0);
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("encoder initialized\n");
|
DRM_DEBUG_DRIVER("encoder initialized\n");
|
||||||
|
@ -974,8 +1071,8 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
|
dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
|
||||||
dw_plat_data->phy_name = "meson_dw_hdmi_phy";
|
dw_plat_data->phy_name = "meson_dw_hdmi_phy";
|
||||||
dw_plat_data->phy_data = meson_dw_hdmi;
|
dw_plat_data->phy_data = meson_dw_hdmi;
|
||||||
dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
|
|
||||||
dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
|
dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
|
||||||
|
dw_plat_data->ycbcr_420_allowed = true;
|
||||||
|
|
||||||
if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
|
if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
|
||||||
dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
|
dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
|
||||||
|
@ -984,11 +1081,16 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
|
||||||
platform_set_drvdata(pdev, meson_dw_hdmi);
|
platform_set_drvdata(pdev, meson_dw_hdmi);
|
||||||
|
|
||||||
meson_dw_hdmi->hdmi = dw_hdmi_bind(pdev, encoder,
|
meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
|
||||||
&meson_dw_hdmi->dw_plat_data);
|
&meson_dw_hdmi->dw_plat_data);
|
||||||
if (IS_ERR(meson_dw_hdmi->hdmi))
|
if (IS_ERR(meson_dw_hdmi->hdmi))
|
||||||
return PTR_ERR(meson_dw_hdmi->hdmi);
|
return PTR_ERR(meson_dw_hdmi->hdmi);
|
||||||
|
|
||||||
|
next_bridge = of_drm_find_bridge(pdev->dev.of_node);
|
||||||
|
if (next_bridge)
|
||||||
|
drm_bridge_attach(encoder, next_bridge,
|
||||||
|
&meson_dw_hdmi->bridge, 0);
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("HDMI controller initialized\n");
|
DRM_DEBUG_DRIVER("HDMI controller initialized\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -354,12 +354,17 @@ enum {
|
||||||
/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
|
/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
|
||||||
MESON_VCLK_HDMI_297000,
|
MESON_VCLK_HDMI_297000,
|
||||||
/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
|
/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
|
||||||
MESON_VCLK_HDMI_594000
|
MESON_VCLK_HDMI_594000,
|
||||||
|
/* 2970 /1 /1 /1 /5 /1 => /1 /2 */
|
||||||
|
MESON_VCLK_HDMI_594000_YUV420,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct meson_vclk_params {
|
struct meson_vclk_params {
|
||||||
|
unsigned int pll_freq;
|
||||||
|
unsigned int phy_freq;
|
||||||
|
unsigned int vclk_freq;
|
||||||
|
unsigned int venc_freq;
|
||||||
unsigned int pixel_freq;
|
unsigned int pixel_freq;
|
||||||
unsigned int pll_base_freq;
|
|
||||||
unsigned int pll_od1;
|
unsigned int pll_od1;
|
||||||
unsigned int pll_od2;
|
unsigned int pll_od2;
|
||||||
unsigned int pll_od3;
|
unsigned int pll_od3;
|
||||||
|
@ -367,8 +372,11 @@ struct meson_vclk_params {
|
||||||
unsigned int vclk_div;
|
unsigned int vclk_div;
|
||||||
} params[] = {
|
} params[] = {
|
||||||
[MESON_VCLK_HDMI_ENCI_54000] = {
|
[MESON_VCLK_HDMI_ENCI_54000] = {
|
||||||
|
.pll_freq = 4320000,
|
||||||
|
.phy_freq = 270000,
|
||||||
|
.vclk_freq = 54000,
|
||||||
|
.venc_freq = 54000,
|
||||||
.pixel_freq = 54000,
|
.pixel_freq = 54000,
|
||||||
.pll_base_freq = 4320000,
|
|
||||||
.pll_od1 = 4,
|
.pll_od1 = 4,
|
||||||
.pll_od2 = 4,
|
.pll_od2 = 4,
|
||||||
.pll_od3 = 1,
|
.pll_od3 = 1,
|
||||||
|
@ -376,8 +384,11 @@ struct meson_vclk_params {
|
||||||
.vclk_div = 1,
|
.vclk_div = 1,
|
||||||
},
|
},
|
||||||
[MESON_VCLK_HDMI_DDR_54000] = {
|
[MESON_VCLK_HDMI_DDR_54000] = {
|
||||||
.pixel_freq = 54000,
|
.pll_freq = 4320000,
|
||||||
.pll_base_freq = 4320000,
|
.phy_freq = 270000,
|
||||||
|
.vclk_freq = 54000,
|
||||||
|
.venc_freq = 54000,
|
||||||
|
.pixel_freq = 27000,
|
||||||
.pll_od1 = 4,
|
.pll_od1 = 4,
|
||||||
.pll_od2 = 4,
|
.pll_od2 = 4,
|
||||||
.pll_od3 = 1,
|
.pll_od3 = 1,
|
||||||
|
@ -385,8 +396,11 @@ struct meson_vclk_params {
|
||||||
.vclk_div = 1,
|
.vclk_div = 1,
|
||||||
},
|
},
|
||||||
[MESON_VCLK_HDMI_DDR_148500] = {
|
[MESON_VCLK_HDMI_DDR_148500] = {
|
||||||
.pixel_freq = 148500,
|
.pll_freq = 2970000,
|
||||||
.pll_base_freq = 2970000,
|
.phy_freq = 742500,
|
||||||
|
.vclk_freq = 148500,
|
||||||
|
.venc_freq = 148500,
|
||||||
|
.pixel_freq = 74250,
|
||||||
.pll_od1 = 4,
|
.pll_od1 = 4,
|
||||||
.pll_od2 = 1,
|
.pll_od2 = 1,
|
||||||
.pll_od3 = 1,
|
.pll_od3 = 1,
|
||||||
|
@ -394,8 +408,11 @@ struct meson_vclk_params {
|
||||||
.vclk_div = 1,
|
.vclk_div = 1,
|
||||||
},
|
},
|
||||||
[MESON_VCLK_HDMI_74250] = {
|
[MESON_VCLK_HDMI_74250] = {
|
||||||
|
.pll_freq = 2970000,
|
||||||
|
.phy_freq = 742500,
|
||||||
|
.vclk_freq = 74250,
|
||||||
|
.venc_freq = 74250,
|
||||||
.pixel_freq = 74250,
|
.pixel_freq = 74250,
|
||||||
.pll_base_freq = 2970000,
|
|
||||||
.pll_od1 = 2,
|
.pll_od1 = 2,
|
||||||
.pll_od2 = 2,
|
.pll_od2 = 2,
|
||||||
.pll_od3 = 2,
|
.pll_od3 = 2,
|
||||||
|
@ -403,8 +420,11 @@ struct meson_vclk_params {
|
||||||
.vclk_div = 1,
|
.vclk_div = 1,
|
||||||
},
|
},
|
||||||
[MESON_VCLK_HDMI_148500] = {
|
[MESON_VCLK_HDMI_148500] = {
|
||||||
|
.pll_freq = 2970000,
|
||||||
|
.phy_freq = 1485000,
|
||||||
|
.vclk_freq = 148500,
|
||||||
|
.venc_freq = 148500,
|
||||||
.pixel_freq = 148500,
|
.pixel_freq = 148500,
|
||||||
.pll_base_freq = 2970000,
|
|
||||||
.pll_od1 = 1,
|
.pll_od1 = 1,
|
||||||
.pll_od2 = 2,
|
.pll_od2 = 2,
|
||||||
.pll_od3 = 2,
|
.pll_od3 = 2,
|
||||||
|
@ -412,8 +432,11 @@ struct meson_vclk_params {
|
||||||
.vclk_div = 1,
|
.vclk_div = 1,
|
||||||
},
|
},
|
||||||
[MESON_VCLK_HDMI_297000] = {
|
[MESON_VCLK_HDMI_297000] = {
|
||||||
|
.pll_freq = 5940000,
|
||||||
|
.phy_freq = 2970000,
|
||||||
|
.venc_freq = 297000,
|
||||||
|
.vclk_freq = 297000,
|
||||||
.pixel_freq = 297000,
|
.pixel_freq = 297000,
|
||||||
.pll_base_freq = 5940000,
|
|
||||||
.pll_od1 = 2,
|
.pll_od1 = 2,
|
||||||
.pll_od2 = 1,
|
.pll_od2 = 1,
|
||||||
.pll_od3 = 1,
|
.pll_od3 = 1,
|
||||||
|
@ -421,14 +444,29 @@ struct meson_vclk_params {
|
||||||
.vclk_div = 2,
|
.vclk_div = 2,
|
||||||
},
|
},
|
||||||
[MESON_VCLK_HDMI_594000] = {
|
[MESON_VCLK_HDMI_594000] = {
|
||||||
|
.pll_freq = 5940000,
|
||||||
|
.phy_freq = 5940000,
|
||||||
|
.venc_freq = 594000,
|
||||||
|
.vclk_freq = 594000,
|
||||||
.pixel_freq = 594000,
|
.pixel_freq = 594000,
|
||||||
.pll_base_freq = 5940000,
|
|
||||||
.pll_od1 = 1,
|
.pll_od1 = 1,
|
||||||
.pll_od2 = 1,
|
.pll_od2 = 1,
|
||||||
.pll_od3 = 2,
|
.pll_od3 = 2,
|
||||||
.vid_pll_div = VID_PLL_DIV_5,
|
.vid_pll_div = VID_PLL_DIV_5,
|
||||||
.vclk_div = 1,
|
.vclk_div = 1,
|
||||||
},
|
},
|
||||||
|
[MESON_VCLK_HDMI_594000_YUV420] = {
|
||||||
|
.pll_freq = 5940000,
|
||||||
|
.phy_freq = 2970000,
|
||||||
|
.venc_freq = 594000,
|
||||||
|
.vclk_freq = 594000,
|
||||||
|
.pixel_freq = 297000,
|
||||||
|
.pll_od1 = 2,
|
||||||
|
.pll_od2 = 1,
|
||||||
|
.pll_od3 = 1,
|
||||||
|
.vid_pll_div = VID_PLL_DIV_5,
|
||||||
|
.vclk_div = 1,
|
||||||
|
},
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -701,6 +739,7 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
|
||||||
unsigned int od, m, frac, od1, od2, od3;
|
unsigned int od, m, frac, od1, od2, od3;
|
||||||
|
|
||||||
if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
|
if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
|
||||||
|
/* OD2 goes to the PHY, and needs to be *10, so keep OD3=1 */
|
||||||
od3 = 1;
|
od3 = 1;
|
||||||
if (od < 4) {
|
if (od < 4) {
|
||||||
od1 = 2;
|
od1 = 2;
|
||||||
|
@ -723,21 +762,28 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum drm_mode_status
|
enum drm_mode_status
|
||||||
meson_vclk_vic_supported_freq(unsigned int freq)
|
meson_vclk_vic_supported_freq(unsigned int phy_freq,
|
||||||
|
unsigned int vclk_freq)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("freq = %d\n", freq);
|
DRM_DEBUG_DRIVER("phy_freq = %d vclk_freq = %d\n",
|
||||||
|
phy_freq, vclk_freq);
|
||||||
|
|
||||||
for (i = 0 ; params[i].pixel_freq ; ++i) {
|
for (i = 0 ; params[i].pixel_freq ; ++i) {
|
||||||
DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
|
DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
|
||||||
i, params[i].pixel_freq,
|
i, params[i].pixel_freq,
|
||||||
FREQ_1000_1001(params[i].pixel_freq));
|
FREQ_1000_1001(params[i].pixel_freq));
|
||||||
|
DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n",
|
||||||
|
i, params[i].phy_freq,
|
||||||
|
FREQ_1000_1001(params[i].phy_freq/10)*10);
|
||||||
/* Match strict frequency */
|
/* Match strict frequency */
|
||||||
if (freq == params[i].pixel_freq)
|
if (phy_freq == params[i].phy_freq &&
|
||||||
|
vclk_freq == params[i].vclk_freq)
|
||||||
return MODE_OK;
|
return MODE_OK;
|
||||||
/* Match 1000/1001 variant */
|
/* Match 1000/1001 variant */
|
||||||
if (freq == FREQ_1000_1001(params[i].pixel_freq))
|
if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) &&
|
||||||
|
vclk_freq == FREQ_1000_1001(params[i].vclk_freq))
|
||||||
return MODE_OK;
|
return MODE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,8 +1011,9 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
|
||||||
}
|
}
|
||||||
|
|
||||||
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||||
unsigned int vclk_freq, unsigned int venc_freq,
|
unsigned int phy_freq, unsigned int vclk_freq,
|
||||||
unsigned int dac_freq, bool hdmi_use_enci)
|
unsigned int venc_freq, unsigned int dac_freq,
|
||||||
|
bool hdmi_use_enci)
|
||||||
{
|
{
|
||||||
bool vic_alternate_clock = false;
|
bool vic_alternate_clock = false;
|
||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
|
@ -986,7 +1033,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||||
* - venc_div = 1
|
* - venc_div = 1
|
||||||
* - encp encoder
|
* - encp encoder
|
||||||
*/
|
*/
|
||||||
meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
|
meson_vclk_set(priv, phy_freq, 0, 0, 0,
|
||||||
VID_PLL_DIV_5, 2, 1, 1, false, false);
|
VID_PLL_DIV_5, 2, 1, 1, false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1008,9 +1055,11 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
|
for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
|
||||||
if (vclk_freq == params[freq].pixel_freq ||
|
if ((phy_freq == params[freq].phy_freq ||
|
||||||
vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
|
phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) &&
|
||||||
if (vclk_freq != params[freq].pixel_freq)
|
(vclk_freq == params[freq].vclk_freq ||
|
||||||
|
vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) {
|
||||||
|
if (vclk_freq != params[freq].vclk_freq)
|
||||||
vic_alternate_clock = true;
|
vic_alternate_clock = true;
|
||||||
else
|
else
|
||||||
vic_alternate_clock = false;
|
vic_alternate_clock = false;
|
||||||
|
@ -1039,7 +1088,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
meson_vclk_set(priv, params[freq].pll_base_freq,
|
meson_vclk_set(priv, params[freq].pll_freq,
|
||||||
params[freq].pll_od1, params[freq].pll_od2,
|
params[freq].pll_od1, params[freq].pll_od2,
|
||||||
params[freq].pll_od3, params[freq].vid_pll_div,
|
params[freq].pll_od3, params[freq].vid_pll_div,
|
||||||
params[freq].vclk_div, hdmi_tx_div, venc_div,
|
params[freq].vclk_div, hdmi_tx_div, venc_div,
|
||||||
|
|
|
@ -25,10 +25,11 @@ enum {
|
||||||
enum drm_mode_status
|
enum drm_mode_status
|
||||||
meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
|
meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
|
||||||
enum drm_mode_status
|
enum drm_mode_status
|
||||||
meson_vclk_vic_supported_freq(unsigned int freq);
|
meson_vclk_vic_supported_freq(unsigned int phy_freq, unsigned int vclk_freq);
|
||||||
|
|
||||||
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
|
||||||
unsigned int vclk_freq, unsigned int venc_freq,
|
unsigned int phy_freq, unsigned int vclk_freq,
|
||||||
unsigned int dac_freq, bool hdmi_use_enci);
|
unsigned int venc_freq, unsigned int dac_freq,
|
||||||
|
bool hdmi_use_enci);
|
||||||
|
|
||||||
#endif /* __MESON_VCLK_H */
|
#endif /* __MESON_VCLK_H */
|
||||||
|
|
|
@ -946,7 +946,9 @@ bool meson_venc_hdmi_venc_repeat(int vic)
|
||||||
EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
|
EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
|
||||||
|
|
||||||
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
|
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
|
||||||
struct drm_display_mode *mode)
|
unsigned int ycrcb_map,
|
||||||
|
bool yuv420_mode,
|
||||||
|
const struct drm_display_mode *mode)
|
||||||
{
|
{
|
||||||
union meson_hdmi_venc_mode *vmode = NULL;
|
union meson_hdmi_venc_mode *vmode = NULL;
|
||||||
union meson_hdmi_venc_mode vmode_dmt;
|
union meson_hdmi_venc_mode vmode_dmt;
|
||||||
|
@ -1528,14 +1530,14 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
|
||||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||||
reg |= VPU_HDMI_INV_VSYNC;
|
reg |= VPU_HDMI_INV_VSYNC;
|
||||||
|
|
||||||
/* Output data format: CbYCr */
|
/* Output data format */
|
||||||
reg |= VPU_HDMI_OUTPUT_CBYCR;
|
reg |= ycrcb_map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write rate to the async FIFO between VENC and HDMI.
|
* Write rate to the async FIFO between VENC and HDMI.
|
||||||
* One write every 2 wr_clk.
|
* One write every 2 wr_clk.
|
||||||
*/
|
*/
|
||||||
if (venc_repeat)
|
if (venc_repeat || yuv420_mode)
|
||||||
reg |= VPU_HDMI_WR_RATE(2);
|
reg |= VPU_HDMI_WR_RATE(2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -60,7 +60,9 @@ extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;
|
||||||
void meson_venci_cvbs_mode_set(struct meson_drm *priv,
|
void meson_venci_cvbs_mode_set(struct meson_drm *priv,
|
||||||
struct meson_cvbs_enci_mode *mode);
|
struct meson_cvbs_enci_mode *mode);
|
||||||
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
|
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
|
||||||
struct drm_display_mode *mode);
|
unsigned int ycrcb_map,
|
||||||
|
bool yuv420_mode,
|
||||||
|
const struct drm_display_mode *mode);
|
||||||
unsigned int meson_venci_get_field(struct meson_drm *priv);
|
unsigned int meson_venci_get_field(struct meson_drm *priv);
|
||||||
|
|
||||||
void meson_venc_enable_vsync(struct meson_drm *priv);
|
void meson_venc_enable_vsync(struct meson_drm *priv);
|
||||||
|
|
|
@ -213,8 +213,10 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
|
||||||
meson_venci_cvbs_mode_set(priv, meson_mode->enci);
|
meson_venci_cvbs_mode_set(priv, meson_mode->enci);
|
||||||
|
|
||||||
/* Setup 27MHz vclk2 for ENCI and VDAC */
|
/* Setup 27MHz vclk2 for ENCI and VDAC */
|
||||||
meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS,
|
meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
|
||||||
MESON_VCLK_CVBS, MESON_VCLK_CVBS, true);
|
MESON_VCLK_CVBS, MESON_VCLK_CVBS,
|
||||||
|
MESON_VCLK_CVBS, MESON_VCLK_CVBS,
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1256,23 +1256,6 @@ nv50_mstm_prepare(struct nv50_mstm *mstm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|
||||||
struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
struct nv50_mstc *mstc = nv50_mstc(connector);
|
|
||||||
|
|
||||||
drm_connector_unregister(&mstc->connector);
|
|
||||||
|
|
||||||
drm_connector_put(&mstc->connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nv50_mstm_register_connector(struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
drm_connector_register(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct drm_connector *
|
static struct drm_connector *
|
||||||
nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
|
nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_dp_mst_port *port, const char *path)
|
struct drm_dp_mst_port *port, const char *path)
|
||||||
|
@ -1291,8 +1274,6 @@ nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
static const struct drm_dp_mst_topology_cbs
|
static const struct drm_dp_mst_topology_cbs
|
||||||
nv50_mstm = {
|
nv50_mstm = {
|
||||||
.add_connector = nv50_mstm_add_connector,
|
.add_connector = nv50_mstm_add_connector,
|
||||||
.register_connector = nv50_mstm_register_connector,
|
|
||||||
.destroy_connector = nv50_mstm_destroy_connector,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -540,7 +540,7 @@ static int ili9322_enable(struct drm_panel *panel)
|
||||||
|
|
||||||
/* Serial RGB modes */
|
/* Serial RGB modes */
|
||||||
static const struct drm_display_mode srgb_320x240_mode = {
|
static const struct drm_display_mode srgb_320x240_mode = {
|
||||||
.clock = 2453500,
|
.clock = 24535,
|
||||||
.hdisplay = 320,
|
.hdisplay = 320,
|
||||||
.hsync_start = 320 + 359,
|
.hsync_start = 320 + 359,
|
||||||
.hsync_end = 320 + 359 + 1,
|
.hsync_end = 320 + 359 + 1,
|
||||||
|
@ -554,7 +554,7 @@ static const struct drm_display_mode srgb_320x240_mode = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_display_mode srgb_360x240_mode = {
|
static const struct drm_display_mode srgb_360x240_mode = {
|
||||||
.clock = 2700000,
|
.clock = 27000,
|
||||||
.hdisplay = 360,
|
.hdisplay = 360,
|
||||||
.hsync_start = 360 + 35,
|
.hsync_start = 360 + 35,
|
||||||
.hsync_end = 360 + 35 + 1,
|
.hsync_end = 360 + 35 + 1,
|
||||||
|
@ -569,7 +569,7 @@ static const struct drm_display_mode srgb_360x240_mode = {
|
||||||
|
|
||||||
/* This is the only mode listed for parallel RGB in the datasheet */
|
/* This is the only mode listed for parallel RGB in the datasheet */
|
||||||
static const struct drm_display_mode prgb_320x240_mode = {
|
static const struct drm_display_mode prgb_320x240_mode = {
|
||||||
.clock = 6400000,
|
.clock = 64000,
|
||||||
.hdisplay = 320,
|
.hdisplay = 320,
|
||||||
.hsync_start = 320 + 38,
|
.hsync_start = 320 + 38,
|
||||||
.hsync_end = 320 + 38 + 1,
|
.hsync_end = 320 + 38 + 1,
|
||||||
|
@ -584,7 +584,7 @@ static const struct drm_display_mode prgb_320x240_mode = {
|
||||||
|
|
||||||
/* YUV modes */
|
/* YUV modes */
|
||||||
static const struct drm_display_mode yuv_640x320_mode = {
|
static const struct drm_display_mode yuv_640x320_mode = {
|
||||||
.clock = 2454000,
|
.clock = 24540,
|
||||||
.hdisplay = 640,
|
.hdisplay = 640,
|
||||||
.hsync_start = 640 + 252,
|
.hsync_start = 640 + 252,
|
||||||
.hsync_end = 640 + 252 + 1,
|
.hsync_end = 640 + 252 + 1,
|
||||||
|
@ -598,7 +598,7 @@ static const struct drm_display_mode yuv_640x320_mode = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_display_mode yuv_720x360_mode = {
|
static const struct drm_display_mode yuv_720x360_mode = {
|
||||||
.clock = 2700000,
|
.clock = 27000,
|
||||||
.hdisplay = 720,
|
.hdisplay = 720,
|
||||||
.hsync_start = 720 + 252,
|
.hsync_start = 720 + 252,
|
||||||
.hsync_end = 720 + 252 + 1,
|
.hsync_end = 720 + 252 + 1,
|
||||||
|
@ -613,7 +613,7 @@ static const struct drm_display_mode yuv_720x360_mode = {
|
||||||
|
|
||||||
/* BT.656 VGA mode, 640x480 */
|
/* BT.656 VGA mode, 640x480 */
|
||||||
static const struct drm_display_mode itu_r_bt_656_640_mode = {
|
static const struct drm_display_mode itu_r_bt_656_640_mode = {
|
||||||
.clock = 2454000,
|
.clock = 24540,
|
||||||
.hdisplay = 640,
|
.hdisplay = 640,
|
||||||
.hsync_start = 640 + 3,
|
.hsync_start = 640 + 3,
|
||||||
.hsync_end = 640 + 3 + 1,
|
.hsync_end = 640 + 3 + 1,
|
||||||
|
@ -628,7 +628,7 @@ static const struct drm_display_mode itu_r_bt_656_640_mode = {
|
||||||
|
|
||||||
/* BT.656 D1 mode 720x480 */
|
/* BT.656 D1 mode 720x480 */
|
||||||
static const struct drm_display_mode itu_r_bt_656_720_mode = {
|
static const struct drm_display_mode itu_r_bt_656_720_mode = {
|
||||||
.clock = 2700000,
|
.clock = 27000,
|
||||||
.hdisplay = 720,
|
.hdisplay = 720,
|
||||||
.hsync_start = 720 + 3,
|
.hsync_start = 720 + 3,
|
||||||
.hsync_end = 720 + 3 + 1,
|
.hsync_end = 720 + 3 + 1,
|
||||||
|
|
|
@ -197,7 +197,7 @@ static int lg4573_enable(struct drm_panel *panel)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_display_mode default_mode = {
|
static const struct drm_display_mode default_mode = {
|
||||||
.clock = 27000,
|
.clock = 28341,
|
||||||
.hdisplay = 480,
|
.hdisplay = 480,
|
||||||
.hsync_start = 480 + 10,
|
.hsync_start = 480 + 10,
|
||||||
.hsync_end = 480 + 10 + 59,
|
.hsync_end = 480 + 10 + 59,
|
||||||
|
|
|
@ -1019,7 +1019,7 @@ static const struct nt35510_config nt35510_hydis_hva40wv1 = {
|
||||||
*/
|
*/
|
||||||
.mode = {
|
.mode = {
|
||||||
/* The internal pixel clock of the NT35510 is 20 MHz */
|
/* The internal pixel clock of the NT35510 is 20 MHz */
|
||||||
.clock = 20000000,
|
.clock = 20000,
|
||||||
.hdisplay = 480,
|
.hdisplay = 480,
|
||||||
.hsync_start = 480 + 2, /* HFP = 2 */
|
.hsync_start = 480 + 2, /* HFP = 2 */
|
||||||
.hsync_end = 480 + 2 + 0, /* HSync = 0 */
|
.hsync_end = 480 + 2 + 0, /* HSync = 0 */
|
||||||
|
|
|
@ -2277,7 +2277,7 @@ static const struct drm_display_mode mitsubishi_aa070mc01_mode = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_display_mode logicpd_type_28_mode = {
|
static const struct drm_display_mode logicpd_type_28_mode = {
|
||||||
.clock = 9000,
|
.clock = 9107,
|
||||||
.hdisplay = 480,
|
.hdisplay = 480,
|
||||||
.hsync_start = 480 + 3,
|
.hsync_start = 480 + 3,
|
||||||
.hsync_end = 480 + 3 + 42,
|
.hsync_end = 480 + 3 + 42,
|
||||||
|
@ -2617,15 +2617,15 @@ static const struct panel_desc ontat_yx700wv03 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_display_mode ortustech_com37h3m_mode = {
|
static const struct drm_display_mode ortustech_com37h3m_mode = {
|
||||||
.clock = 22153,
|
.clock = 22230,
|
||||||
.hdisplay = 480,
|
.hdisplay = 480,
|
||||||
.hsync_start = 480 + 8,
|
.hsync_start = 480 + 40,
|
||||||
.hsync_end = 480 + 8 + 10,
|
.hsync_end = 480 + 40 + 10,
|
||||||
.htotal = 480 + 8 + 10 + 10,
|
.htotal = 480 + 40 + 10 + 40,
|
||||||
.vdisplay = 640,
|
.vdisplay = 640,
|
||||||
.vsync_start = 640 + 4,
|
.vsync_start = 640 + 4,
|
||||||
.vsync_end = 640 + 4 + 3,
|
.vsync_end = 640 + 4 + 2,
|
||||||
.vtotal = 640 + 4 + 3 + 4,
|
.vtotal = 640 + 4 + 2 + 4,
|
||||||
.vrefresh = 60,
|
.vrefresh = 60,
|
||||||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||||
};
|
};
|
||||||
|
@ -2666,6 +2666,7 @@ static const struct panel_desc ortustech_com43h4m85ulc = {
|
||||||
},
|
},
|
||||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
|
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
|
||||||
|
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_display_mode osddisplays_osd070t1718_19ts_mode = {
|
static const struct drm_display_mode osddisplays_osd070t1718_19ts_mode = {
|
||||||
|
|
|
@ -48,7 +48,7 @@ struct acx424akp {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct drm_display_mode sony_acx424akp_vid_mode = {
|
static const struct drm_display_mode sony_acx424akp_vid_mode = {
|
||||||
.clock = 330000,
|
.clock = 27234,
|
||||||
.hdisplay = 480,
|
.hdisplay = 480,
|
||||||
.hsync_start = 480 + 15,
|
.hsync_start = 480 + 15,
|
||||||
.hsync_end = 480 + 15 + 0,
|
.hsync_end = 480 + 15 + 0,
|
||||||
|
@ -68,7 +68,7 @@ static const struct drm_display_mode sony_acx424akp_vid_mode = {
|
||||||
* command mode using the maximum HS frequency.
|
* command mode using the maximum HS frequency.
|
||||||
*/
|
*/
|
||||||
static const struct drm_display_mode sony_acx424akp_cmd_mode = {
|
static const struct drm_display_mode sony_acx424akp_cmd_mode = {
|
||||||
.clock = 420160,
|
.clock = 35478,
|
||||||
.hdisplay = 480,
|
.hdisplay = 480,
|
||||||
.hsync_start = 480 + 154,
|
.hsync_start = 480 + 154,
|
||||||
.hsync_end = 480 + 154 + 16,
|
.hsync_end = 480 + 154 + 16,
|
||||||
|
|
|
@ -301,25 +301,8 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
|
||||||
return connector;
|
return connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void radeon_dp_register_mst_connector(struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
drm_connector_register(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
|
||||||
struct drm_connector *connector)
|
|
||||||
{
|
|
||||||
drm_connector_unregister(connector);
|
|
||||||
drm_connector_cleanup(connector);
|
|
||||||
|
|
||||||
kfree(connector);
|
|
||||||
DRM_DEBUG_KMS("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct drm_dp_mst_topology_cbs mst_cbs = {
|
static const struct drm_dp_mst_topology_cbs mst_cbs = {
|
||||||
.add_connector = radeon_dp_add_mst_connector,
|
.add_connector = radeon_dp_add_mst_connector,
|
||||||
.register_connector = radeon_dp_register_mst_connector,
|
|
||||||
.destroy_connector = radeon_dp_destroy_mst_connector,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
|
|
|
@ -98,7 +98,8 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
|
||||||
if (of_property_read_u32(endpoint, "reg", &endpoint_id))
|
if (of_property_read_u32(endpoint, "reg", &endpoint_id))
|
||||||
endpoint_id = 0;
|
endpoint_id = 0;
|
||||||
|
|
||||||
if (rockchip_drm_endpoint_is_subdriver(endpoint) > 0)
|
/* if subdriver (> 0) or error case (< 0), ignore entry */
|
||||||
|
if (rockchip_drm_endpoint_is_subdriver(endpoint) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
child_count++;
|
child_count++;
|
||||||
|
|
|
@ -45,7 +45,7 @@ static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
|
||||||
void *data = par;
|
void *data = par;
|
||||||
u32 speed_hz;
|
u32 speed_hz;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
u16 *buf;
|
__be16 *buf;
|
||||||
|
|
||||||
buf = kmalloc(32 * sizeof(u16), GFP_KERNEL);
|
buf = kmalloc(32 * sizeof(u16), GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
|
|
|
@ -151,8 +151,6 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo,
|
||||||
struct ttm_bo_device *bdev = bo->bdev;
|
struct ttm_bo_device *bdev = bo->bdev;
|
||||||
struct ttm_mem_type_manager *man;
|
struct ttm_mem_type_manager *man;
|
||||||
|
|
||||||
dma_resv_assert_held(bo->base.resv);
|
|
||||||
|
|
||||||
if (!list_empty(&bo->lru))
|
if (!list_empty(&bo->lru))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -604,7 +602,8 @@ static void ttm_bo_release(struct kref *kref)
|
||||||
*/
|
*/
|
||||||
if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {
|
if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {
|
||||||
bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT;
|
bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT;
|
||||||
ttm_bo_move_to_lru_tail(bo, NULL);
|
ttm_bo_del_from_lru(bo);
|
||||||
|
ttm_bo_add_mem_to_lru(bo, &bo->mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
kref_init(&bo->kref);
|
kref_init(&bo->kref);
|
||||||
|
|
|
@ -604,7 +604,7 @@ static struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags,
|
||||||
p = pool->name;
|
p = pool->name;
|
||||||
for (i = 0; i < ARRAY_SIZE(t); i++) {
|
for (i = 0; i < ARRAY_SIZE(t); i++) {
|
||||||
if (type & t[i]) {
|
if (type & t[i]) {
|
||||||
p += snprintf(p, sizeof(pool->name) - (p - pool->name),
|
p += scnprintf(p, sizeof(pool->name) - (p - pool->name),
|
||||||
"%s", n[i]);
|
"%s", n[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ struct dw_hdmi_plat_data {
|
||||||
unsigned long input_bus_format;
|
unsigned long input_bus_format;
|
||||||
unsigned long input_bus_encoding;
|
unsigned long input_bus_encoding;
|
||||||
bool use_drm_infoframe;
|
bool use_drm_infoframe;
|
||||||
|
bool ycbcr_420_allowed;
|
||||||
|
|
||||||
/* Vendor PHY support */
|
/* Vendor PHY support */
|
||||||
const struct dw_hdmi_phy_ops *phy_ops;
|
const struct dw_hdmi_phy_ops *phy_ops;
|
||||||
|
|
|
@ -254,6 +254,23 @@ enum drm_panel_orientation {
|
||||||
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
|
DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct drm_monitor_range_info - Panel's Monitor range in EDID for
|
||||||
|
* &drm_display_info
|
||||||
|
*
|
||||||
|
* This struct is used to store a frequency range supported by panel
|
||||||
|
* as parsed from EDID's detailed monitor range descriptor block.
|
||||||
|
*
|
||||||
|
* @min_vfreq: This is the min supported refresh rate in Hz from
|
||||||
|
* EDID's detailed monitor range.
|
||||||
|
* @max_vfreq: This is the max supported refresh rate in Hz from
|
||||||
|
* EDID's detailed monitor range
|
||||||
|
*/
|
||||||
|
struct drm_monitor_range_info {
|
||||||
|
u8 min_vfreq;
|
||||||
|
u8 max_vfreq;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a consolidated colorimetry list supported by HDMI and
|
* This is a consolidated colorimetry list supported by HDMI and
|
||||||
* DP protocol standard. The respective connectors will register
|
* DP protocol standard. The respective connectors will register
|
||||||
|
@ -473,6 +490,11 @@ struct drm_display_info {
|
||||||
* @non_desktop: Non desktop display (HMD).
|
* @non_desktop: Non desktop display (HMD).
|
||||||
*/
|
*/
|
||||||
bool non_desktop;
|
bool non_desktop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @monitor_range: Frequency range supported by monitor range descriptor
|
||||||
|
*/
|
||||||
|
struct drm_monitor_range_info monitor_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
int drm_display_info_set_bus_formats(struct drm_display_info *info,
|
int drm_display_info_set_bus_formats(struct drm_display_info *info,
|
||||||
|
|
|
@ -479,7 +479,6 @@ struct drm_dp_mst_topology_mgr;
|
||||||
struct drm_dp_mst_topology_cbs {
|
struct drm_dp_mst_topology_cbs {
|
||||||
/* create a connector for a port */
|
/* create a connector for a port */
|
||||||
struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path);
|
struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path);
|
||||||
void (*register_connector)(struct drm_connector *connector);
|
|
||||||
void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
|
void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_connector *connector);
|
struct drm_connector *connector);
|
||||||
};
|
};
|
||||||
|
@ -590,6 +589,11 @@ struct drm_dp_mst_topology_mgr {
|
||||||
*/
|
*/
|
||||||
bool payload_id_table_cleared : 1;
|
bool payload_id_table_cleared : 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @is_waiting_for_dwn_reply: whether we're waiting for a down reply.
|
||||||
|
*/
|
||||||
|
bool is_waiting_for_dwn_reply : 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @mst_primary: Pointer to the primary/first branch device.
|
* @mst_primary: Pointer to the primary/first branch device.
|
||||||
*/
|
*/
|
||||||
|
@ -619,11 +623,6 @@ struct drm_dp_mst_topology_mgr {
|
||||||
*/
|
*/
|
||||||
struct mutex qlock;
|
struct mutex qlock;
|
||||||
|
|
||||||
/**
|
|
||||||
* @is_waiting_for_dwn_reply: indicate whether is waiting for down reply
|
|
||||||
*/
|
|
||||||
bool is_waiting_for_dwn_reply;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @tx_msg_downq: List of pending down replies.
|
* @tx_msg_downq: List of pending down replies.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -91,6 +91,11 @@ struct detailed_data_string {
|
||||||
u8 str[13];
|
u8 str[13];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00
|
||||||
|
#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01
|
||||||
|
#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02
|
||||||
|
#define DRM_EDID_CVT_SUPPORT_FLAG 0x04
|
||||||
|
|
||||||
struct detailed_data_monitor_range {
|
struct detailed_data_monitor_range {
|
||||||
u8 min_vfreq;
|
u8 min_vfreq;
|
||||||
u8 max_vfreq;
|
u8 max_vfreq;
|
||||||
|
|
|
@ -272,7 +272,7 @@ static inline bool drm_mm_node_allocated(const struct drm_mm_node *node)
|
||||||
*/
|
*/
|
||||||
static inline bool drm_mm_initialized(const struct drm_mm *mm)
|
static inline bool drm_mm_initialized(const struct drm_mm *mm)
|
||||||
{
|
{
|
||||||
return mm->hole_stack.next;
|
return READ_ONCE(mm->hole_stack.next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче