mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-07 13:43:51 +00:00
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:
commit
d076e2bd09
@ -17,6 +17,7 @@ properties:
|
||||
items:
|
||||
- enum:
|
||||
- chongzhou,cz101b4001
|
||||
- kingdisplay,kd101ne3-40ti
|
||||
- radxa,display-10hd-ad001
|
||||
- radxa,display-8hd-ad002
|
||||
- const: jadard,jd9365da-h3
|
||||
|
@ -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
|
||||
|
119
Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml
Normal file
119
Documentation/devicetree/bindings/display/st,stm32mp25-lvds.yaml
Normal 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 = <<dc_ep1_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds_out0: endpoint {
|
||||
remote-endpoint = <&lvds_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
1226
drivers/gpu/drm/stm/lvds.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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_ */
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user