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:
Dave Airlie 2020-03-19 11:00:48 +10:00
Родитель 71fa42fac5 6afe692996
Коммит d5152d3595
44 изменённых файлов: 917 добавлений и 229 удалений

Просмотреть файл

@ -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);
} }
/** /**