drm-misc-next for $kernel-version:

UAPI Changes:
 
 Cross-subsystem Changes:
 
 Core Changes:
   - dp/mst: Fix daisy-chaining at resume
   - dsc: Add helper to dump the DSC configuration
   - tests: Add tests for the new monochrome TV mode variant
 
 Driver Changes:
   - ast: Refactor the mode setting code
   - panfrost: Fix devfreq job reporting
   - stm: Add LDVS support, DSI PHY updates
   - panels:
     - New panel: AUO G104STN01, K&d kd101ne3-40ti,
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCZoaglQAKCRDj7w1vZxhR
 xVV5AP9xLIWjyN/yoZMYn7FXm2CbsmYgxGPTHyHfPbwO52Kt/AEA4EnkDJ9WVNof
 qf2PpieG/g66x/DCFdaltKXN6sXQlQQ=
 =49mR
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-2024-07-04' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for $kernel-version:

UAPI Changes:

Cross-subsystem Changes:

Core Changes:
  - dp/mst: Fix daisy-chaining at resume
  - dsc: Add helper to dump the DSC configuration
  - tests: Add tests for the new monochrome TV mode variant

Driver Changes:
  - ast: Refactor the mode setting code
  - panfrost: Fix devfreq job reporting
  - stm: Add LDVS support, DSI PHY updates
  - panels:
    - New panel: AUO G104STN01, K&d kd101ne3-40ti,

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240704-curvy-outstanding-lizard-bcea78@houat
This commit is contained in:
Daniel Vetter 2024-07-05 12:37:21 +02:00
commit d076e2bd09
26 changed files with 2605 additions and 560 deletions

View File

@ -17,6 +17,7 @@ properties:
items:
- enum:
- chongzhou,cz101b4001
- kingdisplay,kd101ne3-40ti
- radxa,display-10hd-ad001
- radxa,display-8hd-ad002
- const: jadard,jd9365da-h3

View File

@ -51,6 +51,8 @@ properties:
- auo,g101evn010
# AU Optronics Corporation 10.4" (800x600) color TFT LCD panel
- auo,g104sn02
# AU Optronics Corporation 10.4" (800x600) color TFT LCD panel
- auo,g104stn01
# AU Optronics Corporation 12.1" (1280x800) TFT LCD panel
- auo,g121ean01
# AU Optronics Corporation 15.6" (1366x768) TFT LCD panel

View File

@ -0,0 +1,119 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/st,stm32mp25-lvds.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STM32 LVDS Display Interface Transmitter
maintainers:
- Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
- Yannick Fertre <yannick.fertre@foss.st.com>
description: |
The STMicroelectronics STM32 LVDS Display Interface Transmitter handles the
LVDS protocol: it maps the pixels received from the upstream Pixel-DMA (LTDC)
onto the LVDS PHY.
It is composed of three sub blocks:
- LVDS host: handles the LVDS protocol (FPD / OpenLDI) and maps its input
pixels onto the data lanes of the PHY
- LVDS PHY: parallelize the data and drives the LVDS data lanes
- LVDS wrapper: handles top-level settings
The LVDS controller driver supports the following high-level features:
- FDP-Link-I and OpenLDI (v0.95) protocols
- Single-Link or Dual-Link operation
- Single-Display or Double-Display (with the same content duplicated on both)
- Flexible Bit-Mapping, including JEIDA and VESA
- RGB888 or RGB666 output
- Synchronous design, with one input pixel per clock cycle
properties:
compatible:
const: st,stm32mp25-lvds
"#clock-cells":
const: 0
description:
Provides the internal LVDS PHY clock to the framework.
reg:
maxItems: 1
clocks:
items:
- description: APB peripheral clock
- description: Reference clock for the internal PLL
clock-names:
items:
- const: pclk
- const: ref
resets:
maxItems: 1
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/properties/port
description:
LVDS input port node, connected to the LTDC RGB output port.
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
LVDS output port node, connected to a panel or bridge input port.
required:
- port@0
- port@1
required:
- compatible
- "#clock-cells"
- reg
- clocks
- clock-names
- resets
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/st,stm32mp25-rcc.h>
#include <dt-bindings/reset/st,stm32mp25-rcc.h>
lvds: lvds@48060000 {
compatible = "st,stm32mp25-lvds";
reg = <0x48060000 0x2000>;
#clock-cells = <0>;
clocks = <&rcc CK_BUS_LVDS>, <&rcc CK_KER_LVDSPHY>;
clock-names = "pclk", "ref";
resets = <&rcc LVDS_R>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
lvds_in: endpoint {
remote-endpoint = <&ltdc_ep1_out>;
};
};
port@1 {
reg = <1>;
lvds_out0: endpoint {
remote-endpoint = <&lvds_panel_in>;
};
};
};
};
...

View File

@ -7484,6 +7484,7 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
F: Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml
F: drivers/gpu/drm/stm
DRM DRIVERS FOR TI KEYSTONE

View File

@ -303,7 +303,7 @@ static void ast_set_std_reg(struct ast_device *ast,
/* Set SEQ; except Screen Disable field */
ast_set_index_reg(ast, AST_IO_VGASRI, 0x00, 0x03);
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, stdtable->seq[0]);
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0x20, stdtable->seq[0]);
for (i = 1; i < 4; i++) {
jreg = stdtable->seq[i];
ast_set_index_reg(ast, AST_IO_VGASRI, (i + 1), jreg);
@ -649,12 +649,12 @@ static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_framebuffer *old_fb = old_plane_state->fb;
struct ast_plane *ast_plane = to_ast_plane(plane);
struct drm_crtc *crtc = plane_state->crtc;
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct drm_rect damage;
struct drm_atomic_helper_damage_iter iter;
if (!old_fb || (fb->format != old_fb->format)) {
struct drm_crtc *crtc = plane_state->crtc;
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (!old_fb || (fb->format != old_fb->format) || crtc_state->mode_changed) {
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
@ -690,15 +690,15 @@ static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane,
* Therefore only reprogram the address after enabling the plane.
*/
ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x00);
}
static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct ast_device *ast = to_ast_device(plane->dev);
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x20);
/*
* Keep this empty function to avoid calling
* atomic_update when disabling the plane.
*/
}
static int ast_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane,
@ -1019,62 +1019,6 @@ static int ast_cursor_plane_init(struct ast_device *ast)
* CRTC
*/
static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct ast_device *ast = to_ast_device(crtc->dev);
u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
struct ast_crtc_state *ast_state;
const struct drm_format_info *format;
struct ast_vbios_mode_info *vbios_mode_info;
/* TODO: Maybe control display signal generation with
* Sync Enable (bit CR17.7).
*/
switch (mode) {
case DRM_MODE_DPMS_ON:
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0);
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, 0);
if (ast->tx_chip_types & AST_TX_DP501_BIT)
ast_set_dp501_video_output(crtc->dev, 1);
if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
ast_wait_for_vretrace(ast);
ast_dp_set_on_off(crtc->dev, 1);
}
ast_state = to_ast_crtc_state(crtc->state);
format = ast_state->format;
if (format) {
vbios_mode_info = &ast_state->vbios_mode_info;
ast_set_color_reg(ast, format);
ast_set_vbios_color_reg(ast, format, vbios_mode_info);
if (crtc->state->gamma_lut)
ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
else
ast_crtc_set_gamma_linear(ast, format);
}
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
ch = mode;
if (ast->tx_chip_types & AST_TX_DP501_BIT)
ast_set_dp501_video_output(crtc->dev, 0);
if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
ast_dp_set_on_off(crtc->dev, 0);
ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
}
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0x20);
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, ch);
break;
}
}
static enum drm_mode_status
ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
{
@ -1147,6 +1091,33 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode
return status;
}
static void ast_crtc_helper_mode_set_nofb(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct ast_device *ast = to_ast_device(dev);
struct drm_crtc_state *crtc_state = crtc->state;
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info =
&ast_crtc_state->vbios_mode_info;
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
/*
* Ensure that no scanout takes place before reprogramming mode
* and format registers.
*
* TODO: Get vblank interrupts working and remove this line.
*/
ast_wait_for_vretrace(ast);
ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06);
ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_crtthd_reg(ast);
ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
}
static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@ -1206,7 +1177,6 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct ast_device *ast = to_ast_device(dev);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
/*
* The gamma LUT has to be reloaded after changing the primary
@ -1220,40 +1190,27 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
else
ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
}
//Set Aspeed Display-Port
if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
ast_dp_set_mode(crtc, vbios_mode_info);
}
static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
struct drm_device *dev = crtc->dev;
struct ast_device *ast = to_ast_device(dev);
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info =
&ast_crtc_state->vbios_mode_info;
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
struct ast_device *ast = to_ast_device(crtc->dev);
ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06);
ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
ast_set_crtthd_reg(ast);
ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, 0x00);
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, 0x00);
}
static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
struct drm_device *dev = crtc->dev;
struct ast_device *ast = to_ast_device(dev);
struct ast_device *ast = to_ast_device(crtc->dev);
u8 vgacrb6;
ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, AST_IO_VGASR1_SD);
vgacrb6 = AST_IO_VGACRB6_VSYNC_OFF |
AST_IO_VGACRB6_HSYNC_OFF;
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, vgacrb6);
/*
* HW cursors require the underlying primary plane and CRTC to
@ -1266,16 +1223,11 @@ static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_ato
* simple pageflips on the planes.
*/
drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
/*
* Ensure that no scanout takes place before reprogramming mode
* and format registers.
*/
ast_wait_for_vretrace(ast);
}
static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
.mode_valid = ast_crtc_helper_mode_valid,
.mode_set_nofb = ast_crtc_helper_mode_set_nofb,
.atomic_check = ast_crtc_helper_atomic_check,
.atomic_flush = ast_crtc_helper_atomic_flush,
.atomic_enable = ast_crtc_helper_atomic_enable,
@ -1521,6 +1473,27 @@ static const struct drm_encoder_funcs ast_dp501_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static void ast_dp501_encoder_helper_atomic_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct drm_device *dev = encoder->dev;
ast_set_dp501_video_output(dev, 1);
}
static void ast_dp501_encoder_helper_atomic_disable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct drm_device *dev = encoder->dev;
ast_set_dp501_video_output(dev, 0);
}
static const struct drm_encoder_helper_funcs ast_dp501_encoder_helper_funcs = {
.atomic_enable = ast_dp501_encoder_helper_atomic_enable,
.atomic_disable = ast_dp501_encoder_helper_atomic_disable,
};
/*
* DP501 Connector
*/
@ -1607,6 +1580,8 @@ static int ast_dp501_output_init(struct ast_device *ast)
DRM_MODE_ENCODER_TMDS, NULL);
if (ret)
return ret;
drm_encoder_helper_add(encoder, &ast_dp501_encoder_helper_funcs);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = ast_dp501_connector_init(dev, connector);
@ -1628,6 +1603,43 @@ static const struct drm_encoder_funcs ast_astdp_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_crtc *crtc = crtc_state->crtc;
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
ast_dp_set_mode(crtc, vbios_mode_info);
}
static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct drm_device *dev = encoder->dev;
struct ast_device *ast = to_ast_device(dev);
ast_dp_power_on_off(dev, AST_DP_POWER_ON);
ast_wait_for_vretrace(ast);
ast_dp_set_on_off(dev, 1);
}
static void ast_astdp_encoder_helper_atomic_disable(struct drm_encoder *encoder,
struct drm_atomic_state *state)
{
struct drm_device *dev = encoder->dev;
ast_dp_set_on_off(dev, 0);
ast_dp_power_on_off(dev, AST_DP_POWER_OFF);
}
static const struct drm_encoder_helper_funcs ast_astdp_encoder_helper_funcs = {
.atomic_mode_set = ast_astdp_encoder_helper_atomic_mode_set,
.atomic_enable = ast_astdp_encoder_helper_atomic_enable,
.atomic_disable = ast_astdp_encoder_helper_atomic_disable,
};
/*
* ASPEED Display-Port Connector
*/
@ -1726,6 +1738,8 @@ static int ast_astdp_output_init(struct ast_device *ast)
DRM_MODE_ENCODER_TMDS, NULL);
if (ret)
return ret;
drm_encoder_helper_add(encoder, &ast_astdp_encoder_helper_funcs);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = ast_astdp_connector_init(dev, connector);
@ -1851,7 +1865,7 @@ static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *s
* the I/O-register lock. Released in atomic_flush().
*/
mutex_lock(&ast->modeset_lock);
drm_atomic_helper_commit_tail_rpm(state);
drm_atomic_helper_commit_tail(state);
mutex_unlock(&ast->modeset_lock);
}

View File

@ -22,6 +22,7 @@
#define AST_IO_VGAER_VGA_ENABLE BIT(0)
#define AST_IO_VGASRI (0x44)
#define AST_IO_VGASR1_SD BIT(5)
#define AST_IO_VGADRR (0x47)
#define AST_IO_VGADWR (0x48)
#define AST_IO_VGAPDR (0x49)
@ -31,6 +32,8 @@
#define AST_IO_VGACR80_PASSWORD (0xa8)
#define AST_IO_VGACRA1_VGAIO_DISABLED BIT(1)
#define AST_IO_VGACRA1_MMIO_ENABLED BIT(2)
#define AST_IO_VGACRB6_HSYNC_OFF BIT(0)
#define AST_IO_VGACRB6_VSYNC_OFF BIT(1)
#define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */
#define AST_IO_VGACRCB_HWC_ENABLED BIT(1)
@ -75,13 +78,6 @@
#define ASTDP_HOST_EDID_READ_DONE BIT(0)
#define ASTDP_HOST_EDID_READ_DONE_MASK GENMASK(0, 0)
/*
* CRB8[b1]: Enable VSYNC off
* CRB8[b0]: Enable HSYNC off
*/
#define AST_DPMS_VSYNC_OFF BIT(1)
#define AST_DPMS_HSYNC_OFF BIT(0)
/*
* CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
* Precondition: A. ~AST_DP_PHY_SLEEP &&

View File

@ -35,6 +35,7 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dp_mst_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <drm/drm_panel.h>
@ -4151,9 +4152,9 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
int symbol_cycles;
if (lane_count == 0 || hactive == 0 || bpp_x16 == 0) {
DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, hactive %d, bpp_x16 %d.%04d\n",
DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, hactive %d, bpp_x16 " FXP_Q4_FMT "\n",
lane_count, hactive,
bpp_x16 >> 4, (bpp_x16 & 0xf) * 625);
FXP_Q4_ARGS(bpp_x16));
return 0;
}

View File

@ -2929,7 +2929,7 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
/* FIXME: Actually do some real error handling here */
ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
if (ret <= 0) {
if (ret < 0) {
drm_err(mgr->dev, "Sending link address failed with %d\n", ret);
goto out;
}
@ -2981,7 +2981,7 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
mutex_unlock(&mgr->lock);
out:
if (ret <= 0)
if (ret < 0)
mstb->link_address_sent = false;
kfree(txmsg);
return ret < 0 ? ret : changed;
@ -4069,6 +4069,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
const struct drm_dp_connection_status_notify *conn_stat =
&up_req->msg.u.conn_stat;
bool handle_csn;
drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n",
conn_stat->port_number,
@ -4077,6 +4078,16 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
conn_stat->message_capability_status,
conn_stat->input_port,
conn_stat->peer_device_type);
mutex_lock(&mgr->probe_lock);
handle_csn = mgr->mst_primary->link_address_sent;
mutex_unlock(&mgr->probe_lock);
if (!handle_csn) {
drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
kfree(up_req);
goto out;
}
} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
const struct drm_dp_resource_status_notify *res_stat =
&up_req->msg.u.resource_stat;

View File

@ -14,6 +14,7 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dsc_helper.h>
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
/**
@ -1472,3 +1473,93 @@ u32 drm_dsc_flatness_det_thresh(const struct drm_dsc_config *dsc)
return 2 << (dsc->bits_per_component - 8);
}
EXPORT_SYMBOL(drm_dsc_flatness_det_thresh);
static void drm_dsc_dump_config_main_params(struct drm_printer *p, int indent,
const struct drm_dsc_config *cfg)
{
drm_printf_indent(p, indent,
"dsc-cfg: version: %d.%d, picture: w=%d, h=%d, slice: count=%d, w=%d, h=%d, size=%d\n",
cfg->dsc_version_major, cfg->dsc_version_minor,
cfg->pic_width, cfg->pic_height,
cfg->slice_count, cfg->slice_width, cfg->slice_height, cfg->slice_chunk_size);
drm_printf_indent(p, indent,
"dsc-cfg: mode: block-pred=%s, vbr=%s, rgb=%s, simple-422=%s, native-422=%s, native-420=%s\n",
str_yes_no(cfg->block_pred_enable), str_yes_no(cfg->vbr_enable),
str_yes_no(cfg->convert_rgb),
str_yes_no(cfg->simple_422), str_yes_no(cfg->native_422), str_yes_no(cfg->native_420));
drm_printf_indent(p, indent,
"dsc-cfg: color-depth: uncompressed-bpc=%d, compressed-bpp=" FXP_Q4_FMT " line-buf-bpp=%d\n",
cfg->bits_per_component, FXP_Q4_ARGS(cfg->bits_per_pixel), cfg->line_buf_depth);
drm_printf_indent(p, indent,
"dsc-cfg: rc-model: size=%d, bits=%d, mux-word-size: %d, initial-delays: xmit=%d, dec=%d\n",
cfg->rc_model_size, cfg->rc_bits, cfg->mux_word_size,
cfg->initial_xmit_delay, cfg->initial_dec_delay);
drm_printf_indent(p, indent,
"dsc-cfg: offsets: initial=%d, final=%d, slice-bpg=%d\n",
cfg->initial_offset, cfg->final_offset, cfg->slice_bpg_offset);
drm_printf_indent(p, indent,
"dsc-cfg: line-bpg-offsets: first=%d, non-first=%d, second=%d, non-second=%d, second-adj=%d\n",
cfg->first_line_bpg_offset, cfg->nfl_bpg_offset,
cfg->second_line_bpg_offset, cfg->nsl_bpg_offset, cfg->second_line_offset_adj);
drm_printf_indent(p, indent,
"dsc-cfg: rc-tgt-offsets: low=%d, high=%d, rc-edge-factor: %d, rc-quant-incr-limits: [0]=%d, [1]=%d\n",
cfg->rc_tgt_offset_low, cfg->rc_tgt_offset_high,
cfg->rc_edge_factor, cfg->rc_quant_incr_limit0, cfg->rc_quant_incr_limit1);
drm_printf_indent(p, indent,
"dsc-cfg: initial-scale: %d, scale-intervals: increment=%d, decrement=%d\n",
cfg->initial_scale_value, cfg->scale_increment_interval, cfg->scale_decrement_interval);
drm_printf_indent(p, indent,
"dsc-cfg: flatness: min-qp=%d, max-qp=%d\n",
cfg->flatness_min_qp, cfg->flatness_max_qp);
}
static void drm_dsc_dump_config_rc_params(struct drm_printer *p, int indent,
const struct drm_dsc_config *cfg)
{
const u16 *bt = cfg->rc_buf_thresh;
const struct drm_dsc_rc_range_parameters *rp = cfg->rc_range_params;
BUILD_BUG_ON(ARRAY_SIZE(cfg->rc_buf_thresh) != 14);
BUILD_BUG_ON(ARRAY_SIZE(cfg->rc_range_params) != 15);
drm_printf_indent(p, indent,
"dsc-cfg: rc-level: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14\n");
drm_printf_indent(p, indent,
"dsc-cfg: rc-buf-thresh: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
bt[0], bt[1], bt[2], bt[3], bt[4], bt[5], bt[6], bt[7],
bt[8], bt[9], bt[10], bt[11], bt[12], bt[13]);
drm_printf_indent(p, indent,
"dsc-cfg: rc-min-qp: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
rp[0].range_min_qp, rp[1].range_min_qp, rp[2].range_min_qp, rp[3].range_min_qp,
rp[4].range_min_qp, rp[5].range_min_qp, rp[6].range_min_qp, rp[7].range_min_qp,
rp[8].range_min_qp, rp[9].range_min_qp, rp[10].range_min_qp, rp[11].range_min_qp,
rp[12].range_min_qp, rp[13].range_min_qp, rp[14].range_min_qp);
drm_printf_indent(p, indent,
"dsc-cfg: rc-max-qp: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
rp[0].range_max_qp, rp[1].range_max_qp, rp[2].range_max_qp, rp[3].range_max_qp,
rp[4].range_max_qp, rp[5].range_max_qp, rp[6].range_max_qp, rp[7].range_max_qp,
rp[8].range_max_qp, rp[9].range_max_qp, rp[10].range_max_qp, rp[11].range_max_qp,
rp[12].range_max_qp, rp[13].range_max_qp, rp[14].range_max_qp);
drm_printf_indent(p, indent,
"dsc-cfg: rc-bpg-offset: %3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d\n",
rp[0].range_bpg_offset, rp[1].range_bpg_offset, rp[2].range_bpg_offset, rp[3].range_bpg_offset,
rp[4].range_bpg_offset, rp[5].range_bpg_offset, rp[6].range_bpg_offset, rp[7].range_bpg_offset,
rp[8].range_bpg_offset, rp[9].range_bpg_offset, rp[10].range_bpg_offset, rp[11].range_bpg_offset,
rp[12].range_bpg_offset, rp[13].range_bpg_offset, rp[14].range_bpg_offset);
}
/**
* drm_dsc_dump_config - Dump the provided DSC configuration
* @p: The printer used for output
* @indent: Tab indentation level (max 5)
* @cfg: DSC configuration to print
*
* Print the provided DSC configuration in @cfg.
*/
void drm_dsc_dump_config(struct drm_printer *p, int indent,
const struct drm_dsc_config *cfg)
{
drm_dsc_dump_config_main_params(p, indent, cfg);
drm_dsc_dump_config_rc_params(p, indent, cfg);
}
EXPORT_SYMBOL(drm_dsc_dump_config);

View File

@ -197,7 +197,7 @@ void drmm_release_action(struct drm_device *dev,
spin_lock_irqsave(&dev->managed.lock, flags);
list_for_each_entry_reverse(dr, &dev->managed.resources, node.entry) {
if (dr->node.release == action) {
if (!data || (data && *(void **)dr->data == data)) {
if (!data || *(void **)dr->data == data) {
dr_match = dr;
del_dr(dev, dr_match);
break;

View File

@ -501,3 +501,4 @@ module_platform_driver(lima_platform_driver);
MODULE_AUTHOR("Lima Project Developers");
MODULE_DESCRIPTION("Lima DRM Driver");
MODULE_LICENSE("GPL v2");
MODULE_SOFTDEP("pre: governor_simpleondemand");

View File

@ -111,12 +111,12 @@ static inline void mga_wait_vsync(struct mga_device *mdev)
unsigned int status = 0;
do {
status = RREG32(MGAREG_Status);
status = RREG32(MGAREG_STATUS);
} while ((status & 0x08) && time_before(jiffies, timeout));
timeout = jiffies + HZ/10;
status = 0;
do {
status = RREG32(MGAREG_Status);
status = RREG32(MGAREG_STATUS);
} while (!(status & 0x08) && time_before(jiffies, timeout));
}
@ -125,7 +125,7 @@ static inline void mga_wait_busy(struct mga_device *mdev)
unsigned long timeout = jiffies + HZ;
unsigned int status = 0;
do {
status = RREG8(MGAREG_Status + 2);
status = RREG8(MGAREG_STATUS + 2);
} while ((status & 0x01) && time_before(jiffies, timeout));
}

View File

@ -102,7 +102,7 @@
#define MGAREG_EXEC 0x0100
#define MGAREG_FIFOSTATUS 0x1e10
#define MGAREG_Status 0x1e14
#define MGAREG_STATUS 0x1e14
#define MGAREG_CACHEFLUSH 0x1fff
#define MGAREG_ICLEAR 0x1e18
#define MGAREG_IEN 0x1e1c

File diff suppressed because it is too large Load Diff

View File

@ -1067,6 +1067,30 @@ static const struct panel_desc auo_g104sn02 = {
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct drm_display_mode auo_g104stn01_mode = {
.clock = 40000,
.hdisplay = 800,
.hsync_start = 800 + 40,
.hsync_end = 800 + 40 + 88,
.htotal = 800 + 40 + 88 + 128,
.vdisplay = 600,
.vsync_start = 600 + 1,
.vsync_end = 600 + 1 + 23,
.vtotal = 600 + 1 + 23 + 4,
};
static const struct panel_desc auo_g104stn01 = {
.modes = &auo_g104stn01_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 211,
.height = 158,
},
.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
.connector_type = DRM_MODE_CONNECTOR_LVDS,
};
static const struct display_timing auo_g121ean01_timing = {
.pixelclock = { 60000000, 74400000, 90000000 },
.hactive = { 1280, 1280, 1280 },
@ -4534,6 +4558,9 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "auo,g104sn02",
.data = &auo_g104sn02,
}, {
.compatible = "auo,g104stn01",
.data = &auo_g104stn01,
}, {
.compatible = "auo,g121ean01",
.data = &auo_g121ean01,

View File

@ -838,3 +838,4 @@ module_platform_driver(panfrost_driver);
MODULE_AUTHOR("Panfrost Project Developers");
MODULE_DESCRIPTION("Panfrost DRM Driver");
MODULE_LICENSE("GPL v2");
MODULE_SOFTDEP("pre: governor_simpleondemand");

View File

@ -2926,6 +2926,7 @@ queue_run_job(struct drm_sched_job *sched_job)
pm_runtime_get(ptdev->base.dev);
sched->pm.has_ref = true;
}
panthor_devfreq_record_busy(sched->ptdev);
}
done_fence = dma_fence_get(job->done_fence);

View File

@ -20,3 +20,14 @@ config DRM_STM_DSI
select DRM_DW_MIPI_DSI
help
Choose this option for MIPI DSI support on STMicroelectronics SoC.
config DRM_STM_LVDS
tristate "STMicroelectronics LVDS Display Interface Transmitter DRM driver"
depends on DRM_STM
help
Enable support for LVDS encoders on STMicroelectronics SoC.
The STM LVDS is a bridge which serialize pixel stream onto
a LVDS protocol.
To compile this driver as a module, choose M here: the module will be
called lvds.

View File

@ -5,4 +5,6 @@ stm-drm-y := \
obj-$(CONFIG_DRM_STM_DSI) += dw_mipi_dsi-stm.o
obj-$(CONFIG_DRM_STM_LVDS) += lvds.o
obj-$(CONFIG_DRM_STM) += stm-drm.o

View File

@ -7,10 +7,13 @@
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
@ -76,8 +79,12 @@ enum dsi_color {
struct dw_mipi_dsi_stm {
void __iomem *base;
struct device *dev;
struct clk *pllref_clk;
struct clk *pclk;
struct clk_hw txbyte_clk;
struct dw_mipi_dsi *dsi;
struct dw_mipi_dsi_plat_data pdata;
u32 hw_version;
int lane_min_kbps;
int lane_max_kbps;
@ -194,29 +201,198 @@ static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,
return 0;
}
static int dw_mipi_dsi_phy_init(void *priv_data)
#define clk_to_dw_mipi_dsi_stm(clk) \
container_of(clk, struct dw_mipi_dsi_stm, txbyte_clk)
static void dw_mipi_dsi_clk_disable(struct clk_hw *clk)
{
struct dw_mipi_dsi_stm *dsi = priv_data;
struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);
DRM_DEBUG_DRIVER("\n");
/* Disable the DSI PLL */
dsi_clear(dsi, DSI_WRPCR, WRPCR_PLLEN);
/* Disable the regulator */
dsi_clear(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);
}
static int dw_mipi_dsi_clk_enable(struct clk_hw *clk)
{
struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(clk);
u32 val;
int ret;
DRM_DEBUG_DRIVER("\n");
/* Enable the regulator */
dsi_set(dsi, DSI_WRPCR, WRPCR_REGEN | WRPCR_BGREN);
ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_RRS,
SLEEP_US, TIMEOUT_US);
ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_RRS,
SLEEP_US, TIMEOUT_US);
if (ret)
DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");
/* Enable the DSI PLL & wait for its lock */
dsi_set(dsi, DSI_WRPCR, WRPCR_PLLEN);
ret = readl_poll_timeout(dsi->base + DSI_WISR, val, val & WISR_PLLLS,
SLEEP_US, TIMEOUT_US);
ret = readl_poll_timeout_atomic(dsi->base + DSI_WISR, val, val & WISR_PLLLS,
SLEEP_US, TIMEOUT_US);
if (ret)
DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");
return 0;
}
static int dw_mipi_dsi_clk_is_enabled(struct clk_hw *hw)
{
struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
return dsi_read(dsi, DSI_WRPCR) & WRPCR_PLLEN;
}
static unsigned long dw_mipi_dsi_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
u32 val;
DRM_DEBUG_DRIVER("\n");
pll_in_khz = (unsigned int)(parent_rate / 1000);
val = dsi_read(dsi, DSI_WRPCR);
idf = (val & WRPCR_IDF) >> 11;
if (!idf)
idf = 1;
ndiv = (val & WRPCR_NDIV) >> 2;
odf = int_pow(2, (val & WRPCR_ODF) >> 16);
/* Get the adjusted pll out value */
pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
return (unsigned long)pll_out_khz * 1000;
}
static long dw_mipi_dsi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
int ret;
DRM_DEBUG_DRIVER("\n");
pll_in_khz = (unsigned int)(*parent_rate / 1000);
/* Compute best pll parameters */
idf = 0;
ndiv = 0;
odf = 0;
ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000,
&idf, &ndiv, &odf);
if (ret)
DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
/* Get the adjusted pll out value */
pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
return pll_out_khz * 1000;
}
static int dw_mipi_dsi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct dw_mipi_dsi_stm *dsi = clk_to_dw_mipi_dsi_stm(hw);
unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
int ret;
u32 val;
DRM_DEBUG_DRIVER("\n");
pll_in_khz = (unsigned int)(parent_rate / 1000);
/* Compute best pll parameters */
idf = 0;
ndiv = 0;
odf = 0;
ret = dsi_pll_get_params(dsi, pll_in_khz, rate / 1000, &idf, &ndiv, &odf);
if (ret)
DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
/* Get the adjusted pll out value */
pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
/* Set the PLL division factors */
dsi_update_bits(dsi, DSI_WRPCR, WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,
(ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));
/* Compute uix4 & set the bit period in high-speed mode */
val = 4000000 / pll_out_khz;
dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);
return 0;
}
static void dw_mipi_dsi_clk_unregister(void *data)
{
struct dw_mipi_dsi_stm *dsi = data;
DRM_DEBUG_DRIVER("\n");
of_clk_del_provider(dsi->dev->of_node);
clk_hw_unregister(&dsi->txbyte_clk);
}
static const struct clk_ops dw_mipi_dsi_stm_clk_ops = {
.enable = dw_mipi_dsi_clk_enable,
.disable = dw_mipi_dsi_clk_disable,
.is_enabled = dw_mipi_dsi_clk_is_enabled,
.recalc_rate = dw_mipi_dsi_clk_recalc_rate,
.round_rate = dw_mipi_dsi_clk_round_rate,
.set_rate = dw_mipi_dsi_clk_set_rate,
};
static struct clk_init_data cdata_init = {
.name = "ck_dsi_phy",
.ops = &dw_mipi_dsi_stm_clk_ops,
.parent_names = (const char * []) {"ck_hse"},
.num_parents = 1,
};
static int dw_mipi_dsi_clk_register(struct dw_mipi_dsi_stm *dsi,
struct device *dev)
{
struct device_node *node = dev->of_node;
int ret;
DRM_DEBUG_DRIVER("Registering clk\n");
dsi->txbyte_clk.init = &cdata_init;
ret = clk_hw_register(dev, &dsi->txbyte_clk);
if (ret)
return ret;
ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get,
&dsi->txbyte_clk);
if (ret)
clk_hw_unregister(&dsi->txbyte_clk);
return ret;
}
static int dw_mipi_dsi_phy_init(void *priv_data)
{
struct dw_mipi_dsi_stm *dsi = priv_data;
int ret;
ret = clk_prepare_enable(dsi->txbyte_clk.clk);
return ret;
}
static void dw_mipi_dsi_phy_power_on(void *priv_data)
{
struct dw_mipi_dsi_stm *dsi = priv_data;
@ -233,6 +409,8 @@ static void dw_mipi_dsi_phy_power_off(void *priv_data)
DRM_DEBUG_DRIVER("\n");
clk_disable_unprepare(dsi->txbyte_clk.clk);
/* Disable the DSI wrapper */
dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
}
@ -243,9 +421,8 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
unsigned int *lane_mbps)
{
struct dw_mipi_dsi_stm *dsi = priv_data;
unsigned int idf, ndiv, odf, pll_in_khz, pll_out_khz;
unsigned int pll_in_khz, pll_out_khz;
int ret, bpp;
u32 val;
pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
@ -266,25 +443,10 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
DRM_WARN("Warning min phy mbps is used\n");
}
/* Compute best pll parameters */
idf = 0;
ndiv = 0;
odf = 0;
ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
&idf, &ndiv, &odf);
ret = clk_set_rate((dsi->txbyte_clk.clk), pll_out_khz * 1000);
if (ret)
DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
/* Get the adjusted pll out value */
pll_out_khz = dsi_pll_get_clkout_khz(pll_in_khz, idf, ndiv, odf);
/* Set the PLL division factors */
dsi_update_bits(dsi, DSI_WRPCR, WRPCR_NDIV | WRPCR_IDF | WRPCR_ODF,
(ndiv << 2) | (idf << 11) | ((ffs(odf) - 1) << 16));
/* Compute uix4 & set the bit period in high-speed mode */
val = 4000000 / pll_out_khz;
dsi_update_bits(dsi, DSI_WPCR0, WPCR0_UIX4, val);
DRM_DEBUG_DRIVER("ERROR Could not set rate of %d to %s clk->name",
pll_out_khz, clk_hw_get_name(&dsi->txbyte_clk));
/* Select video mode by resetting DSIM bit */
dsi_clear(dsi, DSI_WCFGR, WCFGR_DSIM);
@ -443,7 +605,7 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_mipi_dsi_stm *dsi;
struct clk *pclk;
const struct dw_mipi_dsi_plat_data *pdata = of_device_get_match_data(dev);
int ret;
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
@ -483,21 +645,21 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
goto err_clk_get;
}
pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(pclk)) {
ret = PTR_ERR(pclk);
dsi->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(dsi->pclk)) {
ret = PTR_ERR(dsi->pclk);
DRM_ERROR("Unable to get peripheral clock: %d\n", ret);
goto err_dsi_probe;
}
ret = clk_prepare_enable(pclk);
ret = clk_prepare_enable(dsi->pclk);
if (ret) {
DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);
goto err_dsi_probe;
}
dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
clk_disable_unprepare(pclk);
clk_disable_unprepare(dsi->pclk);
if (dsi->hw_version != HWVER_130 && dsi->hw_version != HWVER_131) {
ret = -ENODEV;
@ -513,18 +675,41 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
dsi->lane_max_kbps *= 2;
}
dw_mipi_dsi_stm_plat_data.base = dsi->base;
dw_mipi_dsi_stm_plat_data.priv_data = dsi;
dsi->pdata = *pdata;
dsi->pdata.base = dsi->base;
dsi->pdata.priv_data = dsi;
dsi->pdata.max_data_lanes = 2;
dsi->pdata.phy_ops = &dw_mipi_dsi_stm_phy_ops;
platform_set_drvdata(pdev, dsi);
dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data);
dsi->dsi = dw_mipi_dsi_probe(pdev, &dsi->pdata);
if (IS_ERR(dsi->dsi)) {
ret = PTR_ERR(dsi->dsi);
dev_err_probe(dev, ret, "Failed to initialize mipi dsi host\n");
goto err_dsi_probe;
}
/*
* We need to wait for the generic bridge to probe before enabling and
* register the internal pixel clock.
*/
ret = clk_prepare_enable(dsi->pclk);
if (ret) {
DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__);
goto err_dsi_probe;
}
ret = dw_mipi_dsi_clk_register(dsi, dev);
if (ret) {
DRM_ERROR("Failed to register DSI pixel clock: %d\n", ret);
clk_disable_unprepare(dsi->pclk);
goto err_dsi_probe;
}
clk_disable_unprepare(dsi->pclk);
return 0;
err_dsi_probe:
@ -541,24 +726,26 @@ static void dw_mipi_dsi_stm_remove(struct platform_device *pdev)
dw_mipi_dsi_remove(dsi->dsi);
clk_disable_unprepare(dsi->pllref_clk);
dw_mipi_dsi_clk_unregister(dsi);
regulator_disable(dsi->vdd_supply);
}
static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev)
static int dw_mipi_dsi_stm_suspend(struct device *dev)
{
struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);
DRM_DEBUG_DRIVER("\n");
clk_disable_unprepare(dsi->pllref_clk);
clk_disable_unprepare(dsi->pclk);
regulator_disable(dsi->vdd_supply);
return 0;
}
static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
static int dw_mipi_dsi_stm_resume(struct device *dev)
{
struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data;
struct dw_mipi_dsi_stm *dsi = dev_get_drvdata(dev);
int ret;
DRM_DEBUG_DRIVER("\n");
@ -569,8 +756,16 @@ static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
return ret;
}
ret = clk_prepare_enable(dsi->pclk);
if (ret) {
regulator_disable(dsi->vdd_supply);
DRM_ERROR("Failed to enable pclk: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(dsi->pllref_clk);
if (ret) {
clk_disable_unprepare(dsi->pclk);
regulator_disable(dsi->vdd_supply);
DRM_ERROR("Failed to enable pllref_clk: %d\n", ret);
return ret;
@ -580,8 +775,10 @@ static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev)
}
static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,
dw_mipi_dsi_stm_resume)
SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend,
dw_mipi_dsi_stm_resume)
RUNTIME_PM_OPS(dw_mipi_dsi_stm_suspend,
dw_mipi_dsi_stm_resume, NULL)
};
static struct platform_driver dw_mipi_dsi_stm_driver = {

1226
drivers/gpu/drm/stm/lvds.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -992,6 +992,17 @@ static const struct drm_cmdline_tv_option_test drm_cmdline_tv_option_tests[] = {
TV_OPT_TEST(PAL_M, "720x480i,tv_mode=PAL-M", drm_mode_analog_ntsc_480i),
TV_OPT_TEST(PAL_N, "720x576i,tv_mode=PAL-N", drm_mode_analog_pal_576i),
TV_OPT_TEST(SECAM, "720x576i,tv_mode=SECAM", drm_mode_analog_pal_576i),
{
.name = "MONO_525",
.cmdline = "720x480i,tv_mode=Mono",
.mode_fn = drm_mode_analog_ntsc_480i,
.tv_mode = DRM_MODE_TV_MODE_MONOCHROME,
}, {
.name = "MONO_625",
.cmdline = "720x576i,tv_mode=Mono",
.mode_fn = drm_mode_analog_pal_576i,
.tv_mode = DRM_MODE_TV_MODE_MONOCHROME,
},
};
static void drm_cmdline_tv_option_desc(const struct drm_cmdline_tv_option_test *t,

View File

@ -777,6 +777,7 @@ struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] =
TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
TV_MODE_NAME("Mono", DRM_MODE_TV_MODE_MONOCHROME),
};
static void

View File

@ -130,7 +130,38 @@ static void drm_test_modes_analog_tv_pal_576i_inlined(struct kunit *test)
KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode));
}
static void drm_test_modes_analog_tv_mono_576i(struct kunit *test)
{
struct drm_test_modes_priv *priv = test->priv;
struct drm_display_mode *mode;
mode = drm_analog_tv_mode(priv->drm,
DRM_MODE_TV_MODE_MONOCHROME,
13500 * HZ_PER_KHZ, 720, 576,
true);
KUNIT_ASSERT_NOT_NULL(test, mode);
KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 50);
KUNIT_EXPECT_EQ(test, mode->hdisplay, 720);
/* BT.601 defines hsync_start at 732 for 576i */
KUNIT_EXPECT_EQ(test, mode->hsync_start, 732);
/*
* The PAL standard expects a line to take 64us. With a pixel
* clock of 13.5 MHz, a pixel takes around 74ns, so we need to
* have 64000ns / 74ns = 864.
*
* This is also mandated by BT.601.
*/
KUNIT_EXPECT_EQ(test, mode->htotal, 864);
KUNIT_EXPECT_EQ(test, mode->vdisplay, 576);
KUNIT_EXPECT_EQ(test, mode->vtotal, 625);
}
static struct kunit_case drm_modes_analog_tv_tests[] = {
KUNIT_CASE(drm_test_modes_analog_tv_mono_576i),
KUNIT_CASE(drm_test_modes_analog_tv_ntsc_480i),
KUNIT_CASE(drm_test_modes_analog_tv_ntsc_480i_inlined),
KUNIT_CASE(drm_test_modes_analog_tv_pal_576i),

View File

@ -17,6 +17,8 @@ enum drm_dsc_params_type {
DRM_DSC_1_2_420,
};
struct drm_printer;
void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size);
void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
@ -28,6 +30,7 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);
u8 drm_dsc_initial_scale_value(const struct drm_dsc_config *dsc);
u32 drm_dsc_flatness_det_thresh(const struct drm_dsc_config *dsc);
u32 drm_dsc_get_bpp_int(const struct drm_dsc_config *vdsc_cfg);
void drm_dsc_dump_config(struct drm_printer *p, int indent, const struct drm_dsc_config *cfg);
#endif /* _DRM_DSC_HELPER_H_ */

View File

@ -214,4 +214,27 @@ static inline s64 drm_fixp_exp(s64 x)
return sum;
}
static inline int fxp_q4_from_int(int val_int)
{
return val_int << 4;
}
static inline int fxp_q4_to_int(int val_q4)
{
return val_q4 >> 4;
}
static inline int fxp_q4_to_int_roundup(int val_q4)
{
return (val_q4 + 0xf) >> 4;
}
static inline int fxp_q4_to_frac(int val_q4)
{
return val_q4 & 0xf;
}
#define FXP_Q4_FMT "%d.%04d"
#define FXP_Q4_ARGS(val_q4) fxp_q4_to_int(val_q4), (fxp_q4_to_frac(val_q4) * 625)
#endif